summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
Diffstat (limited to 'httemplate')
-rwxr-xr-xhttemplate/.htaccess3
-rw-r--r--httemplate/autohandler44
-rw-r--r--httemplate/browse/access_group.html106
-rw-r--r--httemplate/browse/access_user.html61
-rw-r--r--httemplate/browse/addr_block.cgi145
-rwxr-xr-xhttemplate/browse/agent.cgi422
-rwxr-xr-xhttemplate/browse/agent_type.cgi61
-rwxr-xr-xhttemplate/browse/cust_main_county.cgi454
-rw-r--r--httemplate/browse/elements/browse.html6
-rw-r--r--httemplate/browse/inventory_class.html93
-rw-r--r--httemplate/browse/invoice_template.html124
-rwxr-xr-xhttemplate/browse/msgcat.cgi44
-rwxr-xr-xhttemplate/browse/nas.cgi82
-rwxr-xr-xhttemplate/browse/part_bill_event.cgi122
-rw-r--r--httemplate/browse/part_event.html167
-rwxr-xr-xhttemplate/browse/part_export.cgi65
-rwxr-xr-xhttemplate/browse/part_pkg.cgi367
-rwxr-xr-xhttemplate/browse/part_pkg_taxproduct.cgi263
-rwxr-xr-xhttemplate/browse/part_referral.html181
-rwxr-xr-xhttemplate/browse/part_svc.cgi215
-rw-r--r--httemplate/browse/part_virtual_field.cgi42
-rw-r--r--httemplate/browse/payment_gateway.html94
-rw-r--r--httemplate/browse/pkg_category.html33
-rw-r--r--httemplate/browse/pkg_class.html46
-rw-r--r--httemplate/browse/rate.cgi64
-rw-r--r--httemplate/browse/rate_detail.html92
-rw-r--r--httemplate/browse/rate_region.html91
-rw-r--r--httemplate/browse/reason.html53
-rw-r--r--httemplate/browse/reason_type.html68
-rw-r--r--httemplate/browse/router.cgi52
-rwxr-xr-xhttemplate/browse/svc_acct_pop.cgi77
-rwxr-xr-xhttemplate/browse/tax_class.html92
-rwxr-xr-xhttemplate/browse/tax_rate.cgi348
-rw-r--r--httemplate/browse/usage_class.html28
-rw-r--r--httemplate/config/config-delete.cgi15
-rw-r--r--httemplate/config/config-download.cgi28
-rw-r--r--httemplate/config/config-image.cgi19
-rw-r--r--httemplate/config/config-process.cgi105
-rw-r--r--httemplate/config/config-view.cgi177
-rw-r--r--httemplate/config/config.cgi331
-rw-r--r--httemplate/docs/AGPL.html672
-rw-r--r--httemplate/docs/about.html53
-rw-r--r--httemplate/docs/ach.html10
-rwxr-xr-xhttemplate/docs/admin.html41
-rw-r--r--httemplate/docs/credits.html175
-rw-r--r--httemplate/docs/cvv2.html24
-rw-r--r--httemplate/docs/ieak.html75
-rw-r--r--httemplate/docs/index.html32
-rwxr-xr-xhttemplate/docs/legacy.html39
-rw-r--r--httemplate/docs/license.html116
-rw-r--r--httemplate/docs/man/FS/part_export/.cvs_is_on_crack0
-rw-r--r--httemplate/docs/overview-new.diabin0 -> 2422 bytes
-rw-r--r--httemplate/docs/overview-new.pngbin0 -> 29062 bytes
-rw-r--r--httemplate/docs/overview.diabin0 -> 2800 bytes
-rw-r--r--httemplate/docs/overview.pngbin0 -> 13064 bytes
-rwxr-xr-xhttemplate/docs/passwd.html23
-rw-r--r--httemplate/docs/schema.diabin0 -> 16364 bytes
-rw-r--r--httemplate/docs/schema.html533
-rw-r--r--httemplate/docs/schema.pngbin0 -> 681043 bytes
-rw-r--r--httemplate/docs/session.html59
-rw-r--r--httemplate/docs/signup.html54
-rwxr-xr-xhttemplate/docs/ssh.html16
-rwxr-xr-xhttemplate/edit/REAL_cust_pkg.cgi186
-rw-r--r--httemplate/edit/access_group.html80
-rw-r--r--httemplate/edit/access_user.html50
-rwxr-xr-xhttemplate/edit/agent.cgi123
-rw-r--r--httemplate/edit/agent_payment_gateway.html68
-rwxr-xr-xhttemplate/edit/agent_type.cgi57
-rw-r--r--httemplate/edit/allocate.html33
-rw-r--r--httemplate/edit/bulk-cust_main_county.html130
-rw-r--r--httemplate/edit/bulk-cust_svc.html95
-rwxr-xr-xhttemplate/edit/cust_bill_pay.cgi14
-rwxr-xr-xhttemplate/edit/cust_credit.cgi68
-rwxr-xr-xhttemplate/edit/cust_credit_bill.cgi14
-rwxr-xr-xhttemplate/edit/cust_credit_refund.cgi14
-rwxr-xr-xhttemplate/edit/cust_main.cgi780
-rw-r--r--httemplate/edit/cust_main/billing.html484
-rw-r--r--httemplate/edit/cust_main/choose_tax_location.html85
-rw-r--r--httemplate/edit/cust_main/contact.html137
-rw-r--r--httemplate/edit/cust_main/select-domain.html67
-rwxr-xr-xhttemplate/edit/cust_main_county-expand.cgi50
-rw-r--r--httemplate/edit/cust_main_county.html62
-rwxr-xr-xhttemplate/edit/cust_main_note.cgi45
-rwxr-xr-xhttemplate/edit/cust_pay.cgi138
-rw-r--r--httemplate/edit/cust_pay_pending.html154
-rwxr-xr-xhttemplate/edit/cust_pay_refund.cgi14
-rwxr-xr-xhttemplate/edit/cust_pkg.cgi150
-rw-r--r--httemplate/edit/cust_pkg_detail.html142
-rwxr-xr-xhttemplate/edit/cust_refund.cgi165
-rw-r--r--httemplate/edit/elements/ApplicationCommon.html177
-rw-r--r--httemplate/edit/elements/edit.html700
-rw-r--r--httemplate/edit/elements/svc_Common.html122
-rw-r--r--httemplate/edit/inventory_class.html16
-rw-r--r--httemplate/edit/invoice_logo.html136
-rw-r--r--httemplate/edit/invoice_template.html69
-rwxr-xr-xhttemplate/edit/msgcat.cgi54
-rwxr-xr-xhttemplate/edit/part_bill_event.cgi570
-rw-r--r--httemplate/edit/part_event.html679
-rw-r--r--httemplate/edit/part_export.cgi123
-rwxr-xr-xhttemplate/edit/part_pkg.cgi637
-rw-r--r--httemplate/edit/part_pkg_taxclass.html32
-rw-r--r--httemplate/edit/part_pkg_taxoverride.html132
-rwxr-xr-xhttemplate/edit/part_referral.html19
-rwxr-xr-xhttemplate/edit/part_svc.cgi361
-rw-r--r--httemplate/edit/part_virtual_field.cgi104
-rw-r--r--httemplate/edit/payment_gateway.html132
-rw-r--r--httemplate/edit/pkg_category.html22
-rw-r--r--httemplate/edit/pkg_class.html28
-rw-r--r--httemplate/edit/prepay_credit.cgi110
-rwxr-xr-xhttemplate/edit/process/REAL_cust_pkg.cgi36
-rw-r--r--httemplate/edit/process/access_group.html28
-rw-r--r--httemplate/edit/process/access_user.html21
-rwxr-xr-xhttemplate/edit/process/addr_block/add.cgi20
-rwxr-xr-xhttemplate/edit/process/addr_block/allocate.cgi16
-rwxr-xr-xhttemplate/edit/process/addr_block/deallocate.cgi20
-rwxr-xr-xhttemplate/edit/process/addr_block/manual_flag.cgi30
-rwxr-xr-xhttemplate/edit/process/addr_block/split.cgi27
-rwxr-xr-xhttemplate/edit/process/agent.cgi16
-rw-r--r--httemplate/edit/process/agent_payment_gateway.html29
-rwxr-xr-xhttemplate/edit/process/agent_type.cgi35
-rw-r--r--httemplate/edit/process/bulk-cust_main_county.html63
-rw-r--r--httemplate/edit/process/bulk-cust_svc.cgi9
-rw-r--r--httemplate/edit/process/change-cust_pkg.html46
-rwxr-xr-xhttemplate/edit/process/cust_bill_pay.cgi13
-rwxr-xr-xhttemplate/edit/process/cust_credit.cgi63
-rwxr-xr-xhttemplate/edit/process/cust_credit_bill.cgi13
-rwxr-xr-xhttemplate/edit/process/cust_credit_refund.cgi13
-rwxr-xr-xhttemplate/edit/process/cust_main.cgi210
-rwxr-xr-xhttemplate/edit/process/cust_main_county-collapse.cgi44
-rwxr-xr-xhttemplate/edit/process/cust_main_county-expand.cgi78
-rw-r--r--httemplate/edit/process/cust_main_county.html13
-rwxr-xr-xhttemplate/edit/process/cust_main_note.cgi54
-rwxr-xr-xhttemplate/edit/process/cust_pay.cgi55
-rw-r--r--httemplate/edit/process/cust_pay_pending.html68
-rwxr-xr-xhttemplate/edit/process/cust_pay_refund.cgi13
-rwxr-xr-xhttemplate/edit/process/cust_pkg.cgi42
-rw-r--r--httemplate/edit/process/cust_pkg_detail.html59
-rwxr-xr-xhttemplate/edit/process/cust_refund.cgi56
-rw-r--r--httemplate/edit/process/cust_svc.cgi30
-rwxr-xr-xhttemplate/edit/process/domain_record.cgi30
-rw-r--r--httemplate/edit/process/elements/ApplicationCommon.html77
-rw-r--r--httemplate/edit/process/elements/process.html268
-rw-r--r--httemplate/edit/process/elements/svc_Common.html15
-rw-r--r--httemplate/edit/process/generic.cgi77
-rw-r--r--httemplate/edit/process/inventory_class.html11
-rw-r--r--httemplate/edit/process/invoice_logo.html25
-rw-r--r--httemplate/edit/process/invoice_template.html15
-rw-r--r--httemplate/edit/process/msgcat.cgi22
-rwxr-xr-xhttemplate/edit/process/part_bill_event.cgi106
-rw-r--r--httemplate/edit/process/part_event.html86
-rw-r--r--httemplate/edit/process/part_export.cgi41
-rwxr-xr-xhttemplate/edit/process/part_pkg.cgi198
-rw-r--r--httemplate/edit/process/part_pkg_taxclass.html53
-rwxr-xr-xhttemplate/edit/process/part_referral.html12
-rwxr-xr-xhttemplate/edit/process/part_svc.cgi9
-rw-r--r--httemplate/edit/process/payment_gateway.html35
-rw-r--r--httemplate/edit/process/pkg_category.html11
-rw-r--r--httemplate/edit/process/pkg_class.html11
-rw-r--r--httemplate/edit/process/prepay_credit.cgi62
-rw-r--r--httemplate/edit/process/quick-charge.cgi68
-rw-r--r--httemplate/edit/process/quick-cust_pkg.cgi63
-rwxr-xr-xhttemplate/edit/process/rate.cgi9
-rw-r--r--httemplate/edit/process/rate_detail.html13
-rwxr-xr-xhttemplate/edit/process/rate_region.cgi57
-rw-r--r--httemplate/edit/process/reason.html12
-rw-r--r--httemplate/edit/process/reason_type.html12
-rw-r--r--httemplate/edit/process/reg_code.cgi45
-rw-r--r--httemplate/edit/process/router.cgi20
-rw-r--r--httemplate/edit/process/svc_Common.html16
-rwxr-xr-xhttemplate/edit/process/svc_acct.cgi64
-rwxr-xr-xhttemplate/edit/process/svc_acct_pop.cgi33
-rw-r--r--httemplate/edit/process/svc_broadband.cgi8
-rwxr-xr-xhttemplate/edit/process/svc_domain.cgi33
-rwxr-xr-xhttemplate/edit/process/svc_external.cgi31
-rwxr-xr-xhttemplate/edit/process/svc_forward.cgi31
-rw-r--r--httemplate/edit/process/svc_phone.html10
-rw-r--r--httemplate/edit/process/svc_www.cgi38
-rw-r--r--httemplate/edit/process/tax_class.html49
-rw-r--r--httemplate/edit/process/tax_rate.html22
-rw-r--r--httemplate/edit/process/usage_class.html11
-rw-r--r--httemplate/edit/quick-charge.html197
-rw-r--r--httemplate/edit/rate.cgi43
-rw-r--r--httemplate/edit/rate_detail.html63
-rw-r--r--httemplate/edit/rate_region.cgi163
-rw-r--r--httemplate/edit/reason.html50
-rw-r--r--httemplate/edit/reason_type.html29
-rw-r--r--httemplate/edit/reg_code.cgi44
-rwxr-xr-xhttemplate/edit/router.cgi44
-rw-r--r--httemplate/edit/svc_Common.html33
-rwxr-xr-xhttemplate/edit/svc_acct.cgi452
-rwxr-xr-xhttemplate/edit/svc_acct_pop.cgi53
-rw-r--r--httemplate/edit/svc_broadband.cgi105
-rwxr-xr-xhttemplate/edit/svc_domain.cgi91
-rw-r--r--httemplate/edit/svc_external.cgi102
-rwxr-xr-xhttemplate/edit/svc_forward.cgi175
-rw-r--r--httemplate/edit/svc_phone.cgi27
-rw-r--r--httemplate/edit/svc_www.cgi240
-rw-r--r--httemplate/edit/tax_class.html36
-rw-r--r--httemplate/edit/tax_rate.html106
-rw-r--r--httemplate/edit/usage_class.html25
-rw-r--r--httemplate/elements/ajaxcontentmws.js185
-rw-r--r--httemplate/elements/calendar-en.js127
-rw-r--r--httemplate/elements/calendar-setup.js200
-rw-r--r--httemplate/elements/calendar-win2k-2.css271
-rw-r--r--httemplate/elements/calendar.js1806
-rw-r--r--httemplate/elements/calendar_stripped.js14
-rw-r--r--httemplate/elements/checkboxes-table-name.html90
-rw-r--r--httemplate/elements/checkboxes-table.html129
-rw-r--r--httemplate/elements/checkboxes.html103
-rw-r--r--httemplate/elements/columnend.html6
-rw-r--r--httemplate/elements/columnnext.html4
-rw-r--r--httemplate/elements/columnstart.html6
-rw-r--r--httemplate/elements/cssexpr.js66
-rw-r--r--httemplate/elements/customer-table.html524
-rw-r--r--httemplate/elements/dashboard-toplist.html113
-rw-r--r--httemplate/elements/error.html4
-rw-r--r--httemplate/elements/errorpage.html11
-rw-r--r--httemplate/elements/fckeditor/editor/css/behaviors/disablehandles.htc15
-rw-r--r--httemplate/elements/fckeditor/editor/css/behaviors/showtableborders.htc36
-rw-r--r--httemplate/elements/fckeditor/editor/css/fck_editorarea.css91
-rw-r--r--httemplate/elements/fckeditor/editor/css/fck_internal.css111
-rw-r--r--httemplate/elements/fckeditor/editor/css/fck_showtableborders_gecko.css42
-rw-r--r--httemplate/elements/fckeditor/editor/css/images/fck_anchor.gifbin0 -> 184 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/css/images/fck_flashlogo.gifbin0 -> 599 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/css/images/fck_hiddenfield.gifbin0 -> 105 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/css/images/fck_pagebreak.gifbin0 -> 54 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.css83
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.js154
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/fcknumericfield.htc24
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/images/locked.gifbin0 -> 74 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/images/reset.gifbin0 -> 104 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/images/unlocked.gifbin0 -> 75 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/common/moz-bindings.xml30
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_about.html155
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fckeditor.gifbin0 -> 2044 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fredck.gifbin0 -> 920 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_anchor.html236
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_button.html107
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_checkbox.html107
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_colorselector.html171
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_docprops.html600
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html113
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_find.html173
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_flash.html146
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash.js286
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html46
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_form.html105
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_hiddenfield.html116
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_image.html252
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image.js493
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image_preview.html66
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_link.html293
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_link/fck_link.js698
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_listprop.html116
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_paste.html285
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_radiobutton.html107
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_replace.html156
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_select.html176
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_select/fck_select.js194
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_smiley.html105
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_source.html65
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_specialchar.html113
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages.html64
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html0
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js87
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html153
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl180
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js462
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html71
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css49
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js272
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_table.html291
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_tablecell.html255
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_template.html242
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_template/images/template1.gifbin0 -> 375 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_template/images/template2.gifbin0 -> 333 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_template/images/template3.gifbin0 -> 422 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_textarea.html94
-rw-r--r--httemplate/elements/fckeditor/editor/dialog/fck_textfield.html139
-rw-r--r--httemplate/elements/fckeditor/editor/fckdebug.html153
-rw-r--r--httemplate/elements/fckeditor/editor/fckdialog.html324
-rw-r--r--httemplate/elements/fckeditor/editor/fckeditor.html227
-rw-r--r--httemplate/elements/fckeditor/editor/fckeditor.original.html319
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.css88
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.html154
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl63
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl158
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi137
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl131
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl667
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl60
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmactualfolder.html67
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html113
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmfolders.html196
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourceslist.html160
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourcetype.html65
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/frmupload.html113
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gifbin0 -> 138 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder.gifbin0 -> 128 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder32.gifbin0 -> 281 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gifbin0 -> 132 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gifbin0 -> 264 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderUp.gifbin0 -> 132 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gifbin0 -> 1140 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gifbin0 -> 454 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gifbin0 -> 709 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gifbin0 -> 224 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gifbin0 -> 177 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gifbin0 -> 258 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gifbin0 -> 260 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gifbin0 -> 170 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gifbin0 -> 946 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gifbin0 -> 704 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gifbin0 -> 1527 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gifbin0 -> 1527 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gifbin0 -> 463 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gifbin0 -> 274 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gifbin0 -> 274 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gifbin0 -> 454 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gifbin0 -> 567 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gifbin0 -> 464 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gifbin0 -> 254 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gifbin0 -> 1493 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gifbin0 -> 725 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gifbin0 -> 724 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gifbin0 -> 213 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gifbin0 -> 277 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gifbin0 -> 271 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gifbin0 -> 408 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gifbin0 -> 368 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ai.gifbin0 -> 403 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/avi.gifbin0 -> 249 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gifbin0 -> 126 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/cs.gifbin0 -> 128 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gifbin0 -> 113 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/dll.gifbin0 -> 132 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/doc.gifbin0 -> 140 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/exe.gifbin0 -> 109 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/fla.gifbin0 -> 382 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/gif.gifbin0 -> 125 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/htm.gifbin0 -> 621 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/html.gifbin0 -> 621 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gifbin0 -> 125 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/js.gifbin0 -> 139 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gifbin0 -> 146 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gifbin0 -> 249 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gifbin0 -> 230 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/png.gifbin0 -> 125 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gifbin0 -> 139 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gifbin0 -> 606 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swf.gifbin0 -> 388 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swt.gifbin0 -> 388 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/txt.gifbin0 -> 122 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gifbin0 -> 136 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xls.gifbin0 -> 138 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xml.gifbin0 -> 231 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/zip.gifbin0 -> 235 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/images/spacer.gifbin0 -> 43 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/js/common.js55
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/browser/default/js/fckxml.js129
-rw-r--r--httemplate/elements/fckeditor/editor/filemanager/upload/test.html133
-rw-r--r--httemplate/elements/fckeditor/editor/images/anchor.gifbin0 -> 184 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/arrow_ltr.gifbin0 -> 49 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/arrow_rtl.gifbin0 -> 49 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/angel_smile.gifbin0 -> 445 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/angry_smile.gifbin0 -> 453 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/broken_heart.gifbin0 -> 423 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/cake.gifbin0 -> 453 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/confused_smile.gifbin0 -> 322 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/cry_smile.gifbin0 -> 473 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/devil_smile.gifbin0 -> 444 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/embaressed_smile.gifbin0 -> 1077 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/envelope.gifbin0 -> 1030 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/heart.gifbin0 -> 1012 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/kiss.gifbin0 -> 978 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/lightbulb.gifbin0 -> 303 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/omg_smile.gifbin0 -> 342 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/regular_smile.gifbin0 -> 1036 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/sad_smile.gifbin0 -> 1039 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/shades_smile.gifbin0 -> 1059 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/teeth_smile.gifbin0 -> 1064 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_down.gifbin0 -> 992 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_up.gifbin0 -> 989 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/tounge_smile.gifbin0 -> 1055 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gifbin0 -> 1034 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/smiley/msn/wink_smile.gifbin0 -> 1041 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/images/spacer.gifbin0 -> 43 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/js/fckeditorcode_gecko.js98
-rw-r--r--httemplate/elements/fckeditor/editor/js/fckeditorcode_ie.js99
-rw-r--r--httemplate/elements/fckeditor/editor/lang/_getfontformat.html85
-rw-r--r--httemplate/elements/fckeditor/editor/lang/_translationstatus.txt76
-rw-r--r--httemplate/elements/fckeditor/editor/lang/af.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ar.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/bg.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/bn.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/bs.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ca.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/cs.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/da.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/de.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/el.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/en-au.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/en-ca.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/en-uk.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/en.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/eo.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/es.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/et.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/eu.js505
-rw-r--r--httemplate/elements/fckeditor/editor/lang/fa.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/fi.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/fo.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/fr.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/gl.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/he.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/hi.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/hr.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/hu.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/it.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ja.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/km.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ko.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/lt.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/lv.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/mn.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ms.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/nb.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/nl.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/no.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/pl.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/pt-br.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/pt.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ro.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/ru.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/sk.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/sl.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/sr-latn.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/sr.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/sv.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/th.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/tr.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/uk.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/vi.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/zh-cn.js504
-rw-r--r--httemplate/elements/fckeditor/editor/lang/zh.js504
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/autogrow/fckplugin.js92
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/fck_placeholder.html100
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/fckplugin.js187
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/lang/de.js27
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/lang/en.js27
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/lang/fr.js27
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/lang/it.js27
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/lang/pl.js27
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/placeholder/placeholder.gifbin0 -> 96 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/simplecommands/fckplugin.js29
-rw-r--r--httemplate/elements/fckeditor/editor/plugins/tablecommands/fckplugin.js32
-rw-r--r--httemplate/elements/fckeditor/editor/skins/_fckviewstrips.html121
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/fck_dialog.css137
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/fck_editor.css464
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/fck_strip.gifbin0 -> 4578 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.arrowright.gifbin0 -> 53 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gifbin0 -> 46 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.collapse.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.end.gifbin0 -> 43 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.expand.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.separator.gifbin0 -> 58 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/default/images/toolbar.start.gifbin0 -> 105 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/fck_dialog.css138
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/fck_editor.css476
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/fck_strip.gifbin0 -> 9030 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gifbin0 -> 53 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.bg.gifbin0 -> 73 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gifbin0 -> 46 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.collapse.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.end.gifbin0 -> 124 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.expand.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.separator.gifbin0 -> 67 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.start.gifbin0 -> 99 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/fck_dialog.css141
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/fck_editor.css473
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/fck_strip.gifbin0 -> 4578 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.arrowright.gifbin0 -> 53 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gifbin0 -> 46 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gifbin0 -> 829 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.collapse.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.end.gifbin0 -> 43 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.expand.gifbin0 -> 152 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.separator.gifbin0 -> 58 bytes
-rw-r--r--httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.start.gifbin0 -> 105 bytes
-rw-r--r--httemplate/elements/fckeditor/fckconfig.js245
-rw-r--r--httemplate/elements/fckeditor/fckeditor.js214
-rw-r--r--httemplate/elements/fckeditor/fckpackager.xml237
-rw-r--r--httemplate/elements/fckeditor/fckstyles.xml53
-rw-r--r--httemplate/elements/fckeditor/fcktemplates.xml103
-rw-r--r--httemplate/elements/file-upload.html74
-rw-r--r--httemplate/elements/footer.html5
-rw-r--r--httemplate/elements/form-file_upload.html93
-rw-r--r--httemplate/elements/freeside.css16
-rw-r--r--httemplate/elements/header-minimal.html19
-rw-r--r--httemplate/elements/header-popup.html24
-rw-r--r--httemplate/elements/header.html299
-rw-r--r--httemplate/elements/hidden.html11
-rw-r--r--httemplate/elements/htmlarea.html36
-rw-r--r--httemplate/elements/iframecontentmws.js59
-rw-r--r--httemplate/elements/init_calendar.html5
-rw-r--r--httemplate/elements/init_overlib.html9
-rw-r--r--httemplate/elements/input-text.html44
-rw-r--r--httemplate/elements/jsrsClient.js356
-rw-r--r--httemplate/elements/jsrsServer.html4
-rw-r--r--httemplate/elements/location.html154
-rw-r--r--httemplate/elements/mcp_lint.html40
-rw-r--r--httemplate/elements/menu.html427
-rw-r--r--httemplate/elements/menubar.html10
-rw-r--r--httemplate/elements/overlibmws.js620
-rw-r--r--httemplate/elements/overlibmws_crossframe.js53
-rw-r--r--httemplate/elements/overlibmws_draggable.js85
-rw-r--r--httemplate/elements/overlibmws_iframe.js93
-rw-r--r--httemplate/elements/pager.html55
-rw-r--r--httemplate/elements/phonenumber.html40
-rw-r--r--httemplate/elements/popup_link-cust_main.html42
-rw-r--r--httemplate/elements/popup_link-cust_pkg.html47
-rw-r--r--httemplate/elements/popup_link-cust_svc.html47
-rw-r--r--httemplate/elements/popup_link.html49
-rw-r--r--httemplate/elements/popup_link_onclick.html74
-rw-r--r--httemplate/elements/progress-init.html87
-rw-r--r--httemplate/elements/progress-popup.html114
-rw-r--r--httemplate/elements/qlib/box.js29
-rw-r--r--httemplate/elements/qlib/boxctrl.js48
-rw-r--r--httemplate/elements/qlib/boxres.js42
-rw-r--r--httemplate/elements/qlib/button.js74
-rw-r--r--httemplate/elements/qlib/buttonres.js23
-rw-r--r--httemplate/elements/qlib/control.js51
-rw-r--r--httemplate/elements/qlib/counter.js81
-rw-r--r--httemplate/elements/qlib/imagelist.js25
-rw-r--r--httemplate/elements/qlib/label.js72
-rw-r--r--httemplate/elements/qlib/messagebox.js57
-rw-r--r--httemplate/elements/qlib/progress.js73
-rw-r--r--httemplate/elements/qlib/sound.js47
-rw-r--r--httemplate/elements/qlib/sprite.js125
-rw-r--r--httemplate/elements/qlib/window.js25
-rw-r--r--httemplate/elements/qlib/wndctrl.js322
-rw-r--r--httemplate/elements/search-cust_main.html181
-rw-r--r--httemplate/elements/select-access_group.html16
-rw-r--r--httemplate/elements/select-agent.html31
-rw-r--r--httemplate/elements/select-agent_type.html21
-rw-r--r--httemplate/elements/select-agent_types.html30
-rw-r--r--httemplate/elements/select-areacode.html91
-rw-r--r--httemplate/elements/select-cdrbatch.html38
-rw-r--r--httemplate/elements/select-country.html127
-rw-r--r--httemplate/elements/select-county.html160
-rw-r--r--httemplate/elements/select-cust-fields.html24
-rw-r--r--httemplate/elements/select-cust-part_pkg.html41
-rw-r--r--httemplate/elements/select-cust_main-status.html30
-rw-r--r--httemplate/elements/select-cust_pkg-status.html30
-rw-r--r--httemplate/elements/select-did.html84
-rw-r--r--httemplate/elements/select-domain.html13
-rw-r--r--httemplate/elements/select-exchange.html86
-rw-r--r--httemplate/elements/select-month_year.html62
-rw-r--r--httemplate/elements/select-otaker.html27
-rw-r--r--httemplate/elements/select-part_pkg.html38
-rw-r--r--httemplate/elements/select-part_referral.html20
-rw-r--r--httemplate/elements/select-payby.html40
-rw-r--r--httemplate/elements/select-phonenum.html84
-rw-r--r--httemplate/elements/select-pkg_class.html18
-rw-r--r--httemplate/elements/select-rate.html9
-rw-r--r--httemplate/elements/select-state.html66
-rw-r--r--httemplate/elements/select-table.html164
-rw-r--r--httemplate/elements/select-taxclass.html41
-rw-r--r--httemplate/elements/select-taxoverride.html28
-rw-r--r--httemplate/elements/select-taxproduct.html28
-rw-r--r--httemplate/elements/selectlayers.html216
-rw-r--r--httemplate/elements/small_custview.html3
-rw-r--r--httemplate/elements/table-grid.html25
-rw-r--r--httemplate/elements/table.html11
-rw-r--r--httemplate/elements/tablebreak-tr-title.html14
-rw-r--r--httemplate/elements/tr-checkbox-multiple.html40
-rw-r--r--httemplate/elements/tr-checkbox.html25
-rw-r--r--httemplate/elements/tr-checkboxes-table.html20
-rw-r--r--httemplate/elements/tr-fixed-country.html10
-rw-r--r--httemplate/elements/tr-fixed-state.html10
-rw-r--r--httemplate/elements/tr-fixed.html15
-rw-r--r--httemplate/elements/tr-freq.html54
-rw-r--r--httemplate/elements/tr-input-beginning_ending.html75
-rw-r--r--httemplate/elements/tr-input-date-field.html40
-rw-r--r--httemplate/elements/tr-input-lessthan_greaterthan.html13
-rw-r--r--httemplate/elements/tr-input-money.html13
-rw-r--r--httemplate/elements/tr-input-percentage.html8
-rw-r--r--httemplate/elements/tr-input-text.html13
-rw-r--r--httemplate/elements/tr-justtitle.html11
-rw-r--r--httemplate/elements/tr-part_pkg_freq.html24
-rw-r--r--httemplate/elements/tr-password.html4
-rw-r--r--httemplate/elements/tr-pkg_svc.html93
-rw-r--r--httemplate/elements/tr-select-access_group.html22
-rw-r--r--httemplate/elements/tr-select-agent.html33
-rw-r--r--httemplate/elements/tr-select-agent_type.html39
-rw-r--r--httemplate/elements/tr-select-agent_types.html19
-rw-r--r--httemplate/elements/tr-select-cdrbatch.html32
-rw-r--r--httemplate/elements/tr-select-cust-fields.html15
-rw-r--r--httemplate/elements/tr-select-cust_location.html178
-rw-r--r--httemplate/elements/tr-select-cust_main-status.html29
-rw-r--r--httemplate/elements/tr-select-cust_pkg-status.html29
-rw-r--r--httemplate/elements/tr-select-did.html25
-rw-r--r--httemplate/elements/tr-select-domain.html12
-rw-r--r--httemplate/elements/tr-select-from_to.html52
-rw-r--r--httemplate/elements/tr-select-invoice_template.html39
-rw-r--r--httemplate/elements/tr-select-otaker.html10
-rw-r--r--httemplate/elements/tr-select-part_pkg.html39
-rw-r--r--httemplate/elements/tr-select-part_referral.html37
-rw-r--r--httemplate/elements/tr-select-part_svc.html29
-rw-r--r--httemplate/elements/tr-select-payby.html37
-rw-r--r--httemplate/elements/tr-select-pkg_class.html27
-rw-r--r--httemplate/elements/tr-select-rate.html21
-rwxr-xr-xhttemplate/elements/tr-select-reason.html189
-rw-r--r--httemplate/elements/tr-select-table.html20
-rw-r--r--httemplate/elements/tr-select-taxclass.html34
-rw-r--r--httemplate/elements/tr-select-taxoverride.html18
-rw-r--r--httemplate/elements/tr-select-taxproduct.html18
-rw-r--r--httemplate/elements/tr-select.html61
-rw-r--r--httemplate/elements/tr-selectlayers-select.html1
-rw-r--r--httemplate/elements/tr-selectlayers.html25
-rw-r--r--httemplate/elements/tr-selectmultiple-part_pkg.html20
-rw-r--r--httemplate/elements/tr-td-label.html17
-rw-r--r--httemplate/elements/tr-title.html5
-rw-r--r--httemplate/elements/xmenu.css196
-rw-r--r--httemplate/elements/xmenu.js668
-rw-r--r--httemplate/elements/xmenu.top.css211
-rw-r--r--httemplate/elements/xmenu.top.js671
-rw-r--r--httemplate/elements/xmlhttp.html125
-rw-r--r--httemplate/graph/cust_bill_pkg.cgi109
-rw-r--r--httemplate/graph/cust_pkg.cgi63
-rw-r--r--httemplate/graph/elements/monthly.html351
-rw-r--r--httemplate/graph/money_time.cgi98
-rw-r--r--httemplate/graph/report_cust_bill_pkg.html39
-rw-r--r--httemplate/graph/report_cust_pkg.html28
-rw-r--r--httemplate/graph/report_money_time.html43
-rw-r--r--httemplate/images/32clear.gifbin0 -> 815 bytes
-rw-r--r--httemplate/images/ach.pngbin0 -> 29759 bytes
-rw-r--r--httemplate/images/arrow.down.pngbin0 -> 155 bytes
-rw-r--r--httemplate/images/arrow.right.black.pngbin0 -> 160 bytes
-rw-r--r--httemplate/images/arrow.right.pngbin0 -> 160 bytes
-rw-r--r--httemplate/images/background-cheat.pngbin0 -> 338 bytes
-rw-r--r--httemplate/images/black-gradient.pngbin0 -> 397 bytes
-rw-r--r--httemplate/images/black-gray-corner.pngbin0 -> 460 bytes
-rw-r--r--httemplate/images/black-gray-gradient.pngbin0 -> 384 bytes
-rw-r--r--httemplate/images/black-gray-side.pngbin0 -> 198 bytes
-rw-r--r--httemplate/images/black-gray-top.pngbin0 -> 203 bytes
-rw-r--r--httemplate/images/calendar-disabled.pngbin0 -> 209 bytes
-rw-r--r--httemplate/images/calendar.pngbin0 -> 426 bytes
-rw-r--r--httemplate/images/cross.pngbin0 -> 655 bytes
-rw-r--r--httemplate/images/cvv2.pngbin0 -> 7791 bytes
-rw-r--r--httemplate/images/cvv2_amex.pngbin0 -> 9539 bytes
-rw-r--r--httemplate/images/error.pngbin0 -> 666 bytes
-rw-r--r--httemplate/images/menu-left-example.pngbin0 -> 24709 bytes
-rw-r--r--httemplate/images/menu-top-example.pngbin0 -> 22816 bytes
-rw-r--r--httemplate/images/progressbar-empty.pngbin0 -> 90 bytes
-rw-r--r--httemplate/images/progressbar-full.pngbin0 -> 79 bytes
-rw-r--r--httemplate/images/red_telephone_mimooh_01.pngbin0 -> 921 bytes
-rw-r--r--httemplate/images/small-logo.pngbin0 -> 4887 bytes
-rw-r--r--httemplate/images/tick.pngbin0 -> 537 bytes
-rw-r--r--httemplate/images/wait-orange.gifbin0 -> 1849 bytes
-rw-r--r--httemplate/index.html54
-rw-r--r--httemplate/misc/areacodes.cgi24
-rw-r--r--httemplate/misc/batch-cust_pay.html38
-rwxr-xr-xhttemplate/misc/bill.cgi45
-rwxr-xr-xhttemplate/misc/bulk_change_pkg.cgi59
-rwxr-xr-xhttemplate/misc/cancel-unaudited.cgi33
-rw-r--r--httemplate/misc/cancel_cust.html63
-rwxr-xr-xhttemplate/misc/cancel_pkg.html109
-rwxr-xr-xhttemplate/misc/catchall.cgi118
-rw-r--r--httemplate/misc/cdr-import.html61
-rw-r--r--httemplate/misc/cdr.cgi48
-rwxr-xr-xhttemplate/misc/change_pkg.cgi72
-rw-r--r--httemplate/misc/copy-rate_detail.html61
-rw-r--r--httemplate/misc/counties.cgi7
-rwxr-xr-xhttemplate/misc/cust_main-cancel.cgi57
-rw-r--r--httemplate/misc/cust_main-import.cgi148
-rw-r--r--httemplate/misc/cust_main-import_charges.cgi22
-rw-r--r--httemplate/misc/cust_main_note-import.cgi207
-rw-r--r--httemplate/misc/cust_main_note-import.html39
-rw-r--r--httemplate/misc/cust_pay-import.cgi62
-rwxr-xr-xhttemplate/misc/delay_susp_pkg.html70
-rw-r--r--httemplate/misc/delete-agent_payment_gateway.cgi15
-rwxr-xr-xhttemplate/misc/delete-cust_credit.cgi21
-rwxr-xr-xhttemplate/misc/delete-cust_pay.cgi21
-rwxr-xr-xhttemplate/misc/delete-cust_refund.cgi21
-rwxr-xr-xhttemplate/misc/delete-customer.cgi64
-rwxr-xr-xhttemplate/misc/delete-domain_record.cgi20
-rwxr-xr-xhttemplate/misc/delete-part_export.cgi20
-rw-r--r--httemplate/misc/disable-payment_gateway.cgi25
-rw-r--r--httemplate/misc/download-batch.cgi213
-rw-r--r--httemplate/misc/dump.cgi20
-rw-r--r--httemplate/misc/email-customers.html145
-rwxr-xr-xhttemplate/misc/email-invoice.cgi19
-rw-r--r--httemplate/misc/email_events.cgi9
-rw-r--r--httemplate/misc/email_invoice_events.cgi9
-rw-r--r--httemplate/misc/email_invoices.cgi9
-rwxr-xr-xhttemplate/misc/enable_or_disable_tax.html37
-rw-r--r--httemplate/misc/exchanges.cgi24
-rwxr-xr-xhttemplate/misc/fax-invoice.cgi19
-rw-r--r--httemplate/misc/fax_events.cgi9
-rw-r--r--httemplate/misc/fax_invoice_events.cgi9
-rw-r--r--httemplate/misc/fax_invoices.cgi9
-rw-r--r--httemplate/misc/file-upload.html53
-rw-r--r--httemplate/misc/ftp_invoices.cgi9
-rw-r--r--httemplate/misc/inventory_item-import.html67
-rwxr-xr-xhttemplate/misc/link.cgi84
-rw-r--r--httemplate/misc/location.cgi19
-rw-r--r--httemplate/misc/meta-import.cgi79
-rw-r--r--httemplate/misc/order_pkg.html75
-rw-r--r--httemplate/misc/payment.cgi285
-rw-r--r--httemplate/misc/phone_avail-import.html88
-rw-r--r--httemplate/misc/phonenums.cgi29
-rwxr-xr-xhttemplate/misc/print-invoice.cgi19
-rw-r--r--httemplate/misc/print_events.cgi9
-rw-r--r--httemplate/misc/print_invoice_events.cgi9
-rw-r--r--httemplate/misc/print_invoices.cgi9
-rw-r--r--httemplate/misc/process/batch-cust_pay.cgi47
-rwxr-xr-xhttemplate/misc/process/bulk_change_pkg.cgi56
-rwxr-xr-xhttemplate/misc/process/cancel_pkg.html72
-rwxr-xr-xhttemplate/misc/process/catchall.cgi35
-rw-r--r--httemplate/misc/process/cdr-import.html9
-rw-r--r--httemplate/misc/process/copy-rate_detail.html61
-rw-r--r--httemplate/misc/process/cust_main-import.cgi10
-rw-r--r--httemplate/misc/process/cust_main-import_charges.cgi23
-rw-r--r--httemplate/misc/process/cust_main_note-import.cgi82
-rw-r--r--httemplate/misc/process/cust_pay-import.cgi21
-rwxr-xr-xhttemplate/misc/process/delay_susp_pkg.html41
-rwxr-xr-xhttemplate/misc/process/delete-customer.cgi33
-rw-r--r--httemplate/misc/process/email-customers.html9
-rwxr-xr-xhttemplate/misc/process/enable_or_disable_tax.html41
-rw-r--r--httemplate/misc/process/inventory_item-import.html9
-rwxr-xr-xhttemplate/misc/process/link.cgi72
-rw-r--r--httemplate/misc/process/meta-import.cgi190
-rw-r--r--httemplate/misc/process/payment.cgi183
-rw-r--r--httemplate/misc/process/phone_avail-import.html9
-rwxr-xr-xhttemplate/misc/process/recharge_svc.html92
-rwxr-xr-xhttemplate/misc/process/recharge_svc.new85
-rw-r--r--httemplate/misc/process/tax-import.cgi9
-rw-r--r--httemplate/misc/process/tax-upgrade.cgi147
-rw-r--r--httemplate/misc/process/timeworked.html57
-rw-r--r--httemplate/misc/queue.cgi49
-rwxr-xr-xhttemplate/misc/recharge_svc.html105
-rw-r--r--httemplate/misc/spool_invoices.cgi9
-rw-r--r--httemplate/misc/states.cgi7
-rw-r--r--httemplate/misc/svc_acct-domains.cgi31
-rw-r--r--httemplate/misc/tax-import.cgi65
-rwxr-xr-xhttemplate/misc/timeworked.html135
-rwxr-xr-xhttemplate/misc/unadjourn_pkg.cgi17
-rwxr-xr-xhttemplate/misc/unapply-cust_credit.cgi20
-rwxr-xr-xhttemplate/misc/unapply-cust_pay.cgi20
-rwxr-xr-xhttemplate/misc/unexpire_pkg.cgi17
-rwxr-xr-xhttemplate/misc/unprovision.cgi26
-rwxr-xr-xhttemplate/misc/unsusp_pkg.cgi20
-rwxr-xr-xhttemplate/misc/unvoid-cust_pay_void.cgi21
-rw-r--r--httemplate/misc/upload-batch.cgi36
-rwxr-xr-xhttemplate/misc/void-cust_pay.cgi26
-rw-r--r--httemplate/misc/whois.cgi33
-rw-r--r--httemplate/misc/xmlhttp-cust_main-address_standardize.html89
-rw-r--r--httemplate/misc/xmlhttp-cust_main-search.cgi36
-rw-r--r--httemplate/misc/xmlrpc.cgi18
-rw-r--r--httemplate/pref/pref-process.html58
-rw-r--r--httemplate/pref/pref.html124
-rw-r--r--httemplate/search/cdr.html159
-rwxr-xr-xhttemplate/search/cust_bill.html251
-rw-r--r--httemplate/search/cust_bill_event.cgi166
-rwxr-xr-xhttemplate/search/cust_bill_event.html67
-rw-r--r--httemplate/search/cust_bill_pay.html131
-rw-r--r--httemplate/search/cust_bill_pkg.cgi335
-rwxr-xr-xhttemplate/search/cust_credit.html104
-rw-r--r--httemplate/search/cust_credit_bill.html135
-rw-r--r--httemplate/search/cust_credit_refund.html130
-rw-r--r--httemplate/search/cust_event.html285
-rwxr-xr-xhttemplate/search/cust_main-otaker.cgi31
-rw-r--r--httemplate/search/cust_main-zip.html99
-rwxr-xr-xhttemplate/search/cust_main.cgi736
-rwxr-xr-xhttemplate/search/cust_main.html109
-rwxr-xr-xhttemplate/search/cust_pay.cgi7
-rwxr-xr-xhttemplate/search/cust_pay_batch.cgi193
-rwxr-xr-xhttemplate/search/cust_pay_pending.html57
-rwxr-xr-xhttemplate/search/cust_pkg.cgi233
-rw-r--r--httemplate/search/cust_refund.html7
-rw-r--r--httemplate/search/cust_svc.html138
-rw-r--r--httemplate/search/cust_tax_exempt.cgi139
-rw-r--r--httemplate/search/cust_tax_exempt.html31
-rw-r--r--httemplate/search/cust_tax_exempt_pkg.cgi182
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html301
-rw-r--r--httemplate/search/elements/search.html912
-rw-r--r--httemplate/search/inventory_item.html125
-rwxr-xr-xhttemplate/search/pay_batch.cgi130
-rw-r--r--httemplate/search/pay_batch.html33
-rw-r--r--httemplate/search/phone_avail.html102
-rw-r--r--httemplate/search/prepay_credit.html67
-rw-r--r--httemplate/search/queue.html138
-rw-r--r--httemplate/search/reg_code.html40
-rw-r--r--httemplate/search/report_cdr.html58
-rw-r--r--httemplate/search/report_cust_bill.html36
-rw-r--r--httemplate/search/report_cust_credit.html48
-rw-r--r--httemplate/search/report_cust_event.html65
-rw-r--r--httemplate/search/report_cust_main-zip.html53
-rwxr-xr-xhttemplate/search/report_cust_main.html94
-rw-r--r--httemplate/search/report_cust_pay.html79
-rw-r--r--httemplate/search/report_cust_pay_batch.html44
-rwxr-xr-xhttemplate/search/report_cust_pkg.html149
-rwxr-xr-xhttemplate/search/report_newtax.cgi158
-rwxr-xr-xhttemplate/search/report_newtax.html23
-rw-r--r--httemplate/search/report_prepaid_income.cgi87
-rw-r--r--httemplate/search/report_prepaid_income.html43
-rwxr-xr-xhttemplate/search/report_receivables.cgi197
-rwxr-xr-xhttemplate/search/report_receivables.html35
-rw-r--r--httemplate/search/report_rt_transaction.html24
-rw-r--r--httemplate/search/report_sql.html23
-rwxr-xr-xhttemplate/search/report_svc_acct.html105
-rwxr-xr-xhttemplate/search/report_tax.cgi612
-rwxr-xr-xhttemplate/search/report_tax.html42
-rw-r--r--httemplate/search/rt_transaction.html96
-rw-r--r--httemplate/search/sql.html13
-rw-r--r--httemplate/search/sqlradius.cgi328
-rw-r--r--httemplate/search/sqlradius.html123
-rwxr-xr-xhttemplate/search/svc_acct.cgi296
-rwxr-xr-xhttemplate/search/svc_broadband.cgi123
-rwxr-xr-xhttemplate/search/svc_domain.cgi112
-rwxr-xr-xhttemplate/search/svc_external.cgi153
-rwxr-xr-xhttemplate/search/svc_forward.cgi146
-rw-r--r--httemplate/search/svc_phone.cgi117
-rwxr-xr-xhttemplate/search/svc_www.cgi113
-rw-r--r--httemplate/search/timeworked.html117
-rwxr-xr-xhttemplate/view/REAL_logo.cgi14
-rwxr-xr-xhttemplate/view/cust_bill-logo.cgi31
-rwxr-xr-xhttemplate/view/cust_bill-pdf.cgi28
-rwxr-xr-xhttemplate/view/cust_bill-ps.cgi24
-rwxr-xr-xhttemplate/view/cust_bill.cgi120
-rwxr-xr-xhttemplate/view/cust_main.cgi158
-rw-r--r--httemplate/view/cust_main/billing.html220
-rw-r--r--httemplate/view/cust_main/contacts.html122
-rw-r--r--httemplate/view/cust_main/misc.html110
-rwxr-xr-xhttemplate/view/cust_main/notes.html88
-rwxr-xr-xhttemplate/view/cust_main/packages.html241
-rw-r--r--httemplate/view/cust_main/packages/location.html60
-rw-r--r--httemplate/view/cust_main/packages/package.html215
-rw-r--r--httemplate/view/cust_main/packages/services.html119
-rw-r--r--httemplate/view/cust_main/packages/status.html379
-rw-r--r--httemplate/view/cust_main/payment_history.html413
-rw-r--r--httemplate/view/cust_main/payment_history/credit.html140
-rw-r--r--httemplate/view/cust_main/payment_history/invoice.html34
-rw-r--r--httemplate/view/cust_main/payment_history/payment.html209
-rw-r--r--httemplate/view/cust_main/payment_history/refund.html50
-rw-r--r--httemplate/view/cust_main/payment_history/voided_payment.html37
-rw-r--r--httemplate/view/cust_main/tickets.html84
-rw-r--r--httemplate/view/cust_pay.html135
-rw-r--r--httemplate/view/cust_refund.html142
-rw-r--r--httemplate/view/elements/svc_Common.html152
-rw-r--r--httemplate/view/logo.cgi47
-rw-r--r--httemplate/view/svc_Common.html29
-rwxr-xr-xhttemplate/view/svc_acct.cgi401
-rw-r--r--httemplate/view/svc_broadband.cgi212
-rwxr-xr-xhttemplate/view/svc_domain.cgi161
-rw-r--r--httemplate/view/svc_external.cgi63
-rwxr-xr-xhttemplate/view/svc_forward.cgi105
-rw-r--r--httemplate/view/svc_phone.cgi54
-rw-r--r--httemplate/view/svc_www.cgi104
860 files changed, 95479 insertions, 0 deletions
diff --git a/httemplate/.htaccess b/httemplate/.htaccess
new file mode 100755
index 000000000..f8c6b9c0c
--- /dev/null
+++ b/httemplate/.htaccess
@@ -0,0 +1,3 @@
+AuthName Freeside
+AuthType Basic
+require valid-user
diff --git a/httemplate/autohandler b/httemplate/autohandler
new file mode 100644
index 000000000..ae04d423f
--- /dev/null
+++ b/httemplate/autohandler
@@ -0,0 +1,44 @@
+% $m->call_next;
+<%init>
+ dbh->{'private_profile'} = {} if UNIVERSAL::can(dbh, 'sprintProfile');
+</%init>
+<%filter>
+
+my $profile = '';
+if ( UNIVERSAL::can(dbh, 'sprintProfile') ) {
+
+ if ( lc($r->content_type) eq 'text/html'
+ && $FS::CurrentUser::CurrentUser->option('show_db_profile')
+ )
+ {
+
+ ## barely worth it, just in case someone tries to use profiling on a
+ ## non-RT install
+ #eval "use Text::Wrapper;";
+ #die $@ if $@;
+
+ my $text = dbh->sprintProfile();
+ #$text =~ s/^/ /mg;
+
+ $profile = '<PRE>'. encode_entities( $text ). "\n\n". '</PRE>';
+
+ }
+
+ #well, could do this without sprintProfile, but definiately don't want it on
+ #unless DBIx::Profile is loaded
+ if ( $FS::CurrentUser::CurrentUser->option('save_db_profile') ) {
+ #my $file = %%%FREESIDE_LOG%%%; #substitute here? maybe get from FS.pm?
+ my $file = '/usr/local/etc/freeside/'; #bah
+ $file .= "dbix_profile.$$.". time;
+ dbh->setLogFile($file);
+ dbh->printProfile();
+ }
+
+ dbh->{'private_profile'} = {};
+}
+
+s/(<\/BODY>[\s\n]*<\/HTML>[\s\n]*)$/$profile$1/i;
+</%filter>
+<%cleanup>
+ dbh->commit();
+</%cleanup>
diff --git a/httemplate/browse/access_group.html b/httemplate/browse/access_group.html
new file mode 100644
index 000000000..aa9097f36
--- /dev/null
+++ b/httemplate/browse/access_group.html
@@ -0,0 +1,106 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Employee Groups',
+ 'menubar' => [ 'View Employees' => $p.'browse/access_user.html', ],
+ 'html_init' => $html_init,
+ 'name' => 'employee groups',
+ 'query' => { 'table' => 'access_group',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY groupname', #??
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Group name',
+ 'Agents',
+ 'Rights',
+ ],
+ 'fields' => [ 'groupnum',
+ 'groupname',
+ $agents_sub,
+ $rights_sub,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ '',
+ ],
+ )
+%>
+<%once>
+
+my $html_init =
+ "Employee groups control access to the back-office interface. Each employee can be assigned to one or more groups.<BR><BR>".
+ qq!<A HREF="${p}edit/access_group.html"><I>Add an employee group</I></A><BR><BR>!;
+
+#false laziness w/access_user.html & agent_type.cgi
+my $agents_sub = sub {
+ my $access_group = shift;
+
+ [ map {
+ my $access_groupagent = $_;
+ my $agent = $access_groupagent->agent;
+ [
+ {
+ 'data' => $agent->agent,
+ 'align' => 'left',
+ 'link' => $p. 'edit/agent.cgi?'. $agent->agentnum,
+ },
+ ];
+ }
+ grep { $_->agent } #?
+ $access_group->access_groupagent,
+
+ ];
+
+};
+
+tie my %rights, 'Tie::IxHash', FS::AccessRight->rights_info;
+
+my $rights_sub = sub {
+ my $access_group = shift;
+
+ #[ map { my $access_right = $_;
+ # [
+ # {
+ # 'data' => $access_right->rightname,
+ # 'align' => 'left',
+ # },
+ # ];
+ # }
+ # $access_group->access_rights,
+ #];
+
+ #some false laziness w/edit/access_group.html
+ my $columns = 3;
+ my $count = 0;
+
+ #include('/elements/table-grid.html', bgcolor=>'#cccccc' ).
+ '<TABLE>'.
+ '<TR>'. join( '', map {
+
+ '<TD CLASS="inv" VALIGN="top"><TABLE WIDTH=100%>'.
+ '<TR><TH BGCOLOR="#dcdcdc">'. $_. '</TH></TR>'.
+ '<TR><TD>'.
+
+ join('<BR>', grep { $access_group->access_right($_); }
+ map { ref($_) ? $_->{'rightname'} : $_; }
+ @{ $rights{$_} }
+ ).
+
+ '</TD></TR></TABLE></TD>'.
+ ( ++$count % $columns ? '' : '</TR><TR>')
+
+ } keys %rights ). '</TR></TABLE>';
+
+};
+
+my $count_query = 'SELECT COUNT(*) FROM access_group';
+
+my $link = [ $p.'edit/access_group.html?', 'groupnum' ];
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html
new file mode 100644
index 000000000..321025b69
--- /dev/null
+++ b/httemplate/browse/access_user.html
@@ -0,0 +1,61 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Employees',
+ 'menubar' => [ 'View Employee groups' => $p.'browse/access_group.html', ],
+ 'html_init' => $html_init,
+ 'name' => 'employees',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'query' => { 'table' => 'access_user',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY last, first'
+ },
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'links' => \@links,
+ 'align' => $align,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ "Employees have access to the back-office interface. Typically, this is your employees and contractors. In a virtualized setup, you can also add accounts for your reseller's employees.<BR><BR>It is <B>highly recommended</B> to add a <B>separate account for each person</B> rather than using role accounts.<BR><BR>".
+ qq!<A HREF="${p}edit/access_user.html"><I>Add an employee</I></A><BR><BR>!;
+
+#false laziness w/access_group.html & agent_type.cgi
+my $groups_sub = sub {
+ my $access_user = shift;
+
+ [ map {
+ my $access_usergroup = $_;
+ my $access_group = $access_usergroup->access_group;
+ [
+ {
+ 'data' => $access_group->groupname,
+ 'align' => 'left',
+ 'link' =>
+ $p. 'edit/access_group.html?'. $access_usergroup->groupnum,
+ },
+ ];
+ }
+ grep { $_->access_group # and ! $_->access_group->disabled
+ }
+ $access_user->access_usergroup,
+
+ ];
+
+};
+
+my $count_query = 'SELECT COUNT(*) FROM access_user';
+
+my $link = [ $p.'edit/access_user.html?', 'usernum' ];
+
+my @header = ( '#', 'Username', 'Full name', 'Groups' );
+my @fields = ( 'usernum', 'username', 'name', $groups_sub );
+my $align = 'rlll';
+my @links = ( $link, $link, $link, '' );
+
+</%init>
diff --git a/httemplate/browse/addr_block.cgi b/httemplate/browse/addr_block.cgi
new file mode 100644
index 000000000..1bbcdcbc1
--- /dev/null
+++ b/httemplate/browse/addr_block.cgi
@@ -0,0 +1,145 @@
+<% include('elements/browse.html',
+ 'title' => 'Address Blocks',
+ 'name' => 'address block',
+ 'html_init' => $html_init,
+ 'html_foot' => $html_foot,
+ 'query' => { 'table' => 'addr_block',
+ 'hashref' => {},
+ 'extra_sql' => $extra_sql,
+ 'order_by' => $order_by,
+ },
+ 'count_query' => "SELECT count(*) from addr_block $count_sql",
+ 'header' => [ 'Address Block',
+ 'Router',
+ 'Action(s)',
+ '',
+ '',
+ ],
+ 'fields' => [ 'NetAddr',
+ sub { my $block = shift;
+ my $router = $block->router;
+ my $result = '';
+ if ($router) {
+ $result .= $router->routername. ' (';
+ $result .= scalar($block->svc_broadband). ' services)';
+ }
+ $result;
+ },
+ $allocate_text,
+ sub { shift->router ? '' : '<FONT SIZE="-2">(split)</FONT>' },
+ sub { '<FONT SIZE="-2">('. (shift->manual_flag ? 'allow' : 'prevent'). ' automatic ip assignment)</FONT>' },
+ ],
+ 'links' => [ '',
+ '',
+ [ 'javascript:void(0)', '' ],
+ $split_link,
+ $autoassign_link,
+ ],
+ 'link_onclicks' => [ '',
+ '',
+ $allocate_link,
+ '',
+ ],
+ 'cell_styles' => [ '',
+ '',
+ 'border-right:none;',
+ 'border-left:none;',
+ ],
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Broadband global configuration',
+ 'agent_pos' => 1,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Broadband configuration')
+ || $FS::CurrentUser::CurrentUser->access_right('Broadband global configuration');
+
+my $p2 = popurl(2);
+my $path = $p2 . "edit/process/addr_block";
+
+my $extra_sql = "";
+
+my $count_sql = "WHERE ". $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'Broadband global configuration',
+);
+
+my $order_by = "ORDER BY ";
+$order_by .= "inet(ip_gateway), " if driver_name =~ /^Pg/i;
+$order_by .= "inet_aton(ip_gateway), " if driver_name =~ /^mysql/i;
+$order_by .= "ip_netmask";
+
+my $html_init = qq(
+<SCRIPT>
+ function addr_block_areyousure(href, word) {
+ if(confirm("Are you sure you want to "+word+" this address block?") == true)
+ window.location.href = href;
+ }
+</SCRIPT>
+);
+
+$html_init .= include('/elements/error.html');
+
+my $confirm = sub {
+ my ($verb, $num) = (shift, shift);
+ "javascript:addr_block_areyousure('$path/$verb.cgi?blocknum=$num', '$verb')";
+};
+
+my $html_foot = qq(
+ <FORM ACTION="$path/add.cgi" METHOD="POST">
+ Gateway/Netmask:
+ <INPUT TYPE="text" NAME="ip_gateway" SIZE="15">/<INPUT TYPE="text" NAME="ip_netmask" SIZE="2">
+);
+$html_foot .= include( '/elements/select-agent.html',
+ 'agent_null_right' => 'Broadband global configuration',
+ );
+$html_foot .= qq(
+ <INPUT TYPE="submit" NAME="submit" VALUE="Add">
+ </FORM>
+);
+
+my $allocate_text = sub { my $block = shift;
+ my $router = $block->router;
+ my $result = '';
+ if ($router) {
+ $result = '<FONT SIZE="-2">(deallocate)</FONT>'
+ unless scalar($block->svc_broadband);
+ }else{
+ $result .= '<FONT SIZE="-2">(allocate)</FONT>'
+ }
+ $result;
+};
+
+my $allocate_link = sub {
+ my $block = shift;
+ if ($block->router) {
+ if (scalar($block->svc_broadband) == 0) {
+ &{$confirm}('deallocate', $block->blocknum);
+ } else {
+ "";
+ }
+ } else {
+ include( '/elements/popup_link_onclick.html',
+ 'action' => "${p2}edit/allocate.html?blocknum=". $block->blocknum,
+ 'actionlabel' => 'Allocate block to router',
+ );
+ }
+};
+
+my $split_link = sub {
+ my $block = shift;
+ my $ref = [ '', '' ];
+ $ref = [ &{$confirm}('split', $block->blocknum), '' ]
+ unless ($block->router);
+ $ref;
+};
+
+my $autoassign_link = sub {
+ my $block = shift;
+ my $url = "$path/manual_flag.cgi?manual_flag=";
+ $url .= $block->manual_flag ? '' : 'Y';
+ [ "$url;blocknum=", 'blocknum' ];
+};
+
+</%init>
diff --git a/httemplate/browse/agent.cgi b/httemplate/browse/agent.cgi
new file mode 100755
index 000000000..0a516edef
--- /dev/null
+++ b/httemplate/browse/agent.cgi
@@ -0,0 +1,422 @@
+<% include("/elements/header.html",'Agent Listing', menubar(
+ 'Agent Types' => $p. 'browse/agent_type.cgi',
+# 'Add new agent' => '../edit/agent.cgi'
+)) %>
+Agents are resellers of your service. Agents may be limited to a subset of your
+full offerings (via their type).<BR><BR>
+<A HREF="<% $p %>edit/agent.cgi"><I>Add a new agent</I></A><BR><BR>
+% if ( dbdef->table('agent')->column('disabled') ) {
+
+ <% $cgi->param('showdisabled')
+ ? do { $cgi->param('showdisabled', 0);
+ '( <a href="'. $cgi->self_url. '">hide disabled agents</a> )'; }
+ : do { $cgi->param('showdisabled', 1);
+ '( <a href="'. $cgi->self_url. '">show disabled agents</a> )'; }
+ %>
+% }
+
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+%
+
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<% ( $cgi->param('showdisabled') || !dbdef->table('agent')->column('disabled') ) ? 2 : 3 %>>Agent</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Type</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Master Customer</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Access Groups</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Invoice<BR>Template</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Customers</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Customer<BR>packages</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Reports</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Registration<BR>codes</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Prepaid cards</TH>
+% if ( $conf->config('ticket_system') ) {
+
+ <TH CLASS="grid" BGCOLOR="#cccccc">Ticketing</TH>
+% }
+
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Payment Gateway Overrides</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Configuration Overrides</FONT></TH>
+</TR>
+%
+%# <TH><FONT SIZE=-1>Agent #</FONT></TH>
+%# <TH>Agent</TH>
+%
+%foreach my $agent ( sort {
+% #$a->getfield('agentnum') <=> $b->getfield('agentnum')
+% $a->getfield('agent') cmp $b->getfield('agent')
+%} qsearch('agent', \%search ) ) {
+%
+% my $cust_main_link = $p. 'search/cust_main.cgi?agentnum_on=1&'.
+% 'agentnum='. $agent->agentnum;
+%
+% my $cust_pkg_link = $p. 'search/cust_pkg.cgi?agentnum='. $agent->agentnum;
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+%
+
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<%$p%>edit/agent.cgi?<% $agent->agentnum %>"><% $agent->agentnum %></A>
+ </TD>
+
+% if ( dbdef->table('agent')->column('disabled')
+% && !$cgi->param('showdisabled') ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $agent->disabled ? 'DISABLED' : '' %>
+ </TD>
+% }
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<%$p%>edit/agent.cgi?<% $agent->agentnum %>"><% $agent->agent %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<%$p%>edit/agent_type.cgi?<% $agent->typenum %>"><% $agent->agent_type->atype %></A>
+ </TD>
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+% if ( $agent->agent_custnum ) {
+ <% include('/elements/small_custview.html',
+ $agent->agent_custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #show balance
+ )
+ %>
+% }
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% foreach my $access_group (
+% map $_->access_group,
+% qsearch('access_groupagent', { 'agentnum' => $agent->agentnum })
+% ) {
+ <A HREF="<%$p%>edit/access_group.html?<% $access_group->groupnum %>"><% $access_group->groupname |h %><BR>
+% }
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $agent->invoice_template || '(Default)' %>
+ </TD>
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="bottom">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#7e0079">
+ <% my $num_prospect = $agent->num_prospect_cust_main %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_prospect ) {
+
+ <A HREF="<% $cust_main_link %>&prospect=1">
+% }
+prospects
+% if ($num_prospect ) {
+</A>
+% }
+
+ <TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#0000CC">
+ <% my $num_inactive = $agent->num_inactive_cust_main %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_inactive ) {
+
+ <A HREF="<% $cust_main_link %>&inactive=1">
+% }
+inactive
+% if ( $num_inactive ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#00CC00">
+ <% my $num_active = $agent->num_active_cust_main %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_active ) {
+
+ <A HREF="<% $cust_main_link %>&active=1">
+% }
+active
+% if ( $num_active ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#FF9900">
+ <% my $num_susp = $agent->num_susp_cust_main %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_susp ) {
+
+ <A HREF="<% $cust_main_link %>&suspended=1">
+% }
+suspended
+% if ( $num_susp ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#FF0000">
+ <% my $num_cancel = $agent->num_cancel_cust_main %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_cancel ) {
+
+ <A HREF="<% $cust_main_link %>&showcancelledcustomers=1&cancelled=1">
+% }
+cancelled
+% if ( $num_cancel ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ </TABLE>
+ </TD>
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="bottom">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#0000CC">
+ <% my $num_inactive_pkg = $agent->num_inactive_cust_pkg %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_inactive_pkg ) {
+
+ <A HREF="<% $cust_pkg_link %>&magic=inactive">
+% }
+inactive
+% if ( $num_inactive_pkg ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#00CC00">
+ <% my $num_active_pkg = $agent->num_active_cust_pkg %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_active_pkg ) {
+
+ <A HREF="<% $cust_pkg_link %>&magic=active">
+% }
+active
+% if ( $num_active_pkg ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#FF9900">
+ <% my $num_susp_pkg = $agent->num_susp_cust_pkg %>&nbsp;
+ </FONT>
+
+ </TH>
+ <TD>
+% if ( $num_susp_pkg ) {
+
+ <A HREF="<% $cust_pkg_link %>&magic=suspended">
+% }
+suspended
+% if ( $num_susp_pkg ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right" WIDTH="40%">
+ <FONT COLOR="#FF0000">
+ <% my $num_cancel_pkg = $agent->num_cancel_cust_pkg %>&nbsp;
+ </FONT>
+ </TH>
+
+ <TD>
+% if ( $num_cancel_pkg ) {
+
+ <A HREF="<% $cust_pkg_link %>&magic=cancelled">
+% }
+cancelled
+% if ( $num_cancel_pkg ) {
+</A>
+% }
+
+ </TD>
+ </TR>
+
+ </TABLE>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<% $p %>graph/report_cust_pkg.html?agentnum=<% $agent->agentnum %>">Package&nbsp;Churn</A>
+ <BR><A HREF="<% $p %>search/report_cust_pay.html?agentnum=<% $agent->agentnum %>">Payments</A>
+ <BR><A HREF="<% $p %>search/report_cust_credit.html?agentnum=<% $agent->agentnum %>">Credits</A>
+ <BR><A HREF="<% $p %>search/report_receivables.cgi?agentnum=<% $agent->agentnum %>">A/R&nbsp;Aging</A>
+ <!--<BR><A HREF="<% $p %>search/money_time.cgi?agentnum=<% $agent->agentnum %>">Sales/Credits/Receipts</A>-->
+
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% my $num_reg_code = $agent->num_reg_code %>
+% if ( $num_reg_code ) {
+
+ <A HREF="<%$p%>search/reg_code.html?agentnum=<% $agent->agentnum %>">
+% }
+Unused
+% if ( $num_reg_code ) {
+</A>
+% }
+
+ <BR><A HREF="<%$p%>edit/reg_code.cgi?agentnum=<% $agent->agentnum %>">Generate codes</A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% my $num_prepay_credit = $agent->num_prepay_credit %>
+% if ( $num_prepay_credit ) {
+
+ <A HREF="<%$p%>search/prepay_credit.html?agentnum=<% $agent->agentnum %>">
+% }
+Unused
+% if ( $num_prepay_credit ) {
+</A>
+% }
+
+ <BR><A HREF="<%$p%>edit/prepay_credit.cgi?agentnum=<% $agent->agentnum %>">Generate cards</A>
+ </TD>
+% if ( $conf->config('ticket_system') ) {
+
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% if ( $agent->ticketing_queueid ) {
+
+ Queue: <% $agent->ticketing_queueid %>: <% $agent->ticketing_queue %><BR>
+% }
+
+ </TD>
+% }
+
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+% foreach my $override (
+% # sort { } want taxclass-full stuff first? and default cards (empty cardtype)
+% qsearch('agent_payment_gateway', { 'agentnum' => $agent->agentnum } )
+% ) {
+%
+
+ <TR>
+ <TD>
+ <% $override->cardtype || 'Default' %> to <% $override->payment_gateway->gateway_module %> (<% $override->payment_gateway->gateway_username %>)
+ <% $override->taxclass
+ ? ' for '. $override->taxclass. ' only'
+ : ''
+ %>
+ <FONT SIZE=-1><A HREF="<%$p%>misc/delete-agent_payment_gateway.cgi?<% $override->agentgatewaynum %>">(delete)</A></FONT>
+ </TD>
+ </TR>
+% }
+
+ <TR>
+ <TD><FONT SIZE=-1><A HREF="<%$p%>edit/agent_payment_gateway.html?agentnum=<% $agent->agentnum %>">(add override)</A></FONT></TD>
+ </TR>
+ </TABLE>
+ </TD>
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+% foreach my $override (
+% qsearch('conf', { 'agentnum' => $agent->agentnum } )
+% ) {
+%
+
+ <TR>
+ <TD>
+ <% $override->name %>&nbsp;<FONT SIZE=-1><A HREF="<%$p%>config/config-delete.cgi?<% $override->confnum %>">(delete)</A></FONT>
+ </TD>
+ </TR>
+% }
+
+ <TR>
+ <TD><FONT SIZE=-1><A HREF="<%$p%>config/config-view.cgi?agentnum=<% $agent->agentnum %>">(view/add/edit overrides)</A></FONT></TD>
+ </TR>
+ </TABLE>
+ </TD>
+
+ </TR>
+% }
+
+
+ </TABLE>
+ </BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my %search;
+if ( $cgi->param('showdisabled')
+ || !dbdef->table('agent')->column('disabled') ) {
+ %search = ();
+} else {
+ %search = ( 'disabled' => '' );
+}
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi
new file mode 100755
index 000000000..d64ff186a
--- /dev/null
+++ b/httemplate/browse/agent_type.cgi
@@ -0,0 +1,61 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Agent Types',
+ 'menubar' => [ 'Agents' =>"${p}browse/agent.cgi", ],
+ 'html_init' => $html_init,
+ 'name' => 'agent types',
+ 'query' => { 'table' => 'agent_type',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY typenum', # 'ORDER BY atype',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Agent Type',
+ 'Packages',
+ ],
+ 'fields' => [ 'typenum',
+ 'atype',
+ $packages_sub,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+'Agent types define groups of packages that you can then assign to'.
+' particular agents.<BR><BR>'.
+qq!<A HREF="${p}edit/agent_type.cgi"><I>Add a new agent type</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM agent_type';
+
+#false laziness w/access_user.html
+my $packages_sub = sub {
+my $agent_type = shift;
+
+[ map {
+ my $type_pkgs = $_;
+ #my $part_pkg = $type_pkgs->part_pkg;
+ [
+ {
+ #'data' => $part_pkg->pkg. ' - '. $part_pkg->comment,
+ 'data' => $type_pkgs->pkg. ' - '. $type_pkgs->comment,
+ 'align' => 'left',
+ 'link' => $p. 'edit/part_pkg.cgi?'. $type_pkgs->pkgpart,
+ },
+ ];
+ }
+
+ $agent_type->type_pkgs_enabled
+];
+
+};
+
+my $link = [ $p.'edit/agent_type.cgi?', 'typenum' ];
+
+</%init>
diff --git a/httemplate/browse/cust_main_county.cgi b/httemplate/browse/cust_main_county.cgi
new file mode 100755
index 000000000..736d7fdbe
--- /dev/null
+++ b/httemplate/browse/cust_main_county.cgi
@@ -0,0 +1,454 @@
+<% include( 'elements/browse.html',
+ 'title' => "Tax Rates $title",
+ 'name_singular' => 'tax rate',
+ 'menubar' => \@menubar,
+ 'html_init' => $html_init,
+ 'html_posttotal' => $html_posttotal,
+ 'html_form' => '<FORM NAME="taxesForm">',
+ 'html_foot' => $html_foot,
+ 'query' => {
+ 'table' => 'cust_main_county',
+ 'hashref' => $hashref,
+ 'order_by' =>
+ 'ORDER BY country, state, county, taxclass',
+ },
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'header2' => \@header2,
+ 'fields' => \@fields,
+ 'align' => $align,
+ 'color' => \@color,
+ 'cell_style' => \@cell_style,
+ 'links' => \@links,
+ 'link_onclicks' => \@link_onclicks,
+ )
+%>
+%
+% # <FONT SIZE=-1><A HREF="<% $p %>edit/process/cust_main_county-collapse.cgi?<% $hashref->{taxnum} %>">collapse state</A></FONT>
+% # % }
+%
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $exempt_sub = sub {
+ my $cust_main_county = shift;
+
+ my @exempt = ();
+ push @exempt,
+ sprintf("$money_char%.2f&nbsp;per&nbsp;month", $cust_main_county->exempt_amount )
+ if $cust_main_county->exempt_amount > 0;
+
+ push @exempt, 'Setup&nbsp;fee'
+ if $cust_main_county->setuptax =~ /^Y$/i;
+
+ push @exempt, 'Recurring&nbsp;fee'
+ if $cust_main_county->recurtax =~ /^Y$/i;
+
+ [ map [ {'data'=>$_} ], @exempt ];
+};
+
+my $oldrow;
+my $cell_style;
+my $cell_style_sub = sub {
+ my $row = shift;
+ if ( $oldrow ne $row ) {
+ if ( $oldrow ) {
+ if ( $oldrow->country ne $row->country ) {
+ $cell_style = 'border-top:1px solid #000000';
+ } elsif ( $oldrow->state ne $row->state ) {
+ $cell_style = 'border-top:1px solid #cccccc'; #default?
+ } elsif ( $oldrow->state eq $row->state ) {
+ #$cell_style = 'border-top:dashed 1px dark gray';
+ $cell_style = 'border-top:1px dashed #cccccc';
+ }
+ }
+ $oldrow = $row;
+ }
+ return $cell_style;
+};
+
+#my $edit_link = [ "${p}edit/cust_main_county.html", 'taxnum' ];
+my $edit_link = [ 'javascript:void(0);', sub { ''; } ];
+
+my $edit_onclick = sub {
+ my $row = shift;
+ my $taxnum = $row->taxnum;
+ include( '/elements/popup_link_onclick.html',
+ 'action' => "${p}edit/cust_main_county.html?$taxnum",
+ 'actionlabel' => 'Edit tax rate',
+ 'height' => 420,
+ #default# 'width' => 540,
+ #default# 'color' => '#333399',
+ );
+};
+
+sub expand_link {
+ my %param = @_;
+
+ my $taxnum = $param{'row'}->taxnum;
+ my $url = "${p}edit/cust_main_county-expand.cgi?$taxnum";
+
+ '<FONT SIZE="-1">'.
+ include( '/elements/popup_link.html',
+ 'label' => $param{'label'},
+ 'action' => $url,
+ 'actionlabel' => $param{'desc'},
+ 'height' => 420,
+ #default# 'width' => 540,
+ #default# 'color' => '#333399',
+ ).
+ '</FONT>';
+}
+
+sub separate_taxclasses_link {
+ my( $row ) = @_;
+ my $taxnum = $row->taxnum;
+ my $url = "${p}edit/process/cust_main_county-expand.cgi?taxclass=1;taxnum=$taxnum";
+
+ qq!<FONT SIZE="-1"><A HREF="$url">!;
+}
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#my $conf = new FS::Conf;
+#my $money_char = $conf->config('money_char') || '$';
+my $enable_taxclasses = $conf->exists('enable_taxclasses');
+
+my @menubar;
+
+my $html_init =
+ "Click on <u>add states</u> to specify a country's tax rates by state or province.
+ <BR>Click on <u>add counties</u> to specify a state's tax rates by county.";
+$html_init .= "<BR>Click on <u>separate taxclasses</u> to specify taxes per taxclass."
+ if $enable_taxclasses;
+$html_init .= '<BR><BR>';
+
+$html_init .= include('/elements/init_overlib.html');
+
+my $title = '';
+
+my $country = '';
+if ( $cgi->param('country') =~ /^(\w\w)$/ ) {
+ $country = $1;
+ $title = $country;
+}
+$cgi->delete('country');
+
+my $state = '';
+if ( $country && $cgi->param('state') =~ /^([\w \-\'\[\]]+)$/ ) {
+ $state = $1;
+ $title = "$state, $title";
+}
+$cgi->delete('state');
+
+my $county = '';
+if ( $country && $state &&
+ $cgi->param('county') =~
+ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]+)$/
+ )
+{
+ $county = $1;
+ if ( $county eq '__NONE__' ) {
+ $title = "No county, $title";
+ } else {
+ $title = "$county county, $title";
+ }
+}
+$cgi->delete('county');
+
+$title = " for $title" if $title;
+
+my $taxclass = '';
+if ( $cgi->param('taxclass') =~ /^([\w \-]+)$/ ) {
+ $taxclass = $1;
+ $title .= " for $taxclass tax class";
+}
+$cgi->delete('taxclass');
+
+if ( $country || $taxclass ) {
+ push @menubar, 'View all tax rates' => $p.'browse/cust_main_county.cgi';
+}
+
+$cgi->param('dummy', 1);
+
+my $filter_change =
+ "window.location = '". $cgi->self_url.
+ ";country=' + encodeURIComponent( document.getElementById('country').options[document.getElementById('country').selectedIndex].value ) + ".
+ "';state=' + encodeURIComponent( document.getElementById('state').options[document.getElementById('state').selectedIndex].value ) +".
+ "';county=' + encodeURIComponent( document.getElementById('county').options[document.getElementById('county').selectedIndex].value );";
+
+#restore this so pagination works
+$cgi->param('country', $country) if $country;
+$cgi->param('state', $state ) if $state;
+$cgi->param('county', $county ) if $county;
+$cgi->param('taxclass', $county ) if $taxclass;
+
+my $html_posttotal =
+ '<BR>( show country: '.
+ include('/elements/select-country.html',
+ 'country' => $country,
+ 'onchange' => $filter_change,
+ 'empty_label' => '(all)',
+ 'disable_empty' => 0,
+ 'disable_stateupdate' => 1,
+ );
+
+my %states_hash = $country ? states_hash($country) : ();
+if ( scalar(keys(%states_hash)) > 1 ) {
+ $html_posttotal .=
+ ' show state: '.
+ include('/elements/select-state.html',
+ 'country' => $country,
+ 'state' => $state,
+ 'onchange' => $filter_change,
+ 'empty_label' => '(all)',
+ 'disable_empty' => 0,
+ 'disable_countyupdate' => 1,
+ );
+} else {
+ $html_posttotal .=
+ '<SELECT NAME="state" ID="state" STYLE="display:none">'.
+ ' <OPTION VALUE="" SELECTED>'.
+ '</SELECT>';
+}
+
+my @counties = ( $country && $state ) ? counties($state, $country) : ();
+if ( scalar(@counties) > 1 ) {
+ $html_posttotal .=
+ ' show county: '.
+ include('/elements/select-county.html',
+ 'country' => $country,
+ 'state' => $state,
+ 'county' => $county,
+ 'onchange' => $filter_change,
+ 'empty_label' => '(all)',
+ 'empty_data_label' => '(none)',
+ 'empty_data_value' => '__NONE__',
+ 'disable_empty' => 0,
+ 'disable_countyupdate' => 1,
+ );
+} else {
+ $html_posttotal .=
+ '<SELECT NAME="county" ID="county" STYLE="display:none">'.
+ ' <OPTION VALUE="" SELECTED>'.
+ '</SELECT>';
+}
+
+$html_posttotal .= ' )';
+
+my $bulk_popup_link =
+ include( '/elements/popup_link_onclick.html',
+ 'action' => "${p}edit/bulk-cust_main_county.html?MAGIC_taxnum_MAGIC",
+ 'actionlabel' => 'Bulk add new tax',
+ 'nofalse' => 1,
+ 'height' => 420,
+ #default# 'width' => 540,
+ #default# 'color' => '#333399',
+ );
+
+my $html_foot = <<END;
+<SCRIPT TYPE="text/javascript">
+
+ function setAll(setTo) {
+ theForm = document.taxesForm;
+ for (i=0,n=theForm.elements.length;i<n;i++) {
+ if (theForm.elements[i].name.indexOf("cust_main_county") != -1) {
+ theForm.elements[i].checked = setTo;
+ }
+ }
+ }
+
+ function toggleAll() {
+ theForm = document.taxesForm;
+ for (i=0,n=theForm.elements.length;i<n;i++) {
+ if (theForm.elements[i].name.indexOf("cust_main_county") != -1) {
+ if ( theForm.elements[i].checked == true ) {
+ theForm.elements[i].checked = false;
+ } else {
+ theForm.elements[i].checked = true;
+ }
+ }
+ }
+ }
+
+ function bulkPopup() {
+ var bulk_popup_link = "$bulk_popup_link";
+ var bulkstring = '';
+ theForm = document.taxesForm;
+ for (i=0,n=theForm.elements.length;i<n;i++) {
+ if ( theForm.elements[i].name.indexOf("cust_main_county") != -1
+ && theForm.elements[i].checked == true
+ ) {
+ var name = theForm.elements[i].name;
+ var taxnum = name.replace(/cust_main_county/, '');
+ if ( bulkstring != '' ) {
+ bulkstring = bulkstring + ',';
+ }
+ bulkstring = bulkstring + taxnum;
+
+ }
+ }
+ if ( bulk_popup_link.length > 1920 ) { // IE 2083 URL limit
+ alert('Too many selections'); // should do some session thing...
+ return false;
+ }
+ bulk_popup_link = bulk_popup_link.replace(/MAGIC_taxnum_MAGIC/, bulkstring);
+ eval(bulk_popup_link);
+ }
+
+</SCRIPT>
+
+<BR>
+<A HREF="javascript:setAll(true)">select all</A> |
+<A HREF="javascript:setAll(false)">unselect all</A> |
+<A HREF="javascript:toggleAll()">toggle all</A>
+<BR><BR>
+<A HREF="javascript:void(0);" onClick="bulkPopup();">Add new tax to selected</A>
+
+END
+
+my $hashref = {};
+my $count_query = 'SELECT COUNT(*) FROM cust_main_county';
+if ( $country ) {
+ $hashref->{'country'} = $country;
+ $count_query .= ' WHERE country = '. dbh->quote($country);
+}
+if ( $state ) {
+ $hashref->{'state'} = $state;
+ $count_query .= ' AND state = '. dbh->quote($state);
+}
+if ( $county ) {
+ if ( $county eq '__NONE__' ) {
+ $hashref->{'county'} = '';
+ $count_query .= " AND ( county = '' OR county IS NULL ) ";
+ } else {
+ $hashref->{'county'} = $county;
+ $count_query .= ' AND county = '. dbh->quote($county);
+ }
+}
+if ( $taxclass ) {
+ $hashref->{'taxclass'} = $taxclass;
+ $count_query .= ( $count_query =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ ' taxclass = '. dbh->quote($taxclass);
+}
+
+
+$cell_style = '';
+
+my @header = ( 'Country', 'State/Province', 'County',);
+my @header2 = ( '', '', '', );
+my @links = ( '', '', '', );
+my @link_onclicks = ( '', '', '', );
+my $align = 'lll';
+
+my @fields = (
+ sub { my $country = shift->country;
+ code2country($country). " ($country)";
+ },
+ sub { state_label($_[0]->state, $_[0]->country).
+ ( $_[0]->state
+ ? ''
+ : '&nbsp'. expand_link( desc => 'Add States',
+ row => $_[0],
+ label => 'add&nbsp;states',
+ )
+ )
+ },
+ sub { $_[0]->county || '(all)&nbsp'.
+ expand_link( desc => 'Add Counties',
+ row => $_[0],
+ label => 'add&nbsp;counties',
+ )
+ },
+);
+
+my @color = (
+ '000000',
+ sub { shift->state ? '000000' : '999999' },
+ sub { shift->county ? '000000' : '999999' },
+);
+
+if ( $conf->exists('enable_taxclasses') ) {
+ push @header, qq!Tax class (<A HREF="${p}edit/part_pkg_taxclass.html">add new</A>)!;
+ push @header2, '(per-package classification)';
+ push @fields, sub { $_[0]->taxclass || '(all)&nbsp'.
+ separate_taxclasses_link($_[0], 'Separate Taxclasses').
+ 'separate&nbsp;taxclasses</A></FONT>'
+ };
+ push @color, sub { shift->taxclass ? '000000' : '999999' };
+ push @links, '';
+ push @link_onclicks, '';
+ $align .= 'l';
+}
+
+push @header,
+ '', #checkbox column
+ 'Tax name',
+ 'Rate', #'Tax',
+ 'Exemptions',
+ ;
+
+push @header2,
+ '',
+ '(printed on invoices)',
+ '',
+ '',
+ ;
+
+my $newregion = 1;
+my $cb_oldrow = '';
+my $cb_sub = sub {
+ my $cust_main_county = shift;
+
+ if ( $cb_oldrow ) {
+ if ( $cb_oldrow->country ne $cust_main_county->country
+ || $cb_oldrow->state ne $cust_main_county->state
+ || $cb_oldrow->county ne $cust_main_county->county
+ || $cb_oldrow->taxclass ne $cust_main_county->taxclass )
+ {
+ $newregion = 1;
+ } else {
+ $newregion = 0;
+ }
+
+ } else {
+ $newregion = 1;
+ }
+ $cb_oldrow = $cust_main_county;
+
+ if ( $newregion ) {
+ my $taxnum = $cust_main_county->taxnum;
+ qq!<INPUT NAME="cust_main_county$taxnum" TYPE="checkbox" VALUE="1">!;
+ } else {
+ '';
+ }
+};
+
+push @fields,
+ $cb_sub,
+ sub { shift->taxname || 'Tax' },
+ sub { shift->tax. '%&nbsp;<FONT SIZE="-1">(edit)</FONT>' },
+ $exempt_sub,
+;
+
+push @color,
+ '000000',
+ sub { shift->taxname ? '000000' : '666666' },
+ sub { shift->tax ? '000000' : '666666' },
+ '000000',
+;
+
+$align .= 'clrl';
+
+my @cell_style = map $cell_style_sub, (1..scalar(@header));
+
+push @links, '', '', $edit_link, '';
+push @link_onclicks, '', '', $edit_onclick, '';
+
+</%init>
diff --git a/httemplate/browse/elements/browse.html b/httemplate/browse/elements/browse.html
new file mode 100644
index 000000000..513c2c4e9
--- /dev/null
+++ b/httemplate/browse/elements/browse.html
@@ -0,0 +1,6 @@
+<% include( '/search/elements/search.html',
+ 'disable_download' => 1,
+ 'disable_nonefound' => 1,
+ @_,
+ )
+%>
diff --git a/httemplate/browse/inventory_class.html b/httemplate/browse/inventory_class.html
new file mode 100644
index 000000000..8ce131ac2
--- /dev/null
+++ b/httemplate/browse/inventory_class.html
@@ -0,0 +1,93 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Inventory Classes',
+ 'name' => 'inventory classes',
+ 'menubar' => [ 'Add a new inventory class' =>
+ $p.'edit/inventory_class.html',
+ ],
+ 'query' => { 'table' => 'inventory_class', },
+ 'count_query' => 'SELECT COUNT(*) FROM inventory_class',
+ 'header' => [ '#', 'Inventory class', 'Inventory' ],
+ 'fields' => [ 'classnum',
+ 'classname',
+ sub {
+ #my $inventory_class = shift;
+ my $i_c = shift;
+
+ my $link =
+ $p. 'search/inventory_item.html?'.
+ 'classnum='. $i_c->classnum;
+
+ my %actioncol = ();
+ foreach ( keys %inv_action_link ) {
+ my($label, $baseurl, $method) =
+ @{ $inv_action_link{$_} };
+ my $url = $baseurl. $i_c->$method();
+ $actioncol{$_} =
+ '<FONT SIZE="-1">'.
+ '('.
+ '<A HREF="'.$url.'">'.
+ $label.
+ '</A>'.
+ ')'.
+ '</FONT>';
+ }
+
+ my %num = map {
+ $_ => $i_c->$_();
+ } keys %labels;
+
+ [ map {
+ [
+ {
+ 'data' => '<B>'. $num{$_}. '</B>',
+ 'align' => 'right',
+ },
+ {
+ 'data' => $labels{$_},
+ 'align' => 'left',
+ 'link' => ( $num{$_}
+ ? $link.$link{$_}
+ : ''
+ ),
+ },
+ { 'data' => $actioncol{$_},
+ 'align' => 'left',
+ },
+ ]
+ } keys %labels
+ ];
+ },
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+tie my %labels, 'Tie::IxHash',
+ 'num_avail' => 'Available', # <FONT SIZE="-1"><A HREF="eventually">(upload batch)</A></FONT>',
+ 'num_used' => 'In use', #'Used', #'Allocated',
+ 'num_total' => 'Total',
+;
+
+my %link = (
+ 'num_avail' => ';avail=1',
+ 'num_used' => ';used=1',
+ 'num_total' => '',
+);
+
+my %inv_action_link = (
+ 'num_avail' => [ 'upload batch',
+ $p.'misc/inventory_item-import.html?classnum=',
+ 'classnum'
+ ],
+);
+
+my $link = [ "${p}edit/inventory_class.html?", 'classnum' ];
+
+</%init>
diff --git a/httemplate/browse/invoice_template.html b/httemplate/browse/invoice_template.html
new file mode 100644
index 000000000..0bbfb2452
--- /dev/null
+++ b/httemplate/browse/invoice_template.html
@@ -0,0 +1,124 @@
+<% include("/elements/header.html", 'Invoice templates') %>
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Template</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">HTML</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Print/PDF (typeset)</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Plaintext</TH>
+</TR>
+
+% foreach my $templatename ( '', @templatenames ) {
+% my $tname = length($templatename) ? "_$templatename" : '';
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $display = length($templatename) ? $templatename : '<i>(Default)</i>';
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $display %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+
+% my( $logo_label, $logo_link_label)= length( $templatename )
+% ? labels("logo_$templatename.png")
+% : ( '', 'edit' );
+ <% $logo_label %> Logo
+ (<A HREF="<% $p %>edit/invoice_logo.html?type=png;name=<% $templatename %>"><% $logo_link_label %></A>)
+ <BR>
+
+% foreach my $suffix (qw( returnaddress notes footer), '' ) {
+% my $file = "invoice_html$suffix$tname";
+% my($label, $link_label) = length($templatename)
+% ? labels($file)
+% : ( '', 'edit' );
+
+ <% $label %> <% $suffix2name{$suffix} %>
+ (<A HREF="<% $p %>edit/invoice_template.html?type=html;suffix=<% $suffix %>;name=<% $templatename %>"><% $link_label %></A>)
+ <BR>
+
+% }
+
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+
+% my( $logo_label, $logo_link_label)= length( $templatename )
+% ? labels("logo_$templatename.eps")
+% : ( '', 'edit' );
+ <% $logo_label %> Logo
+ (<A HREF="<% $p %>edit/invoice_logo.html?type=eps;name=<% $templatename %>"><% $logo_link_label %></A>)
+ <BR>
+
+% foreach my $suffix (qw( returnaddress notes footer smallfooter), '' ) {
+% my $file = "invoice_latex$suffix$tname";
+% my($label, $link_label) = length($templatename)
+% ? labels($file)
+% : ( '', 'edit' );
+
+ <% $label %> <% $suffix2name{$suffix} %>
+ (<A HREF="<% $p %>edit/invoice_template.html?type=latex;suffix=<% $suffix %>;name=<% $templatename %>"><% $link_label %></A>)
+ <BR>
+
+% }
+
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+
+% my( $txt_label, $txtlink_label)=
+% length( $templatename )
+% ? labels("invoice_template_$templatename.png")
+% : ( 'Main template', 'edit' );
+ <% $txt_label %>
+ (<A HREF="<% $p %>edit/invoice_template.html?type=text;name=<% $templatename %>"><% $txtlink_label %></A>)
+
+ </TD>
+
+ </TR>
+
+% }
+
+<% include("/elements/footer.html") %>
+
+<%once>
+
+my %suffix2name = (
+ 'returnaddress' => 'Return address',
+ 'notes' => 'Notes',
+ 'footer' => 'Footer',
+ 'smallfooter' => 'Small footer',
+ '' => 'Main template',
+);
+
+my $conf = new FS::Conf;
+
+sub labels {
+ my $filename = shift;
+ if ( $conf->exists($filename) ) {
+ ( 'Custom', 'edit' );
+ } else {
+ ( 'Standard', 'customize' );
+ }
+}
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @templatenames = $conf->invoice_templatenames;
+
+</%init>
diff --git a/httemplate/browse/msgcat.cgi b/httemplate/browse/msgcat.cgi
new file mode 100755
index 000000000..2c916dc9f
--- /dev/null
+++ b/httemplate/browse/msgcat.cgi
@@ -0,0 +1,44 @@
+<% include('/elements/header.html', "View Message catalog", menubar(
+ 'Edit message catalog' => $p. "edit/msgcat.cgi",
+)) %>
+<% $widget->html %>
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $widget = new HTML::Widgets::SelectLayers(
+ 'selected_layer' => 'en_US',
+ 'options' => { 'en_US'=>'en_US' },
+ 'layer_callback' => sub {
+ my $layer = shift;
+ my $html = "<BR>Messages for locale $layer<BR>". table().
+ "<TR><TH COLSPAN=2>Code</TH>".
+ "<TH>Message</TH>";
+ $html .= "<TH>en_US Message</TH>" unless $layer eq 'en_US';
+ $html .= '</TR>';
+
+ #foreach my $msgcat ( sort { $a->msgcode cmp $b->msgcode }
+ # qsearch('msgcat', { 'locale' => $layer } ) ) {
+ foreach my $msgcat ( qsearch('msgcat', { 'locale' => $layer } ) ) {
+ $html .= '<TR><TD>'. $msgcat->msgnum. '</TD>'.
+ '<TD>'. $msgcat->msgcode. '</TD>'.
+ '<TD>'. $msgcat->msg. '</TD>';
+ unless ( $layer eq 'en_US' ) {
+ my $en_msgcat = qsearchs('msgcat', {
+ 'locale' => 'en_US',
+ 'msgcode' => $msgcat->msgcode,
+ } );
+ $html .= '<TD>'. $en_msgcat->msg. '</TD>';
+ }
+ $html .= '</TR>';
+ }
+
+ $html .= '</TABLE>';
+ $html;
+ },
+
+);
+
+</%init>
diff --git a/httemplate/browse/nas.cgi b/httemplate/browse/nas.cgi
new file mode 100755
index 000000000..b5e0ef8b7
--- /dev/null
+++ b/httemplate/browse/nas.cgi
@@ -0,0 +1,82 @@
+%print header('NAS ports');
+%
+%my $now = time;
+%
+%foreach my $nas ( sort { $a->nasnum <=> $b->nasnum } qsearch( 'nas', {} ) ) {
+% print $nas->nasnum. ": ". $nas->nas. " ".
+% $nas->nasfqdn. " (". $nas->nasip. ") ".
+% "as of ". time2str("%c",$nas->last).
+% " (". &pretty_interval($now - $nas->last). " ago)<br>".
+% &table(). "<TR><TH>Nas<BR>Port #</TH><TH>Global<BR>Port #</BR></TH>".
+% "<TH>IP address</TH><TH>User</TH><TH>Since</TH><TH>Duration</TH><TR>",
+% ;
+% foreach my $port ( sort {
+% $a->nasport <=> $b->nasport || $a->portnum <=> $b->portnum
+% } qsearch( 'port', { 'nasnum' => $nas->nasnum } ) ) {
+% my $session = $port->session;
+% my($user, $since, $pretty_since, $duration);
+% if ( ! $session ) {
+% $user = "(empty)";
+% $since = 0;
+% $pretty_since = "(never)";
+% $duration = '';
+% } elsif ( $session->logout ) {
+% $user = "(empty)";
+% $since = $session->logout;
+% } else {
+% my $svc_acct = $session->svc_acct;
+% $user = "<A HREF=\"$p/view/svc_acct.cgi?". $svc_acct->svcnum. "\">".
+% $svc_acct->username. "</A>";
+% $since = $session->login;
+% }
+% $pretty_since = time2str("%c", $since) if $since;
+% $duration = pretty_interval( $now - $since ). " ago"
+% unless defined($duration);
+% print "<TR><TD>". $port->nasport. "</TD><TD>". $port->portnum. "</TD><TD>".
+% $port->ip. "</TD><TD>$user</TD><TD>$pretty_since".
+% "</TD><TD>$duration</TD></TR>"
+% ;
+% }
+% print "</TABLE><BR>";
+%}
+%
+%#Time::Duration??
+%sub pretty_interval {
+% my $interval = shift;
+% my %howlong = (
+% '604800' => 'week',
+% '86400' => 'day',
+% '3600' => 'hour',
+% '60' => 'minute',
+% '1' => 'second',
+% );
+%
+% my $pretty = "";
+% foreach my $key ( sort { $b <=> $a } keys %howlong ) {
+% my $value = int( $interval / $key );
+% if ( $value ) {
+% if ( $value == 1 ) {
+% $pretty .=
+% ( $howlong{$key} eq 'hour' ? 'an ' : 'a ' ). $howlong{$key}. " "
+% } else {
+% $pretty .= $value. ' '. $howlong{$key}. 's ';
+% }
+% }
+% $interval -= $value * $key;
+% }
+% $pretty =~ /^\s*(\S.*\S)\s*$/;
+% $1;
+%}
+%
+%#print &table(), <<END;
+%#<TR>
+%# <TH>#</TH>
+%# <TH>NAS</
+%
+
+<%init>
+
+#this hasn't been used in ages, and isn't linked from anywhere...
+die 'NAS browse not currently active';
+
+</%init>
diff --git a/httemplate/browse/part_bill_event.cgi b/httemplate/browse/part_bill_event.cgi
new file mode 100755
index 000000000..11bc14e5c
--- /dev/null
+++ b/httemplate/browse/part_bill_event.cgi
@@ -0,0 +1,122 @@
+<% include('/elements/header.html', 'Invoice Event Listing') %>
+
+ <FONT SIZE="+1">Invoice events are the deprecated, old-style actions taken on open invoices. Any events still listed here should be migrated to new-style events.</FONT><BR><BR>
+
+<A HREF="<% $p %>edit/part_bill_event.cgi"><I>Add a new invoice event</I></A>
+<BR><BR>
+
+<% $total %> events
+<% $cgi->param('showdisabled')
+ ? do { $cgi->param('showdisabled', 0);
+ '( <a href="'. $cgi->self_url. '">hide disabled events</a> )'; }
+ : do { $cgi->param('showdisabled', 1);
+ '( <a href="'. $cgi->self_url. '">show disabled events</a> )'; }
+%>
+<BR><BR>
+% tie my %payby, 'Tie::IxHash', FS::payby->cust_payby2longname;
+% tie my %freq, 'Tie::IxHash', '1d' => 'daily', '1m' => 'monthly';
+% foreach my $payby ( keys %payby ) {
+% my $oldfreq = '';
+%
+% my @payby_part_bill_event =
+% grep { $payby eq $_->payby }
+% sort { ( $a->freq || '1d') cmp ( $b->freq || '1d' ) # for now
+% || $a->seconds <=> $b->seconds
+% || $a->weight <=> $b->weight
+% || $a->eventpart <=> $b->eventpart
+% }
+% @part_bill_event;
+%
+%
+% if ( @payby_part_bill_event ) {
+
+
+ <% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+%
+% foreach my $part_bill_event ( @payby_part_bill_event ) {
+% my $url = "${p}edit/part_bill_event.cgi?". $part_bill_event->eventpart;
+% my $delay = duration_exact($part_bill_event->seconds);
+% ( my $plandata = $part_bill_event->plandata ) =~ s/\n/<BR>/go;
+% my $freq = $part_bill_event->freq || '1d';
+% my $reason = $part_bill_event->reasontext ;
+%
+% if ( $oldfreq ne $freq ) {
+
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#999999" COLSPAN=<% $cgi->param('showdisabled') ? 7 : 8 %>><% ucfirst($freq{$freq}) %> event tests for <FONT SIZE="+1"><I><% $payby{$payby} %> customers</I></FONT></TH>
+ </TR>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<% $cgi->param('showdisabled') ? 2 : 3 %>>Event</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">After</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Action</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Reason</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Options</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Code</TH>
+ </TR>
+%
+% $oldfreq = $freq;
+% $bgcolor = '';
+%
+% }
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+
+
+ <TR>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $url %>">
+ <% $part_bill_event->eventpart %></A></TD>
+% unless ( $cgi->param('showdisabled') ) {
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $part_bill_event->disabled ? 'DISABLED' : '' %></TD>
+% }
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $url %>">
+ <% $part_bill_event->event %></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $delay %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $part_bill_event->plan %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $reason %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $plandata %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><FONT SIZE="-1">
+ <% $part_bill_event->eventcode %></FONT></TD>
+ </TR>
+% }
+
+ </TABLE>
+ <BR><BR>
+% }
+% }
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my %search;
+if ( $cgi->param('showdisabled') ) {
+%search = ();
+} else {
+%search = ( 'disabled' => '' );
+}
+
+my @part_bill_event = qsearch('part_bill_event', \%search );
+my $total = scalar(@part_bill_event);
+
+</%init>
diff --git a/httemplate/browse/part_event.html b/httemplate/browse/part_event.html
new file mode 100644
index 000000000..674004bc7
--- /dev/null
+++ b/httemplate/browse/part_event.html
@@ -0,0 +1,167 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Billing Event Definitions',
+ 'html_init' => $html_init,
+ 'name' => 'billing event definitions',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Edit global billing events',
+ 'agent_pos' => 3,
+ 'query' => { 'select' => 'part_event.*',
+ 'table' => 'part_event',
+ 'addl_from' => $join_conditions,
+ 'hashref' => {},
+ 'order_by' => $order_conditions,
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Event',
+ 'Type',
+ 'Check freq.',
+ 'Conditions',
+ 'Action',
+ ],
+ 'fields' => [ 'eventpart',
+ 'event',
+ $eventtable_sub,
+ $check_freq_sub,
+ $conditions_sub,
+ $action_sub,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ '',
+ '',
+ '',
+ ],
+ 'align' => 'rllccc',
+ )
+%>
+<%once>
+
+my $eventtable_labels = FS::part_event->eventtable_labels;
+my $eventtable_sub = sub { $eventtable_labels->{ shift->eventtable }; };
+
+my $check_freq_labels = FS::part_event->check_freq_labels;
+my $check_freq_sub = sub { $check_freq_labels->{ shift->check_freq }; };
+
+my $conditions_sub = sub {
+ my $part_event = shift;
+ my $addl = 0;
+
+ [
+ map {
+ my $part_event_condition = $_;
+ my %options = $part_event_condition->options;
+
+ [
+ {
+ 'data' => $part_event_condition->description,
+ 'width' => '100%',
+ 'align' => 'center',
+ 'colspan' => 2,
+ 'style' => ( $addl++ ? 'border-top: 1px solid gray' : '' ),
+ },
+ ],
+
+ map {
+
+ my $data = $options{$_};
+ if ( ref($data) ) {
+ $data = join('<BR>', keys %$data); #XXX display hash values too?
+ }
+
+ [
+ {
+ 'data' => $part_event_condition->option_label($_). ':',
+ 'align' => 'right',
+ 'valign' => 'top',
+ 'size' => '-1',
+ },
+ {
+ 'data' => $data,
+ 'align' => 'left',
+ 'size' => '-1',
+ },
+ ];
+
+ } keys %options
+
+ }
+ $part_event->part_event_condition
+
+ ];
+
+};
+
+my $action_sub = sub {
+ my $part_event = shift;
+
+ my %options = $part_event->options;
+
+ [
+
+ [
+ {
+ 'data' => $part_event->description,
+ 'width' => '100%',
+ 'align' => 'center',
+ 'colspan' => 2,
+ },
+ ],
+
+ map {
+ [
+ {
+ 'data' => $part_event->option_label($_). ':',
+ 'align' => 'right',
+ 'size' => '-1',
+ },
+ {
+ 'data' => $options{$_},
+ 'align' => 'left',
+ 'size' => '-1',
+ },
+ ];
+ }
+
+ keys %options
+ ];
+
+};
+
+my $link = [ $p.'edit/part_event.html?', 'eventpart' ];
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit billing events')
+ || $FS::CurrentUser::CurrentUser->access_right('Edit global billing events');
+
+my $html_init =
+ #XXX better description
+ 'Events are billing, collection or other actions triggered when certain '.
+ 'customer, invoice, package or other conditions are met.<BR><BR>'.
+ qq!<FORM METHOD="POST" ACTION="${p}edit/part_event.html">!.
+ qq!<A HREF="${p}edit/part_event.html"><I>Add a new event</I></A>!.
+ '&nbsp;or&nbsp;<SELECT NAME="clone"><OPTION></OPTION>';
+
+foreach my $part_event ( qsearch('part_event', {'diabled'=>''}) ) {
+ $html_init .= '<OPTION VALUE="'. $part_event->eventpart. '">'.
+ $part_event->event. '</OPTION>';
+}
+
+$html_init .= '</SELECT><INPUT TYPE="submit" VALUE="Clone existing event">'.
+ '</FORM><BR>';
+
+my $count_query = 'SELECT COUNT(*) FROM part_event WHERE '.
+ $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'Edit global billing events',
+ );
+
+my $join_conditions = FS::part_event_condition->join_conditions_sql;
+my $order_conditions = FS::part_event_condition->order_conditions_sql;
+
+</%init>
diff --git a/httemplate/browse/part_export.cgi b/httemplate/browse/part_export.cgi
new file mode 100755
index 000000000..1cd201360
--- /dev/null
+++ b/httemplate/browse/part_export.cgi
@@ -0,0 +1,65 @@
+<% include("/elements/header.html", "Export Listing") %>
+
+Provisioning services to external machines, databases and APIs.<BR><BR>
+
+<A HREF="<% $p %>edit/part_export.cgi"><I>Add a new export</I></A><BR><BR>
+
+<SCRIPT>
+function part_export_areyousure(href) {
+ if (confirm("Are you sure you want to delete this export?") == true)
+ window.location.href = href;
+}
+</SCRIPT>
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+ <TR>
+ <TH COLSPAN=2 CLASS="grid" BGCOLOR="#cccccc">Export</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Options</TH>
+ </TR>
+
+% foreach my $part_export ( sort {
+% $a->getfield('exportnum') <=> $b->getfield('exportnum')
+% } qsearch('part_export',{})
+% ) {
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>"><% $part_export->exportnum %></A></TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $part_export->exporttype %> to <% $part_export->machine %> (<A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>">edit</A>&nbsp;|&nbsp;<A HREF="javascript:part_export_areyousure('<% $p %>misc/delete-part_export.cgi?<% $part_export->exportnum %>')">delete</A>)</TD>
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <% itable() %>
+% my %opt = $part_export->options;
+% foreach my $opt ( keys %opt ) {
+
+ <TR>
+ <TD ALIGN="right" VALIGN="top" WIDTH="33%"><% $opt %>:&nbsp;</TD>
+ <TD ALIGN="left" WIDTH="67%"><% encode_entities($opt{$opt}) %></TD>
+ </TR>
+% }
+
+ </TABLE>
+ </TD>
+
+ </TR>
+
+% }
+
+</TABLE>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+</%init>
diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
new file mode 100755
index 000000000..801c09f8f
--- /dev/null
+++ b/httemplate/browse/part_pkg.cgi
@@ -0,0 +1,367 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Package Definitions',
+ 'html_init' => $html_init,
+ 'name' => 'package definitions',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 3,
+ 'agent_virt' => 1,
+ 'agent_null_right' => [ $edit, $edit_global ],
+ 'agent_null_right_link' => $edit_global,
+ 'agent_pos' => 5,
+ 'query' => { 'select' => $select,
+ 'table' => 'part_pkg',
+ 'hashref' => {},
+ 'extra_sql' => $extra_sql,
+ 'order_by' => "ORDER BY $orderby"
+ },
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'links' => \@links,
+ 'align' => $align,
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $edit = 'Edit package definitions';
+my $edit_global = 'Edit global package definitions';
+my $acl_edit = $curuser->access_right($edit);
+my $acl_edit_global = $curuser->access_right($edit_global);
+my $acl_config = $curuser->access_right('Configuration'); #to edit services
+ #and agent types
+
+die "access denied"
+ unless $acl_edit || $acl_edit_global;
+
+my $conf = new FS::Conf;
+my $taxclasses = $conf->exists('enable_taxclasses');
+my $money_char = $conf->config('money_char') || '$';
+
+my $select = '*';
+my $orderby = 'pkgpart';
+if ( $cgi->param('active') ) {
+ $orderby = 'num_active DESC';
+}
+
+my $extra_sql = '';
+
+unless ( $acl_edit_global ) {
+ $extra_sql .= ' WHERE '. FS::part_pkg->curuser_pkgs_sql;
+}
+
+my $agentnums = join(',', $curuser->agentnums);
+my $count_cust_pkg = "
+ SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )
+ WHERE cust_pkg.pkgpart = part_pkg.pkgpart
+ AND cust_main.agentnum IN ($agentnums)
+";
+
+$select = "
+
+ *,
+
+ ( $count_cust_pkg
+ AND ( cancel IS NULL OR cancel = 0 )
+ AND ( susp IS NULL OR susp = 0 )
+ ) AS num_active,
+
+ ( $count_cust_pkg
+ AND ( cancel IS NULL OR cancel = 0 )
+ AND susp IS NOT NULL AND susp != 0
+ ) AS num_suspended,
+
+ ( $count_cust_pkg
+ AND cancel IS NOT NULL AND cancel != 0
+ ) AS num_cancelled
+
+";
+
+my $html_init;
+#unless ( $cgi->param('active') ) {
+ $html_init = qq!
+ One or more service definitions are grouped together into a package
+ definition and given pricing information. Customers purchase packages
+ rather than purchase services directly.<BR><BR>
+ <FORM METHOD="POST" ACTION="${p}edit/part_pkg.cgi">
+ <A HREF="${p}edit/part_pkg.cgi"><I>Add a new package definition</I></A>
+ or
+ !.include('/elements/select-part_pkg.html', 'element_name' => 'clone' ). qq!
+ <INPUT TYPE="submit" VALUE="Clone existing package">
+ </FORM>
+ <BR><BR>
+ !;
+#}
+
+# ------
+
+my $link = [ $p.'edit/part_pkg.cgi?', 'pkgpart' ];
+
+my @header = ( '#', 'Package', 'Comment' );
+my @fields = ( 'pkgpart', 'pkg', 'comment' );
+my $align = 'rll';
+my @links = ( $link, $link, '' );
+
+unless ( 0 ) { #already showing only one class or something?
+ push @header, 'Class';
+ push @fields, sub { shift->classname || '(none)'; };
+ $align .= 'l';
+}
+
+tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() };
+
+tie my %plan_labels, 'Tie::IxHash',
+ map { $_ => ( $plans{$_}->{'shortname'} || $plans{$_}->{'name'} ) }
+ keys %plans;
+
+push @header, 'Pricing';
+$align .= 'r'; #?
+push @fields, sub {
+ my $part_pkg = shift;
+ (my $plan = $plan_labels{$part_pkg->plan} ) =~ s/ /&nbsp;/g;
+ my $is_recur = ( $part_pkg->freq ne '0' );
+
+ [
+ [
+ { data =>$plan,
+ align=>'center',
+ colspan=>2,
+ },
+ ],
+ [
+ { data =>$money_char.
+ sprintf('%.2f', $part_pkg->option('setup_fee') ),
+ align=>'right'
+ },
+ { data => ( $is_recur ? ' setup' : ' one-time' ),
+ align=>'left',
+ },
+ ],
+ [
+ { data=>( $is_recur
+ ? $money_char.sprintf('%.2f ', $part_pkg->option('recur_fee') )
+ : $part_pkg->freq_pretty
+ ),
+ align=> ( $is_recur ? 'right' : 'center' ),
+ colspan=> ( $is_recur ? 1 : 2 ),
+ },
+ ( $is_recur
+ ? { data => ( $is_recur ? $part_pkg->freq_pretty : '' ),
+ align=>'left',
+ }
+ : ()
+ ),
+ ],
+ ( map {
+ my $dst_pkg = $_->dst_pkg;
+ [
+ { data => 'Add-on:&nbsp;'.$dst_pkg->pkg_comment,
+ align=>'center', #?
+ colspan=>2,
+ }
+ ]
+ }
+ $part_pkg->bill_part_pkg_link
+ ),
+ ];
+
+# $plan_labels{$part_pkg->plan}.'<BR>'.
+# $money_char.sprintf('%.2f setup<BR>', $part_pkg->option('setup_fee') ).
+# ( $part_pkg->freq ne '0'
+# ? $money_char.sprintf('%.2f ', $part_pkg->option('recur_fee') )
+# : ''
+# ).
+# $part_pkg->freq_pretty; #.'<BR>'
+};
+
+###
+# Agent goes here if displayed
+###
+
+#agent type
+if ( $acl_edit_global ) {
+ #really we just want a count, but this is fine unless someone has tons
+ my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
+ if ( scalar(@all_agent_types) > 1 ) {
+ push @header, 'Agent types';
+ my $typelink = $p. 'edit/agent_type.cgi?';
+ push @fields, sub { my $part_pkg = shift;
+ [
+ map { warn $_;
+ my $agent_type = $_->agent_type;
+ warn $agent_type;
+ [
+ { 'data' => $agent_type->atype, #escape?
+ 'align' => 'left',
+ 'link' => ( $acl_config
+ ? $typelink.
+ $agent_type->typenum
+ : ''
+ ),
+ },
+ ];
+ }
+ $part_pkg->type_pkgs
+ ];
+ };
+ $align .= 'l';
+ }
+}
+
+#if ( $cgi->param('active') ) {
+ push @header, 'Customer<BR>packages';
+ my %col = (
+ 'active' => '00CC00',
+ 'suspended' => 'FF9900',
+ 'cancelled' => 'FF0000',
+ #'one-time charge' => '000000',
+ 'charge' => '000000',
+ );
+ my $cust_pkg_link = $p. 'search/cust_pkg.cgi?pkgpart=';
+ push @fields, sub { my $part_pkg = shift;
+ [
+ map {
+ my $magic = $_;
+ my $label = $_;
+ if ( $magic eq 'active' && $part_pkg->freq == 0 ) {
+ $magic = 'inactive';
+ #$label = 'one-time charge',
+ $label = 'charge',
+ }
+
+ [
+ {
+ 'data' => '<B><FONT COLOR="#'. $col{$label}. '">'.
+ $part_pkg->get("num_$_").
+ '</FONT></B>',
+ 'align' => 'right',
+ },
+ {
+ 'data' => $label.
+ ( $part_pkg->get("num_$_") != 1
+ && $label =~ /charge$/
+ ? 's'
+ : ''
+ ),
+ 'align' => 'left',
+ 'link' => ( $part_pkg->get("num_$_")
+ ? $cust_pkg_link.
+ $part_pkg->pkgpart.
+ ";magic=$magic"
+ : ''
+ ),
+ },
+ ],
+ } (qw( active suspended cancelled ))
+ ]; };
+ $align .= 'r';
+#}
+
+if ( $taxclasses ) {
+ push @header, 'Taxclass';
+ push @fields, sub { shift->taxclass() || '&nbsp;'; };
+ $align .= 'l';
+}
+
+push @header, 'Plan options',
+ 'Services';
+ #'Service', 'Quan', 'Primary';
+
+push @fields,
+ sub {
+ my $part_pkg = shift;
+ if ( $part_pkg->plan ) {
+
+ my %options = $part_pkg->options;
+
+ [ map {
+ [
+ { 'data' => $_,
+ 'align' => 'right',
+ },
+ { 'data' => $part_pkg->format($_,$options{$_}),
+ 'align' => 'left',
+ },
+ ];
+ }
+ grep { $options{$_} =~ /\S/ }
+ grep { $_ !~ /^(setup|recur)_fee$/ }
+ keys %options
+ ];
+
+ } else {
+
+ [ map { [
+ { 'data' => uc($_),
+ 'align' => 'right',
+ },
+ {
+ 'data' => $part_pkg->$_(),
+ 'align' => 'left',
+ },
+ ];
+ }
+ (qw(setup recur))
+ ];
+
+ }
+
+ },
+
+ sub {
+ my $part_pkg = shift;
+
+ [
+ (map {
+ my $pkg_svc = $_;
+ my $part_svc = $pkg_svc->part_svc;
+ my $svc = $part_svc->svc;
+ if ( $pkg_svc->primary_svc =~ /^Y/i ) {
+ $svc = "<B>$svc (PRIMARY)</B>";
+ }
+ $svc =~ s/ +/&nbsp;/g;
+
+ [
+ {
+ 'data' => '<B>'. $pkg_svc->quantity. '</B>',
+ 'align' => 'right'
+ },
+ {
+ 'data' => $svc,
+ 'align' => 'left',
+ 'link' => ( $acl_config
+ ? $p. 'edit/part_svc.cgi?'.
+ $part_svc->svcpart
+ : ''
+ ),
+ },
+ ];
+ }
+ sort { $b->primary_svc =~ /^Y/i
+ <=> $a->primary_svc =~ /^Y/i
+ }
+ $part_pkg->pkg_svc('disable_linked'=>1)
+ ),
+ ( map {
+ my $dst_pkg = $_->dst_pkg;
+ [
+ { data => 'Add-on:&nbsp;'.$dst_pkg->pkg_comment,
+ align=>'center', #?
+ colspan=>2,
+ }
+ ]
+ }
+ $part_pkg->svc_part_pkg_link
+ )
+ ];
+
+ };
+
+$align .= 'lrl'; #rr';
+
+# --------
+
+my $count_query = "SELECT COUNT(*) FROM part_pkg $extra_sql";
+
+</%init>
diff --git a/httemplate/browse/part_pkg_taxproduct.cgi b/httemplate/browse/part_pkg_taxproduct.cgi
new file mode 100755
index 000000000..7e0cb8191
--- /dev/null
+++ b/httemplate/browse/part_pkg_taxproduct.cgi
@@ -0,0 +1,263 @@
+<% include( 'elements/browse.html',
+ 'title' => "Tax Products $title",
+ 'name_singular' => 'tax product',
+ 'menubar' => \@menubar,
+ 'html_init' => $html_init,
+ 'query' => {
+ 'table' => 'part_pkg_taxproduct',
+ 'hashref' => $hashref,
+ 'order_by' => 'ORDER BY description',
+ 'extra_sql' => $extra_sql,
+ },
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'align' => $align,
+ 'links' => \@links,
+ 'link_onclicks' => \@link_onclicks,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+
+my $select_link = [ 'javascript:void(0);', sub { ''; } ];
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @menubar;
+my $title = '';
+my $onclick = 'cClick';
+
+my $data_vendor = '';
+if ( $cgi->param('data_vendor') =~ /^(\w+)$/ ) {
+ $data_vendor = $1;
+ $title = "$data_vendor";
+}
+$cgi->delete('data_vendor');
+
+$title = " for $title" if $title;
+
+my $taxproductnum = $1
+ if ( $cgi->param('taxproductnum') =~ /^(\d+)$/ );
+my $tax_group = $1
+ if ( $cgi->param('tax_group') =~ /^([- \w\(\).\/]+)$/ );
+my $tax_item = $1
+ if ( $cgi->param('tax_item') =~ /^([- \w\(\).\/&%]+)$/ );
+my $tax_provider = $1
+ if ( $cgi->param('tax_provider') =~ /^([ \w]+)$/ );
+my $tax_customer = $1
+ if ( $cgi->param('tax_customer') =~ /^([ \w]+)$/ );
+my $id = $1
+ if ( $cgi->param('id') =~ /^([ \w]+)$/ );
+
+$onclick = $1
+ if ( $cgi->param('onclick') =~ /^(\w+)$/ );
+$cgi->delete('onclick');
+
+my $remove_onclick = <<EOS
+ parent.document.getElementById('$id').value = '';
+ parent.document.getElementById('${id}_description').value = '';
+ parent.$onclick();
+EOS
+ if $id;
+
+my $select_onclick = sub {
+ my $row = shift;
+ my $taxnum = $row->taxproductnum;
+ my $desc = $row->description;
+ "parent.document.getElementById('$id').value = $taxnum;".
+ "parent.document.getElementById('${id}_description').value = '$desc';".
+ "parent.$onclick();";
+}
+ if $id;
+
+my $selected_part_pkg_taxproduct;
+if ($taxproductnum) {
+ $selected_part_pkg_taxproduct =
+ qsearchs('part_pkg_taxproduct', { 'taxproductnum' => $taxproductnum });
+}
+
+my $hashref = {};
+my $extra_sql = '';
+if ( $data_vendor ) {
+ $extra_sql .= ' WHERE data_vendor = '. dbh->quote($data_vendor);
+}
+
+if ($tax_group || $tax_item || $tax_customer || $tax_provider) {
+ my $compare = "LIKE '". ( $tax_group || "%" ). " : ". ( $tax_item || "%" ). " : ".
+ ( $tax_provider || "%" ). " : ". ( $tax_customer || "%" ). "'";
+ $compare = "= '$tax_group:$tax_item:$tax_provider:$tax_customer'"
+ if ($tax_group && $tax_item && $tax_provider && $tax_customer);
+
+ $extra_sql .= ($extra_sql =~ /WHERE/ ? ' AND ' : ' WHERE ').
+ "description $compare";
+
+}
+$cgi->delete('tax_group');
+$cgi->delete('tax_item');
+$cgi->delete('tax_provider');
+$cgi->delete('tax_customer');
+
+
+if ( $tax_group || $tax_item || $tax_provider || $tax_customer ) {
+ push @menubar, 'View all tax products' => $p.'browse/part_pkg_taxproduct.cgi';
+}
+
+$cgi->param('dummy', 1);
+
+#restore this so pagination works
+$cgi->param('data_vendor', $data_vendor) if $data_vendor;
+$cgi->param('tax_group', $tax_group) if $tax_group;
+$cgi->param('tax_item', $tax_item ) if $tax_item;
+$cgi->param('tax_provider', $tax_provider ) if $tax_provider;
+$cgi->param('tax_customer', $tax_customer ) if $tax_customer;
+$cgi->param('onclick', $onclick ) if $onclick;
+
+my $count_query = "SELECT COUNT(*) FROM part_pkg_taxproduct $extra_sql";
+
+my @header = ( 'Data Vendor', 'Group', 'Item', 'Provider', 'Customer' );
+my @links = ( $select_link,
+ $select_link,
+ $select_link,
+ $select_link,
+ $select_link,
+ );
+my @link_onclicks = ( $select_onclick,
+ $select_onclick,
+ $select_onclick,
+ $select_onclick,
+ $select_onclick,
+ );
+my $align = 'lllll';
+
+my @fields = (
+ 'data_vendor',
+ sub { shift->description =~ /^(.*):.*:.*:.*$/; $1;},
+ sub { shift->description =~ /^.*:(.*):.*:.*$/; $1;},
+ sub { shift->description =~ /^.*:.*:(.*):.*$/; $1;},
+ sub { shift->description =~ /^.*:.*:.*:(.*)$/; $1;},
+);
+
+my $html_init = '';
+
+my $select_link = [ 'javascript:void(0);', sub { ''; } ];
+$html_init = '<TABLE><TR><TD><A HREF="javascript:void(0)" '.
+ qq!onClick="$remove_onclick">(remove)</A>&nbsp;!.
+ 'Current tax product: </TD><TD>'.
+ $selected_part_pkg_taxproduct->description.
+ '</TD></TR></TABLE><BR><BR>'
+ if $selected_part_pkg_taxproduct;
+
+my $type = $cgi->param('_type');
+$html_init .= qq(
+ <FORM>
+ <INPUT NAME="_type" TYPE="hidden" VALUE="$type">
+ <INPUT NAME="taxproductnum" TYPE="hidden" VALUE="$taxproductnum">
+ <INPUT NAME="onclick" TYPE="hidden" VALUE="$onclick">
+ <INPUT NAME="id" TYPE="hidden" VALUE="$id">
+ <TABLE>
+ <TR>
+ <TD><SELECT NAME="data_vendor" onChange="this.form.submit()">
+);
+
+my $sql = "SELECT DISTINCT data_vendor FROM part_pkg_taxproduct ORDER BY data_vendor";
+my $dbh = dbh;
+my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (['(choose data vendor)'], @{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $data_vendor ? " SELECTED" : "").
+ '">'. $_->[0];
+}
+$html_init .= qq(
+ </SELECT>
+
+<!-- cch specific -->
+ <TD><SELECT NAME="tax_group" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ qq!substring(description from '#"%#" : % : % : %' for '#'),!.
+ qq!substring(description from '#"%#" : % : % : %' for '#')!.
+ "FROM part_pkg_taxproduct ORDER BY 1";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (['', '(choose group)'], @{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_group ? " SELECTED" : "").
+ '">'. $_->[1];
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ <TD><SELECT NAME="tax_item" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ qq!substring(description from '% : #"%#" : %: %' for '#'),!.
+ qq!substring(description from '% : #"%#" : %: %' for '#')!.
+ "FROM part_pkg_taxproduct ORDER BY 1";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (@{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_item ? " SELECTED" : "").
+ '">'. ($_->[0] ? $_->[1] : '(choose item)');
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ <TD><SELECT NAME="tax_provider" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ qq!substring(description from '% : % : #"%#" : %' for '#'),!.
+ qq!substring(description from '% : % : #"%#" : %' for '#')!.
+ "FROM part_pkg_taxproduct ORDER BY 1";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (@{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_provider ? " SELECTED" : "").
+ '">'. ($_->[0] ? $_->[1] : '(choose provider type)');
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ <TD><SELECT NAME="tax_customer" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ qq!substring(description from '% : % : % : #"%#"' for '#'),!.
+ qq!substring(description from '% : % : % : #"%#"' for '#')!.
+ "FROM part_pkg_taxproduct ORDER BY 1";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (@{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_customer ? " SELECTED" : "").
+ '">'. ($_->[0] ? $_->[1] : '(choose customer type)');
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ </TR>
+ </TABLE>
+ </FORM>
+
+);
+
+</%init>
diff --git a/httemplate/browse/part_referral.html b/httemplate/browse/part_referral.html
new file mode 100755
index 000000000..9cc32c459
--- /dev/null
+++ b/httemplate/browse/part_referral.html
@@ -0,0 +1,181 @@
+<% include("/elements/header.html","Advertising source Listing" ) %>
+
+Where a customer heard about your service. Tracked for informational purposes.
+<BR><BR>
+
+<A HREF="<% $p %>edit/part_referral.html"><I>Add a new advertising source</I></A>
+<BR><BR>
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2 ROWSPAN=2>Advertising source</TH>
+% if ( $show_agentnums ) {
+
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2>Agent</TH>
+% }
+
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<% scalar(keys %after) %>>Customers and Packages</TH>
+</TR>
+% for my $period ( keys %after ) {
+
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% $period %></FONT></TH>
+% }
+
+</TR>
+
+%foreach my $part_referral ( FS::part_referral->all_part_referral(1) ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% $a = 0;
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% if ( $part_referral->agentnum || $curuser->access_right('Edit global advertising sources') ) {
+% $a++;
+%
+
+ <A HREF="<% $p %>edit/part_referral.html?<% $part_referral->refnum %>">
+% }
+
+ <% $part_referral->refnum %><% $a ? '</A>' : '' %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% if ( $a ) {
+
+ <A HREF="<% $p %>edit/part_referral.html?<% $part_referral->refnum %>">
+% }
+
+ <% $part_referral->referral %><% $a ? '</A>' : '' %></TD>
+% if ( $show_agentnums ) {
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $part_referral->agentnum ? $part_referral->agent->agent : '(global)' %></TD>
+% }
+% for my $period ( keys %after ) {
+% my @param = ( $part_referral->refnum,
+% $today-$after{$period},
+% $today+$before{$period},
+% );
+% $cust_sth->execute(@param) or die $cust_sth->errstr;
+% my $num_cust = $cust_sth->fetchrow_arrayref->[0];
+% $pkg_sth->execute(@param) or die $pkg_sth->errstr;
+% my $num_pkg = $pkg_sth->fetchrow_arrayref->[0];
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>" ALIGN="right">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD ALIGN="right"><B><% $num_cust %></B></TD>
+ <TD ALIGN="left">customers</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><B><% $num_pkg %></B></TD>
+ <TD ALIGN="left">packages</TD>
+ </TR>
+ </TABLE>
+ </TD>
+% }
+
+ </TR>
+% }
+%
+% $cust_statement =~ s/AND refnum = \?//;
+% $cust_sth = dbh->prepare($cust_statement)
+% or die dbh->errstr;
+% $pkg_statement =~ s/AND h_pkg_referral\.refnum = \?//;
+% $pkg_sth = dbh->prepare($pkg_statement)
+% or die dbh->errstr;
+
+ <TR>
+ <TD BGCOLOR="#dddddd" ALIGN="center" COLSPAN=3><B>Total</B></TD>
+% for my $period ( keys %after ) {
+% my @param = ( $today-$after{$period},
+% $today+$before{$period},
+% );
+% $cust_sth->execute( @param ) or die $cust_sth->errstr;
+% my $num_cust = $cust_sth->fetchrow_arrayref->[0];
+% $pkg_sth->execute(@param) or die $pkg_sth->errstr;
+% my $num_pkg = $pkg_sth->fetchrow_arrayref->[0];
+
+ <TD CLASS="inv" BGCOLOR="#dddddd" ALIGN="right">
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD ALIGN="right"><B><% $num_cust %></B></TD>
+ <TD ALIGN="left">customers</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><B><% $num_pkg %></B></TD>
+ <TD ALIGN="left">packages</TD>
+ </TR>
+ </TABLE>
+ </TD>
+
+% }
+
+ </TR>
+ </TABLE>
+ </BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit advertising sources')
+ || $FS::CurrentUser::CurrentUser->access_right('Edit global advertising sources');
+
+my $today = timelocal(0, 0, 0, (localtime(time))[3..5] );
+
+tie my %after, 'Tie::IxHash',
+ 'Today' => 0,
+ 'Yesterday' => 86400, # 60sec * 60min * 24hrs
+ 'Past week' => 518400, # 60sec * 60min * 24hrs * 6days
+ 'Past 30 days' => 2505600, # 60sec * 60min * 24hrs * 29days
+ 'Past 60 days' => 5097600, # 60sec * 60min * 24hrs * 59days
+ 'Past 90 days' => 7689600, # 60sec * 60min * 24hrs * 89days
+ 'Past 6 months' => 15724800, # 60sec * 60min * 24hrs * 182days
+ 'Past year' => 31486000, # 60sec * 60min * 24hrs * 364days
+ 'Total' => $today,
+;
+my %before = (
+ 'Today' => 86400, # 60sec * 60min * 24hrs
+ 'Yesterday' => 0,
+ 'Past week' => 86400, # 60sec * 60min * 24hrs
+ 'Past 30 days' => 86400, # 60sec * 60min * 24hrs
+ 'Past 60 days' => 86400, # 60sec * 60min * 24hrs
+ 'Past 90 days' => 86400, # 60sec * 60min * 24hrs
+ 'Past 6 months' => 86400, # 60sec * 60min * 24hrs
+ 'Past year' => 86400, # 60sec * 60min * 24hrs
+ 'Total' => 86400, # 60sec * 60min * 24hrs
+);
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $show_agentnums = ( scalar($curuser->agentnums) > 1 );
+
+my $cust_statement = "SELECT COUNT(*) FROM h_cust_main
+ WHERE history_action = 'insert'
+ AND refnum = ?
+ AND history_date >= ?
+ AND history_date < ?
+ AND ". $curuser->agentnums_sql;
+my $cust_sth = dbh->prepare($cust_statement)
+ or die dbh->errstr;
+
+my $pkg_statement = "SELECT COUNT(*) FROM h_pkg_referral
+ LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN cust_main USING ( custnum )
+ WHERE history_action = 'insert'
+ AND h_pkg_referral.refnum = ?
+ AND history_date >= ?
+ AND history_date < ?
+ AND ". $curuser->agentnums_sql;
+my $pkg_sth = dbh->prepare($pkg_statement)
+ or die dbh->errstr;
+
+</%init>
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
new file mode 100755
index 000000000..f1b283638
--- /dev/null
+++ b/httemplate/browse/part_svc.cgi
@@ -0,0 +1,215 @@
+<% include('/elements/header.html', 'Service Definition Listing') %>
+
+<SCRIPT>
+function part_export_areyousure(href) {
+ if (confirm("Are you sure you want to delete this export?") == true)
+ window.location.href = href;
+}
+</SCRIPT>
+
+ Service definitions are the templates for items you offer to your customers.<BR><BR>
+
+<FORM METHOD="POST" ACTION="<% $p %>edit/part_svc.cgi">
+<A HREF="<% $p %>edit/part_svc.cgi"><I>Add a new service definition</I></A>
+% if ( @part_svc ) {
+&nbsp;or&nbsp;<SELECT NAME="clone"><OPTION></OPTION>
+% foreach my $part_svc ( @part_svc ) {
+
+ <OPTION VALUE="<% $part_svc->svcpart %>"><% $part_svc->svc %></OPTION>
+% }
+
+</SELECT><INPUT TYPE="submit" VALUE="Clone existing service">
+% }
+
+</FORM><BR>
+
+<% $total %> service definitions
+<% $cgi->param('showdisabled')
+ ? do { $cgi->param('showdisabled', 0);
+ '( <a href="'. $cgi->self_url. '">hide disabled services</a> )'; }
+ : do { $cgi->param('showdisabled', 1);
+ '( <a href="'. $cgi->self_url. '">show disabled services</a> )'; }
+%>
+% $cgi->param('showdisabled', ( 1 ^ $cgi->param('showdisabled') ) );
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+ <TR>
+
+ <TH CLASS="grid" BGCOLOR="#cccccc"><A HREF="<% do { $cgi->param('orderby', 'svcpart'); $cgi->self_url } %>">#</A></TH>
+
+% if ( $cgi->param('showdisabled') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
+% }
+
+ <TH CLASS="grid" BGCOLOR="#cccccc"><A HREF="<% do { $cgi->param('orderby', 'svc'); $cgi->self_url; } %>">Service</A></TH>
+
+ <TH CLASS="grid" BGCOLOR="#cccccc">Table</TH>
+
+ <TH CLASS="grid" BGCOLOR="#cccccc"><A HREF="<% do { $cgi->param('orderby', 'active'); $cgi->self_url; } %>"><FONT SIZE=-1>Customer<BR>Services</FONT></A></TH>
+
+ <TH CLASS="grid" BGCOLOR="#cccccc">Export</TH>
+
+ <TH CLASS="grid" BGCOLOR="#cccccc">Field</TH>
+
+ <TH COLSPAN=2 CLASS="grid" BGCOLOR="#cccccc">Modifier</TH>
+
+ </TR>
+
+% foreach my $part_svc ( @part_svc ) {
+% my $svcdb = $part_svc->svcdb;
+% my $svc_x = "FS::$svcdb"->new( { svcpart => $part_svc->svcpart } );
+% my @dfields = $svc_x->fields;
+% push @dfields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
+% my @fields =
+% grep { $svc_x->pvf($_)
+% or $_ ne 'svcnum' && $part_svc->part_svc_column($_)->columnflag }
+% @dfields ;
+% my $rowspan = scalar(@fields) || 1;
+% my $url = "${p}edit/part_svc.cgi?". $part_svc->svcpart;
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+
+ <TR>
+
+ <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<% $url %>"><% $part_svc->svcpart %></A>
+ </TD>
+
+% if ( $cgi->param('showdisabled') ) {
+ <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $part_svc->disabled
+ ? '<FONT COLOR="#FF0000"><B>Disabled</B></FONT>'
+ : '<FONT COLOR="#00CC00"><B>Enabled</B></FONT>'
+ %>
+ </TD>
+% }
+
+ <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $url %>">
+ <% $part_svc->svc %></A></TD>
+
+ <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $svcdb %></TD>
+
+ <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <FONT COLOR="#00CC00"><B><% $num_active_cust_svc{$part_svc->svcpart} %></B></FONT>&nbsp;<% $num_active_cust_svc{$part_svc->svcpart} ? svc_url( 'ahref' => 1, 'm' => $m, 'action' => 'search', 'part_svc' => $part_svc, 'query' => "svcpart=". $part_svc->svcpart ) : '<A NAME="zero">' %>active</A>
+
+% if ( $num_active_cust_svc{$part_svc->svcpart} ) {
+ <BR><FONT SIZE="-1">[ <A HREF="<%$p%>edit/bulk-cust_svc.html?svcpart=<% $part_svc->svcpart %>">change</A> ]</FONT>
+% }
+
+ </TD>
+
+ <TD ROWSPAN=<% $rowspan %> CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv">
+%
+%# my @part_export =
+%map { qsearchs('part_export', { exportnum => $_->exportnum } ) } qsearch('export_svc', { svcpart => $part_svc->svcpart } ) ;
+% foreach my $part_export (
+% map { qsearchs('part_export', { exportnum => $_->exportnum } ) }
+% qsearch('export_svc', { svcpart => $part_svc->svcpart } )
+% ) {
+%
+
+ <TR>
+ <TD><A HREF="<% $p %>edit/part_export.cgi?<% $part_export->exportnum %>"><% $part_export->exportnum %>:&nbsp;<% $part_export->exporttype %>&nbsp;to&nbsp;<% $part_export->machine %></A></TD>
+ </TR>
+% }
+
+ </TABLE>
+ </TD>
+
+% unless ( @fields ) {
+% for ( 1..3 ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"</TD>
+% }
+% }
+%
+% my($n1)='';
+% foreach my $field ( @fields ) {
+% my $formatter =
+% FS::part_svc->svc_table_fields($svcdb)->{$field}->{format}
+% || sub { shift };
+% my $flag = $part_svc->part_svc_column($field)->columnflag;
+%
+
+ <% $n1 %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $field %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $flag{$flag} %></TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% my $value = &$formatter($part_svc->part_svc_column($field)->columnvalue);
+% if ( $flag =~ /^[MA]$/ ) {
+% $inventory_class{$value}
+% ||= qsearchs('inventory_class', { 'classnum' => $value } );
+%
+
+ <% $inventory_class{$value}
+ ? $inventory_class{$value}->classname
+ : "WARNING: inventory_class.classnum $value not found" %>
+% } else {
+
+ <% $value %>
+% }
+
+ </TD>
+% $n1="</TR><TR>";
+% }
+%
+
+ </TR>
+% }
+
+</TABLE>
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm
+my %flag = (
+ '' => '',
+ 'D' => 'Default',
+ 'F' => 'Fixed (unchangeable)',
+ 'S' => 'Selectable choice',
+ #'M' => 'Manual selection from inventory',
+ 'M' => 'Manual selected from inventory',
+ #'A' => 'Automatically fill in from inventory',
+ 'A' => 'Automatically filled in from inventory',
+ 'X' => 'Excluded',
+);
+
+my %search;
+if ( $cgi->param('showdisabled') ) {
+ %search = ();
+} else {
+ %search = ( 'disabled' => '' );
+}
+
+my @part_svc =
+ sort { $a->getfield('svcpart') <=> $b->getfield('svcpart') }
+ qsearch('part_svc', \%search );
+my $total = scalar(@part_svc);
+
+my %num_active_cust_svc = map { $_->svcpart => $_->num_cust_svc } @part_svc;
+
+if ( $cgi->param('orderby') eq 'active' ) {
+ @part_svc = sort { $num_active_cust_svc{$b->svcpart} <=>
+ $num_active_cust_svc{$a->svcpart} } @part_svc;
+} elsif ( $cgi->param('orderby') eq 'svc' ) {
+ @part_svc = sort { lc($a->svc) cmp lc($b->svc) } @part_svc;
+}
+
+my %inventory_class = ();
+
+</%init>
diff --git a/httemplate/browse/part_virtual_field.cgi b/httemplate/browse/part_virtual_field.cgi
new file mode 100644
index 000000000..b18440036
--- /dev/null
+++ b/httemplate/browse/part_virtual_field.cgi
@@ -0,0 +1,42 @@
+<% include('/elements/header.html', 'Virtual field definitions') %>
+
+<% include('/elements/error.html') %>
+
+<A HREF="<%$p2%>edit/part_virtual_field.cgi"><I>Add a new field</I></A><BR><BR>
+% foreach $dbtable (sort { $a cmp $b } keys (%pvfs)) {
+
+<H3><%$dbtable%></H3>
+
+<%table()%>
+<TH><TD>Field name</TD><TD>Description</TD></TH>
+% foreach my $pvf (sort {$a->name cmp $b->name} @{ $pvfs{$dbtable} }) {
+
+ <TR>
+ <TD></TD>
+ <TD>
+ <A HREF="<%$p2%>edit/part_virtual_field.cgi?<%$pvf->vfieldpart%>">
+ <%$pvf->name%></A></TD>
+ <TD><%$pvf->label%></TD>
+ </TR>
+% }
+
+</TABLE>
+% }
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my %pvfs;
+my $block;
+my $p2 = popurl(2);
+my $dbtable;
+
+foreach (qsearch('part_virtual_field', {})) {
+ push @{ $pvfs{$_->dbtable} }, $_;
+}
+
+</%init>
diff --git a/httemplate/browse/payment_gateway.html b/httemplate/browse/payment_gateway.html
new file mode 100644
index 000000000..848c58a82
--- /dev/null
+++ b/httemplate/browse/payment_gateway.html
@@ -0,0 +1,94 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Payment gateways',
+ 'menubar' => [ 'Agents' => $p.'browse/agent.cgi', ],
+ 'html_init' => $html_init,
+ 'name' => 'payment gateways',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 1,
+ 'query' => { 'table' => 'payment_gateway',
+ 'hashref' => {},
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Gateway',
+ 'Username',
+ 'Password',
+ 'Action',
+ 'Options',
+ ],
+ 'fields' => [ 'gatewaynum',
+ $gateway_sub,
+ 'gateway_username',
+ sub { ' - '; },
+ 'gateway_action',
+ $options_sub,
+ ],
+ )
+%>
+
+</TABLE>
+
+<% include('/elements/footer.html') %>
+<%once>
+
+my $html_init = qq!
+ <A HREF="${p}edit/payment_gateway.html"><I>Add a new payment gateway</I></A>
+ <BR><BR>
+
+ <SCRIPT>
+ function areyousure(href) {
+ if (confirm("Are you sure you want to disable this payment gateway?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+!;
+
+my $gateway_sub = sub {
+ my($payment_gateway) = @_;
+
+ my $gatewaynum = $payment_gateway->gatewaynum;
+
+ my $html = $payment_gateway->gateway_module. ' '. qq!
+ <FONT SIZE="-1">
+ <A HREF="${p}edit/payment_gateway.html?$gatewaynum">(edit)</A>
+ !;
+
+ unless ( $payment_gateway->disabled ) {
+ $html .= qq!
+ <A HREF="javascript:areyousure('${p}misc/disable-payment_gateway.cgi?$gatewaynum')">(disable)</A>
+ !;
+ }
+
+ $html .= '</FONT>';
+
+ $html;
+
+};
+
+my $options_sub = sub {
+ my($payment_gateway) = @_;
+
+ #should return a structure instead of this manual formatting...
+
+ my $html = '<TABLE CELLSPACING=0 CELLPADDING=0>';
+
+ my %options = $payment_gateway->options;
+ foreach my $option ( keys %options ) {
+ $html .= '<TR><TH>'. $option. ':</TH>'.
+ '<TD>'. $options{$option}. '</TD></TR>';
+ }
+ $html .= '</TABLE>';
+
+ $html;
+};
+
+my $count_query = 'SELECT COUNT(*) FROM payment_gateway';
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/browse/pkg_category.html b/httemplate/browse/pkg_category.html
new file mode 100644
index 000000000..20bf1a8df
--- /dev/null
+++ b/httemplate/browse/pkg_category.html
@@ -0,0 +1,33 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Package categories',
+ 'html_init' => $html_init,
+ 'name' => 'package categories',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'query' => { 'table' => 'pkg_category',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY categorynum',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#', 'Category' ],
+ 'fields' => [ 'categorynum', 'categoryname' ],
+ 'links' => [ $link, $link ],
+ )
+%>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ qq!<A HREF="${p}browse/pkg_class.html">Package classes</A><BR><BR>!.
+ 'Package categories define groups of package classes, for reporting and '.
+ 'convenience purposes.<BR><BR>'.
+ qq!<A HREF="${p}edit/pkg_category.html"><I>Add a package category</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM pkg_category';
+
+my $link = [ $p.'edit/pkg_category.html?', 'categorynum' ];
+
+</%init>
diff --git a/httemplate/browse/pkg_class.html b/httemplate/browse/pkg_class.html
new file mode 100644
index 000000000..75969dbe8
--- /dev/null
+++ b/httemplate/browse/pkg_class.html
@@ -0,0 +1,46 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Package classes',
+ 'html_init' => $html_init,
+ 'name' => 'package classes',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'query' => { 'table' => 'pkg_class',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY classnum',
+ },
+ 'count_query' => $count_query,
+ 'header' => $header,
+ 'fields' => $fields,
+ 'links' => $links,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ 'Package classes define groups of packages, for reporting and '.
+ 'convenience purposes.<BR><BR>'.
+ qq!<A HREF="${p}edit/pkg_class.html"><I>Add a package class</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM pkg_class';
+
+my $link = [ $p.'edit/pkg_class.html?', 'classnum' ];
+
+my $header = [ '#', 'Class' ];
+my $fields = [ 'classnum', 'classname' ];
+my $links = [ $link, $link ];
+
+my $cat_query = 'SELECT COUNT(*) FROM pkg_class where categorynum IS NOT NULL';
+my $sth = dbh->prepare($cat_query)
+ or die "Error preparing $cat_query: ". dbh->errstr;
+$sth->execute
+ or die "Error executing $cat_query: ". $sth->errstr;
+if ($sth->fetchrow_arrayref->[0]) {
+ push @$header, 'Category';
+ push @$fields, 'categoryname';
+ push @$links, $link;
+}
+
+</%init>
diff --git a/httemplate/browse/rate.cgi b/httemplate/browse/rate.cgi
new file mode 100644
index 000000000..02d670fbd
--- /dev/null
+++ b/httemplate/browse/rate.cgi
@@ -0,0 +1,64 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Rate plans',
+ 'menubar' => [ 'Regions and Prefixes' =>
+ $p.'browse/rate_region.html',
+ ],
+ 'html_init' => $html_init,
+ 'name' => 'rate plans',
+ 'query' => { 'table' => 'rate',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY ratenum',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#', 'Rate plan', 'Rates' ],
+ 'fields' => [ 'ratenum', 'ratename', $rates_sub ],
+ 'links' => [ $link, $link, '' ],
+ )
+%>
+<%once>
+
+my $all_countrycodes = join("\n", map qq(<OPTION VALUE="$_">$_),
+ FS::rate_prefix->all_countrycodes
+ );
+
+my $rates_sub = sub {
+ my $rate = shift;
+ my $ratenum = $rate->ratenum;
+
+ qq( <FORM METHOD="GET" ACTION="${p}browse/rate_detail.html">
+ <INPUT TYPE="hidden" NAME="ratenum" VALUE="$ratenum">
+ <SELECT NAME="countrycode" onChange="this.form.submit();">
+ <OPTION SELECTED>Select Country Code
+ <OPTION VALUE="">(all)
+ $all_countrycodes
+ </SELECT>
+ </FORM>
+ );
+
+
+};
+
+my $html_init =
+ 'Rate plans for VoIP and call billing.<BR><BR>'.
+ qq!<A HREF="${p}edit/rate.cgi"><I>Add a rate plan</I></A>!.
+ qq! | <A HREF="${p}misc/copy-rate_detail.html"><I>Copy rates between plans</I></A>!.
+ '<BR><BR>
+ <SCRIPT>
+ function rate_areyousure(href) {
+ if (confirm("Are you sure you want to delete this rate plan?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+ ';
+
+my $count_query = 'SELECT COUNT(*) FROM rate';
+
+my $link = [ $p.'edit/rate.cgi?', 'ratenum' ];
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/browse/rate_detail.html b/httemplate/browse/rate_detail.html
new file mode 100644
index 000000000..23bc23ff8
--- /dev/null
+++ b/httemplate/browse/rate_detail.html
@@ -0,0 +1,92 @@
+<% include( 'elements/browse.html',
+ 'title' => $title,
+ 'name_singular' => 'rate',
+ 'html_init' => $html_init,
+ 'menubar' => [ 'Rate plans' => $p.'browse/rate.cgi' ],
+ 'query' => {
+ 'table' => 'rate_detail',
+ 'addl_from' => $join,
+ 'hashref' => { 'ratenum' => $ratenum },
+ 'extra_sql' => $where,
+ },
+ 'count_query' => "SELECT COUNT(*) FROM rate_detail $join".
+ " WHERE ratenum = $ratenum $where",
+ 'header' => [
+ 'Region',
+ 'Prefix(es)',
+ 'Included<BR>minutes',
+ 'Charge per<BR>minute',
+ 'Granularity',
+ 'Usage class',
+ ],
+ 'fields' => [
+ 'regionname',
+ sub { shift->dest_region->prefixes_short },
+ sub { shift->min_included.
+ '&nbsp;<FONT SIZE="-1">(edit)</FONT>';
+ },
+ sub { $money_char. shift->min_charge.
+ '&nbsp;<FONT SIZE="-1">(edit)</FONT>';
+ },
+ sub { $granularity{ shift->sec_granularity } },
+ 'classname',
+ ],
+ 'links' => [ '', '', $edit_link, $edit_link, '', '' ],
+ 'link_onclicks' => [ '', '', $edit_onclick, $edit_onclick, '', '' ],
+ 'align' => 'llrrcc',
+ )
+%>
+<%once>
+
+tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $join =
+ ' JOIN rate_region ON ( rate_detail.dest_regionnum = rate_region.regionnum )';
+
+my $edit_link = [ 'javascript:void(0);', sub { ''; } ];
+
+my $edit_onclick = sub {
+ my $rate_detail = shift;
+ my $ratedetailnum = $rate_detail->ratedetailnum;
+ include( '/elements/popup_link_onclick.html',
+ 'action' => "${p}edit/rate_detail.html?$ratedetailnum",
+ 'actionlabel' => 'Edit rate',
+ 'height' => 420,
+ #default# 'width' => 540,
+ #default# 'color' => '#333399',
+ );
+};
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init = include('/elements/init_overlib.html');
+
+$cgi->param('ratenum') =~ /^(\d+)$/ or die "unparsable ratenum";
+my $ratenum = $1;
+my $rate = qsearchs('rate', { 'ratenum' => $ratenum } )
+ or die "unknown ratenum $ratenum";
+my $ratename = $rate->ratename;
+my $title = "$ratename rates";
+
+my @where = ();
+
+if ( $cgi->param('countrycode') =~ /^(\d+)$/ ) {
+ my $countrycode = $1;
+ push @where, "0 < ( SELECT COUNT(*) FROM rate_prefix
+ WHERE rate_prefix.regionnum = rate_region.regionnum
+ AND countrycode = '$countrycode'
+ )
+ ";
+ $title .= " for +$countrycode";
+}
+
+my $where = scalar(@where) ? ' AND '.join(' AND ', @where ) : '';
+
+</%init>
diff --git a/httemplate/browse/rate_region.html b/httemplate/browse/rate_region.html
new file mode 100644
index 000000000..b454a9e74
--- /dev/null
+++ b/httemplate/browse/rate_region.html
@@ -0,0 +1,91 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Rating Regions and Prefixes',
+ 'name_singular' => 'region', #'rate region',
+ 'menubar' => [ 'Rate plans' => $p.'browse/rate.cgi' ],
+ 'html_init' => $html_init,
+ 'html_posttotal' => $html_posttotal,
+ 'query' => {
+ 'select' => $select,
+ 'table' => 'rate_region',
+ 'addl_from' => $join,
+ 'extra_sql' => $extra_sql,
+ 'order_by' => 'ORDER BY LOWER(regionname)',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#', 'Region', 'Country code', 'Prefixes' ],
+ 'fields' => [ 'regionnum', 'regionname', 'ccode', 'prefixes' ],
+ 'links' => [ $link, $link, $link, $link ],
+ )
+%>
+<%once>
+
+my $edit_url = $p.'edit/rate_region.cgi';
+
+my $link = [ "$edit_url?", 'regionnum' ];
+
+my $html_init =
+ 'Regions and prefixes for VoIP and call billing.<BR><BR>'.
+ qq(<A HREF="$edit_url"><I>Add a new region</I></A><BR><BR>);
+
+#not quite right for the shouldn't-happen multiple countrycode per region case
+my $select = 'rate_region.*, ';
+my $join = '';
+my $group_sql = '';
+if ( driver_name =~ /^Pg/ ) {
+ my $fromwhere = 'FROM rate_prefix'.
+ ' WHERE rate_prefix.regionnum = rate_region.regionnum';
+ my $prefix_sql = " CASE WHEN nxx IS NULL OR nxx = '' ".
+ " THEN npa ".
+ " ELSE npa || '-' || nxx ".
+ " END";
+ my $prefixes_sql = "SELECT $prefix_sql $fromwhere AND npa IS NOT NULL";
+ $select .= "( SELECT countrycode $fromwhere LIMIT 1 ) AS ccode,
+ ARRAY_TO_STRING( ARRAY($prefixes_sql), ',' ) AS prefixes";
+} elsif ( driver_name =~ /^mysql/i ) {
+ $join = 'LEFT JOIN rate_prefix USING ( regionnum )';
+ $select .= "GROUP_CONCAT( DISTINCT countrycode ) AS ccode,
+ GROUP_CONCAT( npa ORDER BY npa ) AS prefixes ";
+ $group_sql = 'GROUP BY regionnum, regionname';
+} else {
+ die 'unknown database '. driver_name;
+}
+
+my $base_count_sql = 'SELECT COUNT(*) FROM rate_region';
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('dummy', 1);
+my $countrycode_filter_change =
+ "window.location = '".
+ $cgi->self_url. ";countrycode=' + this.options[this.selectedIndex].value;";
+
+my $countrycode = '';
+my $extra_sql = $group_sql;
+my $count_query = $base_count_sql;
+if ( $cgi->param('countrycode') =~ /^(\d+)$/ ) {
+ $countrycode = $1;
+ my $ccode_sql = '( SELECT countrycode FROM rate_prefix
+ WHERE rate_prefix.regionnum = rate_region.regionnum
+ LIMIT 1
+ )';
+ $extra_sql = " WHERE $ccode_sql = '$1' $extra_sql";
+ $count_query .= " WHERE $ccode_sql = '$1'";
+}
+
+my $html_posttotal =
+ '(show country code: '.
+ qq(<SELECT NAME="countrycode" onChange="$countrycode_filter_change">).
+ qq(<OPTION VALUE="">(all)).
+ join("\n", map { qq(<OPTION VALUE="$_").
+ ($_ eq $countrycode ? ' SELECTED' : '' ).
+ ">$_",
+ }
+ FS::rate_prefix->all_countrycodes
+ ).
+ '</SELECT>)';
+
+</%init>
diff --git a/httemplate/browse/reason.html b/httemplate/browse/reason.html
new file mode 100644
index 000000000..fe285be4a
--- /dev/null
+++ b/httemplate/browse/reason.html
@@ -0,0 +1,53 @@
+<% include( 'elements/browse.html',
+ 'title' => ucfirst($classname) . ' Reasons',
+ 'menubar' => [ ucfirst($classname).' Reason Types' =>
+ $p."browse/reason_type.html?class=$class"
+ ],
+ 'html_init' => $html_init,
+ 'name' => $classname . ' reasons',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 3,
+ 'query' => { 'table' => 'reason',
+ 'hashref' => {},
+ 'extra_sql' => $where_clause.
+ ' ORDER BY reason_type',
+ 'addl_from' => 'LEFT JOIN reason_type ON reason_type.typenum = reason.reason_type',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ ucfirst($classname) . ' Reason Type',
+ ucfirst($classname) . ' Reason',
+ ],
+ 'fields' => [ 'reasonnum',
+ sub { shift->reasontype->type },
+ 'reason',
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('class') =~ /^(\w)$/ or die "illegal class";
+my $class = $1;
+
+my $classname = $FS::reason_type::class_name{$class};
+my $classpurpose = $FS::reason_type::class_purpose{$class};
+
+my $html_init = ucfirst($classname). " reasons $classpurpose.<BR><BR>".
+qq!<A HREF="${p}edit/reason.html?class=$class">!.
+"<I>Add a $classname reason</I></A><BR><BR>";
+
+my $where_clause = " WHERE class='$class' ";
+
+my $count_query = 'SELECT COUNT(*) FROM reason LEFT JOIN reason_type on ' .
+ 'reason_type.typenum = reason.reason_type ' . $where_clause;
+
+my $link = [ $p."edit/reason.html?class=$class&reasonnum=", 'reasonnum' ];
+
+</%init>
diff --git a/httemplate/browse/reason_type.html b/httemplate/browse/reason_type.html
new file mode 100644
index 000000000..6b444bad1
--- /dev/null
+++ b/httemplate/browse/reason_type.html
@@ -0,0 +1,68 @@
+<% include( 'elements/browse.html',
+ 'title' => ucfirst($classname) . " Reason Types",
+ 'menubar' => [ ucfirst($classname) . " reasons" =>
+ $p.'browse/reason.html?class=' . $class,
+ ],
+ 'html_init' => $html_init,
+ 'name' => $classname . " reason types",
+ 'query' => { 'table' => 'reason_type',
+ 'hashref' => {},
+ 'extra_sql' => $where_clause .
+ 'ORDER BY typenum',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ ucfirst($classname) . ' Reason Type',
+ ucfirst($classname) . ' Reasons',
+ ],
+ 'fields' => [ 'typenum',
+ 'type',
+ $reasons_sub,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('class') =~ /^(\w)$/ or die "illegal class";
+my $class=$1;
+
+my $classname = $FS::reason_type::class_name{$class};
+
+my $html_init = ucfirst($classname) .
+ " reason types allow groups of $classname reasons for reporting purposes." .
+ qq!<BR><BR><A HREF="${p}edit/reason_type.html?class=$class"><I>Add a ! .
+ $classname . " reason type</I></A><BR><BR>";
+
+my $reasons_sub = sub {
+ my $reason_type = shift;
+
+ [ map {
+ [
+ {
+ 'data' => $_->reason,
+ 'align' => 'left',
+ 'link' => $p. "edit/reason.html?class=$class&reasonnum=".
+ $_->reasonnum,
+ },
+ ];
+ }
+ $reason_type->enabled_reasons,
+
+ ];
+
+};
+
+my $where_clause = "WHERE class='$class'";
+my $count_query = 'SELECT COUNT(*) FROM reason_type ';
+$count_query .= $where_clause;
+
+my $link = [ $p.'edit/reason_type.html?class='.$class.'&typenum=', 'typenum' ];
+
+</%init>
diff --git a/httemplate/browse/router.cgi b/httemplate/browse/router.cgi
new file mode 100644
index 000000000..541e967dd
--- /dev/null
+++ b/httemplate/browse/router.cgi
@@ -0,0 +1,52 @@
+<% include('elements/browse.html',
+ 'title' => 'Routers',
+ 'menubar' => [ @menubar ],
+ 'name_singular' => 'router',
+ 'query' => { 'table' => 'router',
+ 'hashref' => {},
+ 'extra_sql' => $extra_sql,
+ },
+ 'count_query' => "SELECT count(*) from router $count_sql",
+ 'header' => [ 'Router name',
+ 'Address block(s)',
+ ],
+ 'fields' => [ 'routername',
+ sub { join( '<BR>', map { $_->NetAddr }
+ shift->addr_block
+ );
+ },
+ ],
+ 'links' => [ [ "${p2}edit/router.cgi?", 'routernum' ],
+ '',
+ ],
+ 'agent_virt' => 1,
+ 'agent_null_right'=> "Broadband global configuration",
+ 'agent_pos' => 1,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Broadband configuration')
+ || $FS::CurrentUser::CurrentUser->access_right('Broadband global configuration');
+
+my $p2 = popurl(2);
+my $extra_sql = '';
+
+my @menubar = ( 'Add a new router', "${p2}edit/router.cgi" );
+
+if ($cgi->param('hidecustomerrouters') eq '1') {
+ $extra_sql = 'WHERE svcnum > 0';
+ $cgi->param('hidecustomerrouters', 0);
+ push @menubar, 'Show customer routers', $cgi->self_url();
+} else {
+ $cgi->param('hidecustomerrouters', 1);
+ push @menubar, 'Hide customer routers', $cgi->self_url();
+}
+
+my $count_sql = $extra_sql. ( $extra_sql =~ /WHERE/ ? ' AND' : 'WHERE' ).
+ $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'Broadband global configuration',
+ );
+
+</%init>
diff --git a/httemplate/browse/svc_acct_pop.cgi b/httemplate/browse/svc_acct_pop.cgi
new file mode 100755
index 000000000..c6e615d40
--- /dev/null
+++ b/httemplate/browse/svc_acct_pop.cgi
@@ -0,0 +1,77 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Access Numbers',
+ 'html_init' => $html_init,
+ 'name_singular' => 'access number',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'header' => [
+ '#',
+ 'City',
+ 'State',
+ 'Area code',
+ 'Exchange',
+ 'Local',
+ 'Accounts',
+ ],
+ 'fields' => [
+ 'popnum',
+ 'city',
+ 'state',
+ 'ac',
+ 'exch',
+ 'loc',
+ $num_accounts_sub,
+ ],
+ 'align' => 'rllrrrr',
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Dialup configuration')
+ || $curuser->access_right('Dialup global configuration');
+
+my $html_init = qq!
+ <A HREF="${p}edit/svc_acct_pop.cgi"><I>Add new Access Number</I></A>
+ <BR><BR>
+!;
+
+my $query = { 'select' => '*,
+ ( SELECT COUNT(*) FROM svc_acct
+ WHERE svc_acct.popnum = svc_acct_pop.popnum
+ ) AS num_accounts
+ ',
+ 'table' => 'svc_acct_pop',
+ #'hashref' => { 'disabled' => '' },
+ 'extra_sql' => 'ORDER BY state, city, ac, exch, loc',
+ };
+
+my $count_query = "SELECT COUNT(*) FROM svc_acct_pop"; # WHERE DISABLED IS NULL OR DISABLED = ''";
+
+my $svc_acct_pop_link = [ $p.'edit/svc_acct_pop.cgi?', 'popnum' ];
+
+my $svc_acct_link = $p. 'search/svc_acct.cgi?popnum=';
+
+my $num_accounts_sub = sub {
+ my $svc_acct_pop = shift;
+ [
+ [
+ { 'data' => '<B><FONT COLOR="#00CC00">'.
+ $svc_acct_pop->get('num_accounts').
+ '</FONT></B>',
+ 'align' => 'right',
+ },
+ { 'data' => 'active',
+ 'align' => 'left',
+ 'link' => ( $svc_acct_pop->get('num_accounts')
+ ? $svc_acct_link. $svc_acct_pop->popnum
+ : ''
+ ),
+ },
+ ],
+ ];
+};
+
+</%init>
diff --git a/httemplate/browse/tax_class.html b/httemplate/browse/tax_class.html
new file mode 100755
index 000000000..76d266bf9
--- /dev/null
+++ b/httemplate/browse/tax_class.html
@@ -0,0 +1,92 @@
+<% include( 'elements/browse.html',
+ 'title' => "Tax classes $title",
+ 'name_singular' => 'tax class',
+ 'menubar' => \@menubar,
+ 'html_init' => $html_init,
+ 'query' => {
+ 'table' => 'tax_class',
+ 'hashref' => $hashref,
+ 'extra_sql' => $where,
+ 'order_by' => 'ORDER BY taxclass',
+ },
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'align' => $align,
+ 'links' => \@links,
+ 'link_onclicks' => \@link_onclicks,
+ 'disable_maxselect' => 1,
+ 'disable_total' => 1,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $title = '';
+my @menubar = ();
+my $html_init = '';
+my $hashref = {};
+my @where = ();
+my $onclick = 'return true;';
+
+my $omit = '';
+if ( $cgi->param('magic') eq 'omit' ) {
+ $cgi->param('omit') =~ /^([,\d]+)$/;
+ $omit = $1;
+ $title .= " unselected";
+ push @where, map { "taxclassnum != $_" } grep {$_} split( /,/, $omit );
+ $onclick = sub{ 'parent.doSelect('. shift->taxclassnum. '); return false;' }
+}
+$cgi->delete('omit');
+
+my $data_vendor = '';
+if ( $cgi->param('datavendor') =~ /^([\w]+)$/ ) {
+ $data_vendor = $1;
+ $title .= " for data vendor $1";
+ push @where, 'data_vendor = '. dbh->quote($data_vendor);
+}
+$cgi->delete('data_vendor');
+
+my $selected = '';
+if ( $cgi->param('magic') eq 'select')
+{
+ $cgi->param('selected') =~ /^([,\d]*)$/;
+ $selected = $1;
+ $title = " selected";
+ my @clauses = map { "taxclassnum = $_" } grep {$_} split( /,/, $selected );
+ @where = scalar(@clauses) ? '( '. join(' OR ', @clauses) .')' : '1=0';
+ $onclick = sub{ 'parent.doUnselect('. shift->taxclassnum. '); return false;' } ;
+}
+$cgi->delete('selected');
+
+
+if ( $data_vendor ) {
+ push @menubar, 'View all tax classes' => $p.'browse/tax_class.html';
+}
+
+$cgi->param('dummy', 1);
+
+#restore this so pagination works
+$cgi->param('omit', $omit ) if $omit;
+$cgi->param('selected', $selected ) if $selected;
+$cgi->param('data_vendor', $data_vendor ) if $data_vendor;
+
+my $where = scalar(@where) ? 'WHERE '. join( ' AND ', @where ) : '';
+my $count_query = 'SELECT COUNT(*) FROM tax_class '. $where;
+
+my $link = [ 'javascript:void(0);', sub{ ''; } ];
+
+my @header = ( '', '', '' );
+my @links = ( $link, $link, $link );
+my @link_onclicks = ( $onclick, $onclick, $onclick );
+my $align = 'lll';
+my @fields = ( 'data_vendor', 'taxclass', 'description' );
+
+</%init>
diff --git a/httemplate/browse/tax_rate.cgi b/httemplate/browse/tax_rate.cgi
new file mode 100755
index 000000000..cb997fada
--- /dev/null
+++ b/httemplate/browse/tax_rate.cgi
@@ -0,0 +1,348 @@
+<% include( 'elements/browse.html',
+ 'title' => "Tax Rates $title",
+ 'name_singular' => 'tax rate',
+ 'menubar' => \@menubar,
+ 'html_init' => $html_init,
+ 'html_form' => $html_form,
+ 'disableable' => 1,
+ 'disabled_statuspos' => 5,
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'header' => \@header,
+ 'header2' => \@header2,
+ 'fields' => \@fields,
+ 'align' => $align,
+ 'color' => \@color,
+ 'cell_style' => \@cell_style,
+ 'links' => \@links,
+ 'link_onclicks' => \@link_onclicks,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $rate_sub = sub {
+ my $tax_rate = shift;
+
+ my $units = $tax_rate->unittype_name;
+ $units =~ s/ /&nbsp;/g;
+
+ my @rate = ();
+ push @rate,
+ ($tax_rate->tax * 100). '%&nbsp;<FONT SIZE="-1">(edit)</FONT>'
+ if $tax_rate->tax > 0 || $tax_rate->taxbase > 0;
+ push @rate,
+ ($tax_rate->excessrate * 100). '%&nbsp;<FONT SIZE="-1">(edit)</FONT>'
+ if $tax_rate->excessrate > 0;
+ push @rate,
+ $money_char. $tax_rate->fee.
+ qq!&nbsp;per&nbsp;$units<FONT SIZE="-1">(edit)</FONT>!
+ if $tax_rate->fee > 0 || $tax_rate->feebase > 0;
+ push @rate,
+ $money_char. $tax_rate->excessfee.
+ qq!&nbsp;per&nbsp;$units<FONT SIZE="-1">(edit)</FONT>!
+ if $tax_rate->excessfee > 0;
+
+
+ [ map [ {'data'=>$_} ], @rate ];
+};
+
+my $limit_sub = sub {
+ my $tax_rate = shift;
+
+ my $maxtype = $tax_rate->maxtype_name;
+ $maxtype =~ s/ /&nbsp;/g;
+
+ my $units = $tax_rate->unittype_name;
+ $units =~ s/ /&nbsp;/g;
+
+ my @limit = ();
+ push @limit,
+ sprintf("$money_char%.2f&nbsp%s", $tax_rate->taxbase, $maxtype )
+ if $tax_rate->taxbase > 0;
+ push @limit,
+ sprintf("$money_char%.2f&nbsp;tax", $tax_rate->taxmax )
+ if $tax_rate->taxmax > 0;
+ push @limit,
+ $tax_rate->feebase. "&nbsp;$units". ($tax_rate->feebase == 1 ? '' : 's')
+ if $tax_rate->feebase > 0;
+ push @limit,
+ $tax_rate->feemax. "&nbsp;$units". ($tax_rate->feebase == 1 ? '' : 's')
+ if $tax_rate->feemax > 0;
+
+ push @limit, 'Excluding&nbsp;setup&nbsp;fee'
+ if $tax_rate->setuptax =~ /^Y$/i;
+
+ push @limit, 'Excluding&nbsp;recurring&nbsp;fee'
+ if $tax_rate->recurtax =~ /^Y$/i;
+
+ [ map [ {'data'=>$_} ], @limit ];
+};
+
+my $oldrow;
+my $cell_style;
+my $cell_style_sub = sub {
+ my $row = shift;
+ if ( $oldrow ne $row ) {
+ if ( $oldrow ) {
+ if ( $oldrow->country ne $row->country ) {
+ $cell_style = 'border-top:1px solid #000000';
+ } elsif ( $oldrow->state ne $row->state ) {
+ $cell_style = 'border-top:1px solid #cccccc'; #default?
+ } elsif ( $oldrow->state eq $row->state ) {
+ #$cell_style = 'border-top:dashed 1px dark gray';
+ $cell_style = 'border-top:1px dashed #cccccc';
+ }
+ }
+ $oldrow = $row;
+ }
+ return $cell_style;
+};
+
+my $select_link = [ 'javascript:void(0);', sub { ''; } ];
+
+my $select_onclick = sub {
+ my $row = shift;
+ my $taxnum = $row->taxnum;
+ my $color = '#333399';
+ qq!overlib( OLiframeContent('${p}edit/tax_rate.html?$taxnum', 540, 620, 'edit_tax_rate_popup' ), CAPTION, 'Edit tax rate', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '$color', CGCOLOR, '$color' ); return false;!;
+};
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @menubar;
+my $title = '';
+
+my $data_vendor = '';
+if ( $cgi->param('data_vendor') =~ /^(\w+)$/ ) {
+ $data_vendor = $1;
+ $title = "$data_vendor";
+}
+$cgi->delete('data_vendor');
+
+my $geocode = '';
+if ( $cgi->param('geocode') =~ /^(\w+)$/ ) {
+ $geocode = $1;
+ $title = " geocode $geocode";
+}
+$cgi->delete('geocode');
+
+$title = " for $title" if $title;
+
+my $taxclassnum = '';
+if ( $cgi->param('taxclassnum') =~ /^(\d+)$/ ) {
+ $taxclassnum = $1;
+ my $tax_class = qsearchs('tax_class', {'taxclassnum' => $taxclassnum});
+ if ($tax_class) {
+ $title .= " for ". $tax_class->taxclass.
+ " (". $tax_class->description. ") tax class";
+ }else{
+ $taxclassnum = '';
+ }
+}
+$cgi->delete('taxclassnum');
+
+my $tax_type = $1
+ if ( $cgi->param('tax_type') =~ /^(\d+)$/ );
+my $tax_cat = $1
+ if ( $cgi->param('tax_cat') =~ /^(\d+)$/ );
+
+if ($tax_type || $tax_cat ) {
+ my $compare = "LIKE '". ( $tax_type || "%" ). ":". ( $tax_cat || "%" ). "'";
+ $compare = "= '$tax_type:$tax_cat'" if ($tax_type && $tax_cat);
+ my @tax_class =
+ qsearch({ 'table' => 'tax_class',
+ 'hashref' => {},
+ 'extra_sql' => "WHERE taxclass $compare",
+ });
+ if (@tax_class) {
+ $tax_class[0]->description =~ /^(.*):(.*)/;
+ $title .= " for";
+ $title .= " $tax_type ($1) tax type" if $tax_type;
+ $title .= " and" if ($tax_type && $tax_cat);
+ $title .= " $tax_cat ($2) tax category" if $tax_cat;
+ }else{
+ $tax_type = '';
+ $tax_cat = '';
+ }
+}
+$cgi->delete('tax_type');
+$cgi->delete('tax_cat');
+
+if ( $geocode || $taxclassnum ) {
+ push @menubar, 'View all tax rates' => $p.'browse/tax_rate.cgi';
+}
+
+$cgi->param('dummy', 1);
+
+#restore this so pagination works
+$cgi->param('data_vendor', $data_vendor) if $data_vendor;
+$cgi->param('geocode', $geocode) if $geocode;
+$cgi->param('taxclassnum', $taxclassnum ) if $taxclassnum;
+$cgi->param('tax_type', $tax_type ) if $tax_type;
+$cgi->param('tax_cat', $tax_cat ) if $tax_cat;
+
+my $html_form = include('/elements/init_overlib.html'). '<BR><BR>'.
+ join(' ',
+ map {
+ include('/elements/popup_link.html',
+ {
+ 'action' => $p. "misc/enable_or_disable_tax.html?action=$_&".
+ $cgi->query_string,
+ 'label' => ucfirst($_). ' all these taxes',
+ 'actionlabel' => ucfirst($_). ' taxes',
+ },
+ );
+ }
+ qw(disable enable)
+ );
+
+my ($query, $count_query) = FS::tax_rate::browse_queries(scalar($cgi->Vars));
+
+$cell_style = '';
+
+my @header = ( 'Location Code', );
+my @header2 = ( '', );
+my @links = ( '', );
+my @link_onclicks = ( '', );
+my $align = 'l';
+
+my @fields = (
+ 'geocode',
+);
+
+my @color = (
+ '000000',
+);
+
+push @header, qq!Tax class (<A HREF="${p}edit/tax_class.html">add new</A>)!;
+push @header2, '(per-tax classification)';
+push @fields, 'taxclass_description';
+push @color, '000000';
+push @links, '';
+push @link_onclicks, '';
+$align .= 'l';
+
+push @header, 'Tax name',
+ 'Rate', #'Tax',
+ 'Limits',
+ ;
+
+push @header2, '(printed on invoices)',
+ '',
+ '',
+ ;
+
+push @fields,
+ sub { shift->taxname || 'Tax' },
+ $rate_sub,
+ $limit_sub,
+;
+
+push @color,
+ sub { shift->taxname ? '000000' : '666666' },
+ sub { shift->tax ? '000000' : '666666' },
+ '000000',
+;
+
+$align .= 'lrl';
+
+my @cell_style = map $cell_style_sub, (1..scalar(@header));
+
+push @links, '', $select_link, '';
+push @link_onclicks, '', $select_onclick, '';
+
+my $html_init = '';
+
+$html_init .= qq(
+ <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws_iframe.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws_draggable.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/iframecontentmws.js"></SCRIPT>
+
+);
+
+$html_init .= qq(
+ <FORM>
+ <TABLE>
+ <TR>
+ <TD><SELECT NAME="data_vendor" onChange="this.form.submit()">
+);
+
+my $sql = "SELECT DISTINCT data_vendor FROM tax_rate ORDER BY data_vendor";
+my $dbh = dbh;
+my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (['(choose data vendor)'], @{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $data_vendor ? " SELECTED" : "").
+ '">'. $_->[0];
+}
+$html_init .= qq(
+ </SELECT>
+
+ <TD><INPUT NAME="geocode" TYPE="text" SIZE="12" VALUE="$geocode"></TD>
+
+<!-- generic
+ <TD><INPUT NAME="taxclassnum" TYPE="text" SIZE="12" VALUE="$taxclassnum"></TD>
+ <TD><INPUT TYPE="submit" VALUE="Filter by tax_class"></TD>
+-->
+
+<!-- cch specific -->
+ <TD><SELECT NAME="tax_type" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ "substring(taxclass from 1 for position(':' in taxclass)-1),".
+ "substring(description from 1 for position(':' in description)-1) ".
+ "FROM tax_class WHERE data_vendor='cch' ORDER BY 2";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (['', '(choose tax type)'], @{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_type ? " SELECTED" : "").
+ '">'. $_->[1];
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ <TD><SELECT NAME="tax_cat" onChange="this.form.submit()">
+);
+
+$sql = "SELECT DISTINCT ".
+ "substring(taxclass from position(':' in taxclass)+1),".
+ "substring(description from position(':' in description)+1) ".
+ "from tax_class WHERE data_vendor='cch' ORDER BY 2";
+
+$sth = $dbh->prepare($sql) or die $dbh->errstr;
+$sth->execute or die $sth->errstr;
+for (['', '(choose tax category)'], @{$sth->fetchall_arrayref}) {
+ $html_init .= '<OPTION VALUE="'. $_->[0]. '"'.
+ ($_->[0] eq $tax_cat ? " SELECTED" : "").
+ '">'. $_->[1];
+}
+
+$html_init .= qq(
+ </SELECT>
+
+ </TR>
+ <TR>
+ <TD></TD>
+ <TD><INPUT TYPE="submit" VALUE="Filter by geocode"></TD>
+ <TD></TD>
+ <TD></TD>
+ </TR>
+ </TABLE>
+ </FORM>
+
+);
+
+</%init>
diff --git a/httemplate/browse/usage_class.html b/httemplate/browse/usage_class.html
new file mode 100644
index 000000000..63fd2c5a2
--- /dev/null
+++ b/httemplate/browse/usage_class.html
@@ -0,0 +1,28 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Usage classes',
+ 'html_init' => $html_init,
+ 'name' => 'usage classes',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
+ 'query' => { 'table' => 'usage_class',
+ 'hashref' => {},
+ 'extra_sql' => 'ORDER BY classnum',
+ },
+ 'count_query' => 'SELECT COUNT(*) FROM usage_class',
+ 'header' => [ '#', 'Class' ],
+ 'fields' => [ 'classnum', 'classname' ],
+ 'links' => [ $link, $link ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ 'Usage classes define groups of usage for taxation purposes.<BR><BR>'.
+ qq!<A HREF="${p}edit/usage_class.html"><I>Add a usage class</I></A><BR><BR>!;
+
+my $link = [ $p.'edit/usage_class.html?', 'classnum' ];
+
+</%init>
diff --git a/httemplate/config/config-delete.cgi b/httemplate/config/config-delete.cgi
new file mode 100644
index 000000000..cdac434fa
--- /dev/null
+++ b/httemplate/config/config-delete.cgi
@@ -0,0 +1,15 @@
+<%init>
+die "access denied\n"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+die "No configuration item specified (bad URL)!" unless $cgi->keywords;
+my ($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $confnum = $1;
+
+my $conf = qsearchs('conf', {'confnum' => $confnum});
+die "Configuration not found!" unless $conf;
+$conf->delete;
+
+</%init>
+<% $cgi->redirect(popurl(2) . "browse/agent.cgi") %>
diff --git a/httemplate/config/config-download.cgi b/httemplate/config/config-download.cgi
new file mode 100644
index 000000000..6979246db
--- /dev/null
+++ b/httemplate/config/config-download.cgi
@@ -0,0 +1,28 @@
+%
+%
+%my $conf=new FS::Conf;
+%
+%http_header('Content-Type' => 'application/x-unknown' );
+%
+%die "No configuration variable specified (bad URL)!" # umm
+% unless $cgi->param('key');
+%$cgi->param('key') =~ /^([-\w.]+)$/;
+%my $name = $1;
+%
+%my $agentnum;
+%if ($cgi->param('agentnum') =~ /^(\d+)$/) {
+% $agentnum = $1;
+%}
+%
+%http_header('Content-Disposition' => "attachment; filename=$name" );
+% print $conf->config_binary($name, $agentnum);
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agentnum;
+if ($cgi->param('agentnum') =~ /^(\d+)$/) {
+ $agentnum = $1;
+}
+
+</%init>
diff --git a/httemplate/config/config-image.cgi b/httemplate/config/config-image.cgi
new file mode 100644
index 000000000..892f7c65b
--- /dev/null
+++ b/httemplate/config/config-image.cgi
@@ -0,0 +1,19 @@
+<% $conf->config_binary($name, $agentnum) %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+http_header( 'Content-Type' => 'image/png' ); #just png for now
+
+$cgi->param('key') =~ /^([-\w.]+)$/ or die "illegal config option";
+my $name = $1;
+
+my $agentnum = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+}
+
+</%init>
diff --git a/httemplate/config/config-process.cgi b/httemplate/config/config-process.cgi
new file mode 100644
index 000000000..84bfdefcb
--- /dev/null
+++ b/httemplate/config/config-process.cgi
@@ -0,0 +1,105 @@
+<%init>
+die "access denied\n"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+$FS::Conf::DEBUG = 1;
+my @config_items = grep { $_->key != ~/^invoice_(html|latex|template)/ }
+ $conf->config_items;
+my %confitems = map { $_->key => $_ } $conf->config_items;
+
+my $agentnum = $cgi->param('agentnum');
+my $key = $cgi->param('key');
+my $i = $confitems{$key};
+
+my @touch = ();
+my @delete = ();
+my $n = 0;
+foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
+ if ( $type eq '' ) {
+ } elsif ( $type eq 'textarea' ) {
+ if ( $cgi->param($i->key.$n) ne '' ) {
+ my $value = $cgi->param($i->key.$n);
+ $value =~ s/\r\n/\n/g; #browsers?
+ $conf->set($i->key, $value, $agentnum);
+ } else {
+ $conf->delete($i->key, $agentnum);
+ }
+ } elsif ( $type eq 'binary' || $type eq 'image' ) {
+ if ( defined($cgi->param($i->key.$n)) && $cgi->param($i->key.$n) ) {
+ my $fh = $cgi->upload($i->key.$n);
+ if (defined($fh)) {
+ local $/;
+ $conf->set_binary($i->key, <$fh>, $agentnum);
+ }
+ }else{
+ warn "Condition failed for " . $i->key;
+ }
+ } elsif ( $type eq 'checkbox' ) {
+ if ( defined $cgi->param($i->key.$n) ) {
+ push @touch, $i->key;
+ } else {
+ push @delete, $i->key;
+ }
+ } elsif ( $type eq 'text' || $type eq 'select' || $type eq 'select-sub' ) {
+ if ( $cgi->param($i->key.$n) ne '' ) {
+ $conf->set($i->key, $cgi->param($i->key.$n), $agentnum);
+ } else {
+ $conf->delete($i->key, $agentnum);
+ }
+ } elsif ( $type eq 'editlist' || $type eq 'selectmultiple' ) {
+ if ( scalar(@{[ $cgi->param($i->key.$n) ]}) ) {
+ $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum);
+ } else {
+ $conf->delete($i->key, $agentnum);
+ }
+ }
+ $n++;
+}
+# warn @touch;
+$conf->touch($_, $agentnum) foreach @touch;
+$conf->delete($_, $agentnum) foreach @delete;
+
+</%init>
+<% header('Configuration set') %>
+ <SCRIPT TYPE="text/javascript">
+% my $n = 0;
+% foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
+ var configCell = window.top.document.getElementById('<% $i->key. $n %>');
+ //alert('found cell ' + configCell);
+% if ( $type eq 'textarea'
+% || $type eq 'editlist'
+% || $type eq 'selectmultiple' ) {
+ configCell.innerHTML =
+ '<font size="-2"><pre>' + "\n" +
+ <% encode_entities(join("\n",
+ map { length($_) > 88 ? substr($_,0,88).'...' : $_ }
+ $conf->config($i->key, $agentnum)
+ ) )
+ |js_string %> +
+ '</pre></font>';
+
+% } elsif ( $type eq 'checkbox' ) {
+% if ( $conf->exists($i->key, $agentnum) ) {
+ configCell.style.backgroundColor = '#00ff00';
+ configCell.innerHTML = 'YES';
+% } else {
+ configCell.style.backgroundColor = '#ff0000';
+ configCell.innerHTML = 'NO';
+% }
+% } elsif ( $type eq 'text' || $type eq 'select' ) {
+ configCell.innerHTML = <% $conf->exists($i->key, $agentnum) ? $conf->config($i->key, $agentnum) : '' |js_string %>;
+% } elsif ( $type eq 'select-sub' ) {
+ configCell.innerHTML =
+ <% $conf->config($i->key, $agentnum) |js_string %> + ': ' +
+ <% &{ $i->option_sub }( $conf->config($i->key, $agentnum) ) |js_string %>;
+% } else {
+ //alert('unknown type <% $type %>');
+ window.top.location.reload();
+% }
+
+% $n++;
+% }
+ parent.cClick();
+ </SCRIPT>
+ </BODY></HTML>
diff --git a/httemplate/config/config-view.cgi b/httemplate/config/config-view.cgi
new file mode 100644
index 000000000..0f5fd6213
--- /dev/null
+++ b/httemplate/config/config-view.cgi
@@ -0,0 +1,177 @@
+<% include("/elements/header.html", $title, menubar(@menubar)) %>
+
+Click on a configuration value to change it.
+<BR><BR>
+
+<% include('/elements/init_overlib.html') %>
+
+% if ($FS::UID::use_confcompat) {
+ <FONT SIZE="+1" COLOR="#ff0000">CONFIGURATION NOT STORED IN DATABASE -- USING COMPATIBILITY MODE</FONT><BR><BR>
+%}
+
+% foreach my $section (@sections) {
+
+ <A NAME="<% $section || 'unclassified' %>"></A>
+ <FONT SIZE="-2">
+
+% foreach my $nav_section (@sections) {
+%
+% if ( $section eq $nav_section ) {
+ [<A NAME="not<% $nav_section || 'unclassified' %>" style="background-color: #cccccc"><% ucfirst($nav_section || 'unclassified') %></A>]
+% } else {
+ [<A HREF="#<% $nav_section || 'unclassified' %>"><% ucfirst($nav_section || 'unclassified') %></A>]
+% }
+%
+% }
+
+ </FONT><BR>
+ <TABLE BGCOLOR="#cccccc" BORDER=1 CELLSPACING=0 CELLPADDING=0 BORDERCOLOR="#999999">
+ <tr>
+ <th colspan="2" bgcolor="#dcdcdc">
+ <% ucfirst($section || 'unclassified') %> configuration options
+ </th>
+ </tr>
+% foreach my $i (@{ $section_items{$section} }) {
+% my @types = ref($i->type) ? @{$i->type} : ($i->type);
+% my( $width, $height ) = ( 522, 336 );
+% if ( grep $_ eq 'textarea', @types ) {
+% #800x600
+% $width = 763;
+% $height = 408;
+% #1024x768
+% #$width =
+% #$height =
+% }
+
+ <tr>
+ <td><% include('/elements/popup_link.html',
+ 'action' => 'config.cgi?key='. $i->key.
+ ';agentnum='. $agentnum,
+ 'width' => $width,
+ 'height' => $height,
+ 'actionlabel' => 'Enter configuration value',
+ 'label' => '<b>'. $i->key. '</b>',
+ 'aname' => $i->key,
+ )
+ %>: <% $i->description %>
+ </td>
+ <td><table border=0>
+
+% my $n = 0;
+% foreach my $type (@types) {
+
+% if ( $type eq '' ) {
+
+ <tr>
+ <td><font color="#ff0000">no type</font></td>
+ </tr>
+
+% } elsif ( $type eq 'image' ) {
+
+ <tr>
+
+ <% $conf->exists($i->key, $agentnum)
+ ? '<img src="config-image.cgi?key='. $i->key.
+ ';agentnum='. $agentnum. '">'
+ : 'empty'
+ %>
+ </tr>
+
+% } elsif ( $type eq 'binary' ) {
+
+ <tr>
+
+ <% $conf->exists($i->key, $agentnum)
+ ? qq!<a href="config-download.cgi?key=!. $i->key. ';agentnum='. $agentnum. qq!">download</a>!
+ : 'empty'
+ %>
+ </tr>
+
+% } elsif ( $type eq 'textarea'
+% || $type eq 'editlist'
+% || $type eq 'selectmultiple' ) {
+
+ <tr>
+ <td id="<% $i->key.$n %>" bgcolor="#ffffff">
+<font size="-2"><pre>
+<% encode_entities(join("\n",
+ map { length($_) > 88 ? substr($_,0,88).'...' : $_ }
+ $conf->config($i->key, $agentnum)
+ ) )
+%>
+</pre></font>
+ </td>
+ </tr>
+% } elsif ( $type eq 'checkbox' ) {
+
+ <tr>
+ <td id="<% $i->key.$n %>" bgcolor="#<% $conf->exists($i->key, $agentnum) ? '00ff00">YES' : 'ff0000">NO' %></td>
+ </tr>
+% } elsif ( $type eq 'text' || $type eq 'select' ) {
+
+ <tr>
+ <td id="<% $i->key.$n %>" bgcolor="#ffffff">
+ <% $conf->exists($i->key, $agentnum) ? $conf->config($i->key, $agentnum) : '' %>
+ </td></tr>
+% } elsif ( $type eq 'select-sub' ) {
+
+ <tr>
+ <td id="<% $i->key.$n %>" bgcolor="#ffffff">
+ <% $conf->config($i->key, $agentnum) %>:
+ <% &{ $i->option_sub }( $conf->config($i->key, $agentnum) ) %>
+ </td>
+ </tr>
+% } else {
+
+ <tr><td>
+ <font color="#ff0000">unknown type <% $type %></font>
+ </td></tr>
+% }
+% $n++;
+% }
+
+ </table></td>
+ </tr>
+% }
+
+ </table><br><br>
+% }
+
+
+</body></html>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agentnum = '';
+my $title;
+my @menubar = ();
+if ($cgi->param('agentnum') =~ /^(\d+)$/) {
+ $agentnum = $1;
+ my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ die "Agent $agentnum not found!" unless $agent;
+
+ push @menubar, 'View all agents' => $p.'browse/agent.cgi';
+ $title = 'Agent Configuration for '. $agent->agent;
+} else {
+ $title = 'Global Configuration';
+}
+
+my $conf = new FS::Conf;
+
+my @config_items = grep { $agentnum ? $_->per_agent : 1 }
+ grep { $_->key != ~/^invoice_(html|latex|template)/ }
+ $conf->config_items;
+
+my @sections = qw(required billing username password UI session shell BIND );
+push @sections, '', 'deprecated';
+
+my %section_items = ();
+foreach my $section (@sections) {
+ $section_items{$section} = [ grep $_->section eq $section, @config_items ];
+}
+
+@sections = grep scalar( @{ $section_items{$_} } ), @sections;
+
+</%init>
diff --git a/httemplate/config/config.cgi b/httemplate/config/config.cgi
new file mode 100644
index 000000000..f390c64a3
--- /dev/null
+++ b/httemplate/config/config.cgi
@@ -0,0 +1,331 @@
+<% include("/elements/header-popup.html", $title) %>
+
+<SCRIPT>
+var gSafeOnload = new Array();
+var gSafeOnsubmit = new Array();
+window.onload = SafeOnload;
+function SafeAddOnLoad(f) {
+ gSafeOnload[gSafeOnload.length] = f;
+}
+function SafeOnload() {
+ for (var i=0;i<gSafeOnload.length;i++)
+ gSafeOnload[i]();
+}
+function SafeAddOnSubmit(f) {
+ gSafeOnsubmit[gSafeOnsubmit.length] = f;
+}
+function SafeOnsubmit() {
+ for (var i=0;i<gSafeOnsubmit.length;i++)
+ gSafeOnsubmit[i]();
+}
+</SCRIPT>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="OneTrueForm" ACTION="config-process.cgi" METHOD="POST" enctype="multipart/form-data" onSubmit="SafeOnsubmit()">
+<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agentnum %>">
+<INPUT TYPE="hidden" NAME="key" VALUE="<% $key %>">
+
+Setting <b><% $key %></b>
+
+% my $description_printed = 0;
+% if ( grep $_ eq 'textarea', @types ) {
+% $description_printed = 1;
+
+ - <% $description %>
+
+% }
+
+<table><tr><td>
+
+% my $n = 0;
+% foreach my $type (@types) {
+% if ( $type eq '' ) {
+
+ <font color="#ff0000">no type</font>
+
+% } elsif ( $type eq 'image' ) {
+
+ <% $conf->exists($key, $agentnum)
+ ? 'Current image<br>'.
+ '<img src="config-image.cgi?key='. $key.
+ ';agentnum='. $agentnum. '"><br>'
+ : ''
+ %>
+
+ <BR>
+ New image filename <input type="file" name="<% "$key$n" %>">
+
+% } elsif ( $type eq 'binary' ) {
+
+ Filename <input type="file" name="<% "$key$n" %>">
+
+% } elsif ( $type eq 'textarea' ) {
+
+ <textarea name="<% "$key$n" %>" rows=12 cols=78 wrap="off"><% join("\n", $conf->config($key, $agentnum)) |h %></textarea>
+
+% } elsif ( $type eq 'checkbox' ) {
+
+ <input name="<% "$key$n" %>" type="checkbox" value="1"
+ <% $conf->exists($key, $agentnum) ? 'CHECKED' : '' %> >
+
+% } elsif ( $type eq 'text' ) {
+
+ <input name="<% "$key$n" %>" type="text" value="<% $conf->exists($key, $agentnum) ? $conf->config($key, $agentnum) : '' |h %>">
+
+% } elsif ( $type eq 'select' || $type eq 'selectmultiple' ) {
+
+ <select name="<% "$key$n" %>" <% $type eq 'selectmultiple' ? 'MULTIPLE' : '' %>>
+
+%
+% my %hash = ();
+% if ( $config_item->select_enum ) {
+% tie %hash, 'Tie::IxHash',
+% '' => '', map { $_ => $_ } @{ $config_item->select_enum };
+% } elsif ( $config_item->select_hash ) {
+% if ( ref($config_item->select_hash) eq 'ARRAY' ) {
+% tie %hash, 'Tie::IxHash',
+% '' => '', @{ $config_item->select_hash };
+% } else {
+% tie %hash, 'Tie::IxHash',
+% '' => '', %{ $config_item->select_hash };
+% }
+% } else {
+% %hash = ( '' => 'WARNING: neither select_enum nor select_hash specified in Conf.pm for configuration option "'. $key. '"' );
+% }
+%
+% my %saw = ();
+% foreach my $value ( keys %hash ) {
+% local($^W)=0; next if $saw{$value}++;
+% my $label = $hash{$value};
+%
+
+ <option value="<% $value %>"
+
+% if ( $value eq $conf->config($key, $agentnum)
+% || ( $type eq 'selectmultiple'
+% && grep { $_ eq $value } $conf->config($key, $agentnum) ) ) {
+
+ SELECTED
+
+% }
+
+ ><% $label %>
+
+% }
+% my $curvalue = $conf->config($key, $agentnum);
+% if ( $conf->exists($key, $agentnum) && $curvalue && ! $hash{$curvalue} ) {
+
+ <option value="<% $curvalue %>" SELECTED>
+
+% if ( exists( $hash{ $conf->config($key, $agentnum) } ) ) {
+
+ <% $hash{ $conf->config($key, $agentnum) } %>
+
+% }else{
+
+ <% $curvalue %>
+
+% }
+% }
+
+ </select>
+
+% } elsif ( $type eq 'select-sub' ) {
+
+ <select name="<% "$key$n" %>"><option value="">
+
+% my %options = &{$config_item->options_sub};
+% my @options = sort { $a <=> $b } keys %options;
+% my %saw;
+% foreach my $value ( @options ) {
+% local($^W)=0; next if $saw{$value}++;
+
+ <option value="<% $value %>" <% $value eq $conf->config($key, $agentnum) ? 'SELECTED' : '' %>><% $value %>: <% $options{$value} %>
+
+% }
+% my $curvalue = $conf->config($key, $agentnum);
+% if ( $conf->exists($key, $agentnum) && $curvalue && ! $options{$curvalue} ) {
+
+ <option value="<% $curvalue %>" SELECTED> <% $curvalue %>: <% &{ $config_item->option_sub }( $curvalue ) %>
+
+% }
+
+ </select>
+
+% } elsif ( $type eq 'editlist' ) {
+%
+ <script>
+ function doremove<% "$key$n" %>() {
+ fromObject = document.OneTrueForm.<% "$key$n" %>;
+ for (var i=fromObject.options.length-1;i>-1;i--) {
+ if (fromObject.options[i].selected)
+ deleteOption<% "$key$n" %>(fromObject,i);
+ }
+ }
+ function deleteOption<% "$key$n" %>(object,index) {
+ object.options[index] = null;
+ }
+ function selectall<% "$key$n" %>() {
+ fromObject = document.OneTrueForm.<% "$key$n" %>;
+ for (var i=fromObject.options.length-1;i>-1;i--) {
+ fromObject.options[i].selected = true;
+ }
+ }
+ function doadd<% "$key$n" %>(object) {
+ var myvalue = "";
+
+% if ( defined($config_item->editlist_parts) ) {
+% foreach my $pnum ( 0 .. scalar(@{$config_item->editlist_parts})-1 ) {
+
+ if ( myvalue != "" ) { myvalue = myvalue + " "; }
+
+% if ( $config_item->editlist_parts->[$pnum]{type} eq 'select' ) {
+
+ myvalue = myvalue + object.add<% "$key${n}_$pnum" %>.options[object.add<% "$key${n}_$pnum" %>.selectedIndex].value
+ <!-- #RESET SELECT?? maybe not... -->
+
+% } elsif ( $config_item->editlist_parts->[$pnum]{type} eq 'immutable' ) {
+
+ myvalue = myvalue + object.add<% "$key${n}_$pnum" %>.value
+
+% } else {
+
+ myvalue = myvalue + object.add<% "$key${n}_$pnum" %>.value
+ object.add<% "$key${n}_$pnum" %>.value = ""
+
+% }
+% }
+% } else {
+
+ myvalue = object.add<% "$key${n}_1" %>.value
+
+% }
+
+ var optionName = new Option(myvalue, myvalue);
+ var length = object.<% "$key$n" %>.length;
+ object.<% "$key$n" %>.options[length] = optionName;
+ }
+ </script>
+ <select multiple size=5 name="<% "$key$n" %>">
+ <option selected>----------------------------------------------------------------</option>
+
+% foreach my $line ( $conf->config($key, $agentnum) ) {
+
+ <option value="<% $line %>"><% $line %></option>
+
+% }
+
+ </select><br>
+ <input type="button" value="remove selected" onClick="doremove<% "$key$n" %>()">
+ <script>SafeAddOnLoad(doremove<% "$key$n" %>);
+ SafeAddOnSubmit(selectall<% "$key$n" %>);
+ </script>
+ <br><% itable() %><tr>
+
+% if ( defined $config_item->editlist_parts ) {
+% my $pnum=0;
+% foreach my $part ( @{$config_item->editlist_parts} ) {
+
+ <td>
+
+% if ( $part->{type} eq 'text' ) {
+
+ <input type="text" name="add<% "$key${n}_$pnum" %>">
+
+% } elsif ( $part->{type} eq 'immutable' ) {
+
+ <% $part->{value} %>
+ <input type="hidden" name="add<% "$key${n}_$pnum" %>" value="<% $part->{value} %>">
+
+% } elsif ( $part->{type} eq 'select' ) {
+
+ <select name="add<% qq!$key${n}_$pnum! %>">
+
+% foreach my $key ( keys %{$part->{select_enum}} ) {
+
+ <option value="<% $key %>"><% $part->{select_enum}{$key} %></option>
+
+% }
+
+ </select>
+
+% } else {
+
+ <font color="#ff0000">unknown type <% $part->type %> </font>
+
+% }
+
+ </td>
+
+% $pnum++;
+% }
+% } else {
+
+ <td><input type="text" name="add<% "$key${n}_0" %>></td>
+
+% }
+
+ <td><input type="button" value="add" onClick="doadd<% "$key$n" %>(this.form)"></td>
+ </tr></table>
+
+% } else {
+
+ <font color="#ff0000">unknown type <% $type %></font>
+
+% }
+% $n++;
+% }
+
+ </td>
+% unless ( $description_printed ) {
+ <td><% $description %></td>
+% }
+</tr>
+</table>
+<INPUT TYPE="submit" VALUE="<% $title %>">
+</FORM>
+
+</BODY>
+</HTML>
+<%once>
+
+my $conf = new FS::Conf;
+my @config_items = grep { $_->key != ~/^invoice_(html|latex|template)/ }
+ $conf->config_items;
+my %confitems = map { $_->key => $_ } @config_items;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $action = 'Set';
+
+my $agentnum = '';
+if ($cgi->param('agentnum') =~ /(\d+)$/) {
+ $agentnum=$1;
+}
+
+my $agent = '';
+my $title;
+if ($agentnum) {
+ $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "Agent $agentnum not found!" unless $agent;
+
+ $title = "$action configuration override for ". $agent->agent;
+} else {
+ $title = "$action global configuration";
+}
+
+$cgi->param('key') =~ /^([-.\w]+)$/ or die "illegal configuration item";
+my $key = $1;
+my $value = $conf->config($key);
+my $config_item = $confitems{$key};
+
+my $description = $config_item->description;
+my $config_type = $config_item->type;
+my @types = ref($config_type) ? @$config_type : ($config_type);
+
+</%init>
diff --git a/httemplate/docs/AGPL.html b/httemplate/docs/AGPL.html
new file mode 100644
index 000000000..f55bebb16
--- /dev/null
+++ b/httemplate/docs/AGPL.html
@@ -0,0 +1,672 @@
+<h3 style="text-align: center;">GNU AFFERO GENERAL PUBLIC LICENSE</h3>
+<p style="text-align: center;">Version 3, 19 November 2007</p>
+
+<p>Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;
+ <br>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.</p>
+
+<h3>Preamble</h3>
+
+<p>The GNU Affero General Public License is a free, copyleft license
+for software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.</p>
+
+<p>The licenses for most software and other practical works are
+designed to take away your freedom to share and change the works. By
+contrast, our General Public Licenses are intended to guarantee your
+freedom to share and change all versions of a program--to make sure it
+remains free software for all its users.</p>
+
+<p>When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.</p>
+
+<p>Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.</p>
+
+<p>A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.</p>
+
+<p>The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.</p>
+
+<p>An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.</p>
+
+<p>The precise terms and conditions for copying, distribution and
+modification follow.</p>
+
+<h3>TERMS AND CONDITIONS</h3>
+
+<h4>0. Definitions.</h4>
+
+<p>"This License" refers to version 3 of the GNU Affero General Public
+License.</p>
+
+<p>"Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.</p>
+
+<p>"The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.</p>
+
+<p>To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.</p>
+
+<p>A "covered work" means either the unmodified Program or a work based
+on the Program.</p>
+
+<p>To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.</p>
+
+<p>To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.</p>
+
+<p>An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.</p>
+
+<h4>1. Source Code.</h4>
+
+<p>The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.</p>
+
+<p>A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.</p>
+
+<p>The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.</p>
+
+<p>The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.</p>
+
+<p>The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.</p>
+
+<p>The Corresponding Source for a work in source code form is that
+same work.</p>
+
+<h4>2. Basic Permissions.</h4>
+
+<p>All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.</p>
+
+<p>You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.</p>
+
+<p>Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.</p>
+
+<h4>3. Protecting Users' Legal Rights From Anti-Circumvention Law.</h4>
+
+<p>No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.</p>
+
+<p>When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.</p>
+
+<h4>4. Conveying Verbatim Copies.</h4>
+
+<p>You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.</p>
+
+<p>You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.</p>
+
+<h4>5. Conveying Modified Source Versions.</h4>
+
+<p>You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:</p>
+
+<ul>
+<li>a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.</li>
+
+<li>b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".</li>
+
+<li>c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.</li>
+
+<li>d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.</li>
+
+</ul>
+<p>A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.</p>
+
+<h4>6. Conveying Non-Source Forms.</h4>
+
+<p>You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:</p>
+
+<ul>
+<li>a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.</li>
+
+<li>b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.</li>
+
+<li>c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.</li>
+
+<li>d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.</li>
+
+<li>e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.</li>
+
+</ul>
+<p>A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.</p>
+
+<p>A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.</p>
+
+<p>"Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.</p>
+
+<p>If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).</p>
+
+<p>The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.</p>
+
+<p>Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.</p>
+
+<h4>7. Additional Terms.</h4>
+
+<p>"Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.</p>
+
+<p>When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.</p>
+
+<p>Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:</p>
+
+<ul>
+<li>a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or</li>
+
+<li>b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or</li>
+
+<li>c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or</li>
+
+<li>d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or</li>
+
+<li>e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or</li>
+
+<li>f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.</li>
+
+</ul>
+<p>All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further restriction,
+you may remove that term. If a license document contains a further
+restriction but permits relicensing or conveying under this License, you
+may add to a covered work material governed by the terms of that license
+document, provided that the further restriction does not survive such
+relicensing or conveying.</p>
+
+<p>If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.</p>
+
+<p>Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.</p>
+
+<h4>8. Termination.</h4>
+
+<p>You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).</p>
+
+<p>However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.</p>
+
+<p>Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.</p>
+
+<p>Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.</p>
+
+<h4>9. Acceptance Not Required for Having Copies.</h4>
+
+<p>You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.</p>
+
+<h4>10. Automatic Licensing of Downstream Recipients.</h4>
+
+<p>Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.</p>
+
+<p>An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.</p>
+
+<p>You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.</p>
+
+<h4>11. Patents.</h4>
+
+<p>A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".</p>
+
+<p>A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.</p>
+
+<p>Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.</p>
+
+<p>In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.</p>
+
+<p>If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.</p>
+
+<p>If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.</p>
+
+<p>A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.</p>
+
+<p>Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.</p>
+
+<h4>12. No Surrender of Others' Freedom.</h4>
+
+<p>If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.</p>
+
+<h4>13. Remote Network Interaction; Use with the GNU General Public License.</h4>
+
+<p>Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.</p>
+
+<p>Notwithstanding any other provision of this License, you have permission
+to link or combine any covered work with a work licensed under version 3
+of the GNU General Public License into a single combined work, and to
+convey the resulting work. The terms of this License will continue to
+apply to the part which is the covered work, but the work with which it is
+combined will remain governed by version 3 of the GNU General Public
+License.</p>
+
+<h4>14. Revised Versions of this License.</h4>
+
+<p>The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may differ
+in detail to address new problems or concerns.</p>
+
+<p>Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero
+General Public License "or any later version" applies to it, you have
+the option of following the terms and conditions either of that
+numbered version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number
+of the GNU Affero General Public License, you may choose any version
+ever published by the Free Software Foundation.</p>
+
+<p>If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that
+proxy's public statement of acceptance of a version permanently
+authorizes you to choose that version for the Program.</p>
+
+<p>Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.</p>
+
+<h4>15. Disclaimer of Warranty.</h4>
+
+<p>THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>
+
+<h4>16. Limitation of Liability.</h4>
+
+<p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.</p>
+
+<h4>17. Interpretation of Sections 15 and 16.</h4>
+
+<p>If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.</p>
+
+<p>END OF TERMS AND CONDITIONS</p>
+
+<h3>How to Apply These Terms to Your New Programs</h3>
+
+<p>If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.</p>
+
+<p>To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.</p>
+
+<pre> &lt;one line to give the program's name and a brief idea of what it does.&gt;
+ Copyright (C) &lt;year&gt; &lt;name of author&gt;
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.
+</pre>
+
+<p>Also add information on how to contact you by electronic and paper mail.</p>
+
+<p>If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.</p>
+
+<p>You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+&lt;http://www.gnu.org/licenses/&gt;.
+</p>
+
diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html
new file mode 100644
index 000000000..dee424776
--- /dev/null
+++ b/httemplate/docs/about.html
@@ -0,0 +1,53 @@
+<% include('/elements/header-popup.html', 'Freeside') %>
+
+<% include('/elements/init_overlib.html') %>
+
+<CENTER>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<H3>version <% $FS::VERSION %></H3>
+</CENTER>
+
+<CENTER>
+<FONT SIZE="-1">&copy; 2008 Freeside Internet Services, Inc.<BR>
+All rights reserved.<BR>
+Licensed under the terms of the<BR>
+GNU <i>Affero</i> General Public License.<BR>
+</FONT>
+</CENTER>
+<BR>
+
+<CENTER>
+<A HREF="credits.html">Credits</A>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+<A HREF="javascript:void(0)" onClick="openLicense()">License</A>
+
+
+<BR><BR>
+<A HREF="http://www.freeside.biz/freeside" TARGET="_blank">Freeside homepage</A>
+</CENTER>
+
+<BR>
+
+<CENTER>
+<FONT SIZE="-3">"I need a miracle every day." -J.P. Barlow</FONT>
+</CENTER>
+
+<SCRIPT TYPE="text/javascript">
+
+function openLicense() {
+ parent.<% include('/elements/popup_link_onclick.html',
+ 'action' => $fsurl.'docs/license.html',
+ 'label' => 'License',
+ 'actionlabel' => 'License',
+ 'width' => 600,
+ 'height' => 360,
+ 'color' => '#7e0079',
+ 'nofalse' => 1,
+ )
+ %>
+}
+
+</SCRIPT>
+
+</BODY>
+</HTML>
diff --git a/httemplate/docs/ach.html b/httemplate/docs/ach.html
new file mode 100644
index 000000000..b8a17c87d
--- /dev/null
+++ b/httemplate/docs/ach.html
@@ -0,0 +1,10 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ Electronic check (ACH) information
+ </TITLE>
+ </HEAD>
+ <BODY BGCOLOR="#ffffff">
+ <IMG BORDER=0 SRC="../images/ach.png">
+ </BODY>
+</HTML>
diff --git a/httemplate/docs/admin.html b/httemplate/docs/admin.html
new file mode 100755
index 000000000..2aa934812
--- /dev/null
+++ b/httemplate/docs/admin.html
@@ -0,0 +1,41 @@
+<head>
+ <title>Administration</title>
+</head>
+<body>
+ <h1>Administration</h1>
+</body>
+<ul>
+ <li>Open up the root of the Freeside document tree in your web
+ browser. For example, if you created the Freeside document tree in
+ /home/httpd/html/freeside, and your web browser's DocumentRoot is
+ /home/httpd/html, open https://your_host/freeside/. Replace
+ "your_host" with the name or network address of your web server.
+ <li>Select <u>Configuration</u> from the main menu and update your configuration values.
+
+ <li>Go to <u>View/Edit service definitions</u> on the main menu, and
+ <u>Add a new service definition</u> with <i>Table</i> <b>svc_acct</b>.
+ Select your domain in the <b>domsvc</b> Modifier. Set <b>Fixed</b> to define
+ a service locked-in to this domain, or <b>Default</b> to define a service
+ which may select from among this domain and the customer's domains.
+
+ <li><table><tr>
+ <td> Create at least POP (Point of Presence) by selecting
+ <u>View/Edit POPs</u> from the main menu.</td>
+ <th align="left"> OR </th>
+ <td>If you are not doing dialup, set slipip to fixed and blank for all your
+ Service Definitions which have Table <b>svc_acct</b>.</td>
+ </tr></table>
+
+ <li>If you are using Freeside to keep track of sales taxes, define tax
+ information for your locales by clicking on the <u>View/Edit locales and tax
+ rates</u> on the main menu.
+
+ <li>If you would like Freeside to notify your customers when their credit
+ cards and other billing arrangements are about to expire, arrange for
+ <b>freeside-expiration-alerter</b> to be run daily by cron or similar
+ facility. The message it sends can be configured from the
+ <u>Configuration</u> choice of the main menu as <u>alerter_template</u>.
+
+</ul>
+</body>
+</html>
diff --git a/httemplate/docs/credits.html b/httemplate/docs/credits.html
new file mode 100644
index 000000000..3c5564da3
--- /dev/null
+++ b/httemplate/docs/credits.html
@@ -0,0 +1,175 @@
+<% include('/elements/header-popup.html', '') %>
+
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+
+<FONT SIZE=6>
+ <CENTER>Freeside</CENTER>
+</FONT>
+
+<BR>
+
+<CENTER>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<H3>version <% $FS::VERSION %></H3>
+</CENTER>
+
+<CENTER>
+
+<H3>Core team</H3>
+Peter Bowen<BR>
+Jeff Finucane<BR>
+Jason Hall<BR>
+Kristian Hoffman<BR>
+Ivan Kohler<BR>
+Richard Siddall<BR>
+<BR>
+
+<H3>Contributors</H3>
+Stephen Amadei<BR>
+Eric Arvidsson<BR>
+Mark Asplen-Taylor<BR>
+Mihai Bazon<BR>
+Charles A. Beasley<BR>
+Stephen Bechard<BR>
+Eric Bosrup<BR>
+Dave Burgess<BR>
+Joe Camadine<BR>
+Chris Cappuccio<BR>
+Rebecca Cardennis<BR>
+Shane Chrisp<BR>
+Luke Crawford<BR>
+Brad Dameron<BR>
+Dave Denney<BR>
+Serge Dolgov<BR>
+Scott Edwards<BR>
+Kenny Elliott<BR>
+Donald Greer<BR>
+Joel Griffiths<BR>
+Ryan Gunn<BR>
+Troy Hammonds<BR>
+Sean Hanson<BR>
+Dale Hege<BR>
+Kelly Hickel<BR>
+Mark James<BR>
+Frederico Caldeira Knabben<BR>
+Greg Kuhnert<BR>
+Randall Lucas<BR>
+Foteos Macrides<BR>
+Roger Mangraviti<BR>
+Brian McCane<BR>
+mimooh<BR>
+Mack Nagashima<BR>
+Matt Peterson<BR>
+Luke Pfeifer<BR>
+Ricardo Signes<BR>
+Matt Simerson<BR>
+Steve Simitzis<BR>
+Jason Spence<BR>
+James Switzer<BR>
+Audrey Tang<BR>
+Jason Thomas<BR>
+Jesse Vincent<BR>
+Mark Wells<BR>
+Peter Wemm<BR>
+Mark Williamson<BR>
+Tim Yardley<BR>
+
+</CENTER>
+
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+<BR>
+
+<SCRIPT TYPE="text/javascript">
+
+function myScroll() {
+
+ documentYposition += 1;
+ window.scroll(0,documentYposition);
+
+ var timeout = 25;
+
+ if ( documentYposition > documentLength ) {
+ documentYposition = 0;
+ }
+
+ if ( documentYposition == startingPosition ) {
+ timeout = 5000;
+ }
+
+ setTimeout('myScroll()', timeout);
+}
+
+function DelayThenScroll() {
+ window.scroll(0,documentYposition);
+ documentLength = myHeight();
+ setTimeout('myScroll()', 3000);
+}
+
+function myHeight() {
+/* if (document.all)
+ return document.body.offsetHeight;
+ else if (document.layers)
+ return document.body.document.height;
+ else
+*/
+ return 1700; // approx height (add more per contributors)
+}
+
+document.body.style.overflow = 'hidden';
+
+var startingPosition = 360;
+
+//huh, adjust for firefox
+var ua = navigator.userAgent;
+var opera = /opera [56789]|opera\/[56789]/i.test(ua);
+var webkit = /webkit/i.test(ua)
+var moz = !opera && !webkit && /gecko/i.test(ua);
+if ( moz ) {
+ startingPosition += 20;
+} else if ( opera ) {
+ startingPosition += 21;
+}
+
+var documentYposition = startingPosition;
+var documentLength;
+window.onLoad = DelayThenScroll();
+
+</SCRIPT>
+
+</BODY>
+</HTML>
diff --git a/httemplate/docs/cvv2.html b/httemplate/docs/cvv2.html
new file mode 100644
index 000000000..767098537
--- /dev/null
+++ b/httemplate/docs/cvv2.html
@@ -0,0 +1,24 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ CVV2 information
+ </TITLE>
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8">
+ The CVV2 number (also called CVC2 or CID) is a three- or four-digit
+ security code used to reduce credit card fraud.<BR><BR>
+ <TABLE BORDER=0 CELLSPACING=4>
+ <TR>
+ <TH>Visa / MasterCard / Discover</TH>
+ <TH>American Express</TH>
+ </TR>
+ <TR>
+ <TD>
+ <IMG BORDER=0 ALT="Visa/MasterCard/Discover" SRC="../images/cvv2.png">
+ </TD>
+ <TD>
+ <IMG BORDER=0 ALT="American Express" SRC="../images/cvv2_amex.png">
+ </TD>
+ </TABLE>
+ </BODY>
+</HTML>
diff --git a/httemplate/docs/ieak.html b/httemplate/docs/ieak.html
new file mode 100644
index 000000000..00c53423c
--- /dev/null
+++ b/httemplate/docs/ieak.html
@@ -0,0 +1,75 @@
+<pre>
+this is incomplete
+mostly it should be merged into signup.html and fs_signup/ieak.template
+
+- download and install the IEAK from
+ http://www.microsoft.com/windows/ieak/default.asp
+
+- Good examples may be found in
+ C:\Program Files\IEAK\toolkit\isp\server\ICW\signup\perl\signup08.pl
+ C:\Program Files\IEAK\toolkit\isp\server\ICW\reconfig\perl\reconfig04.pl
+ C:\Program Files\IEAK6\toolkit\isp\servless\basic\sample.ins
+ C:\Program Files\IEAK6\toolkit\isp\servless\advanced\4567.ins
+ C:\Program Files\IEAK6\toolkit\isp\servless\advanced\4568.ins
+ C:\Program Files\IEAK6\toolkit\isp\servless\advanced\7890.ins
+ C:\Program Files\IEAK6\toolkit\isp\servless\advanced\7891.ins
+
+- Full documentation on all the settings available in .INS files is
+ avaialble under Program Files | Microsoft IEAK 6 | IEAK Help
+ | Reference | Internet Settings (.ins) Files
+
+- Freeside will make the following substitutions before sending the file
+ to the user:
+
+ { $ac } - area code of selected POP
+ { $exch } - exchange of selected POP
+ { $loc } - local part of selected POP
+ { $username }
+ { $password }
+ { $email_name } - first and last name
+ { $pkg } - package name
+
+- Simple example follows:
+
+[Entry]
+Entry Name = IEAK Sample
+[Phone]
+Dial_As_Is = No
+Phone_Number = { $exch }{ $loc }
+Area_Code = { $ac }
+Country_Code = 1
+Country_Id = 1
+[Server]
+Type = PPP
+SW_Compress = Yes
+PW_Encrypt = Yes
+Negotiate_TCP/IP = Yes
+Disable_LCP = No
+[TCP/IP]
+Specity_IP_Address = No
+Specity_Server_Address = No
+IP_Header_Compress = Yes
+Gateway_On_Remote = Yes
+[User]
+Name = { $username }
+Passowrd = { $password }
+Display_Password = Yes
+[Internet_Mail]
+Email_Name = { $email_name }
+Email_Address = { $username }@example.com
+POP_Server = mail.example.com
+POP_Server_Port_Number = 110
+POP_Logon_Password = { $password }
+SMTP_Server = mail.example.com
+SMTP_Server_Port_Number = 25
+Install_Mail = 1
+[URL]
+Help_Page = http://www.ieaksample.net/helpdesk
+Home_Page = http://www.ieaksample.net
+Search_Page = http://www.ieaksample,net/search
+[Favorites]
+IEAK Sample \\ IEAK Sample Home Page.url = http://acme.ieaksample.net/
+[Branding]
+Window_Title = Internet Explorer from Acme Internet Services
+
+</pre>
diff --git a/httemplate/docs/index.html b/httemplate/docs/index.html
new file mode 100644
index 000000000..3b419de00
--- /dev/null
+++ b/httemplate/docs/index.html
@@ -0,0 +1,32 @@
+<head>
+ <title>Freeside Documentation</title>
+</head>
+<body bgcolor="#ffffff">
+ <h1>Freeside Documentation</h1>
+<img src="overview-new.png">
+<h3>Installation and upgrades</h3>
+<ul>
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Installation">New Installation</a>
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:RT_Installation">Installing integrated RT ticketing</a>
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Self-Service_Installation">Signup/Self-service installation</a>
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Upgrading">Upgrading from 1.5.8 or 1.6.X</a>
+</ul>
+<h3>Configuration and setup</h3>
+<ul>
+<!--
+ <li><a href="config.html">Configuration files</a>
+!-->
+ <li><a href="admin.html">Administration</a>
+<!--
+ <li><a href="../index.html#admin">Administration</a>
+!-->
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Exports_.28provisioning.29">Exports</a>
+ <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Billing">Billing</a>
+</ul>
+<h3>Developer</h3>
+<ul>
+ <li><a href="schema.html">Schema reference</a>
+ <li><a href="man/FS.html">Perl API</a>
+ <li><a href="legacy.html">Importing legacy data</a>
+</ul>
+</body>
diff --git a/httemplate/docs/legacy.html b/httemplate/docs/legacy.html
new file mode 100755
index 000000000..94efe53af
--- /dev/null
+++ b/httemplate/docs/legacy.html
@@ -0,0 +1,39 @@
+<head>
+ <title>Importing legacy data</title>
+</head>
+<body>
+ <h1>Importing legacy data</h1>
+<font size="+2">In almost all cases, legacy data import will require writing custom code to deal with your particular legacy data. The example scripts here will probably <b>not</b> work "out-of-the-box", and are provided <b>as a starting point only</b>.</font>
+<br><br><i>Some import scripts may require installation of the <a href="http://search.cpan.org/search?dist=Array-PrintCols">Array-PrintCols</a> and <a href="http://search.cpan.org/search?dist=Term-Query">Term-Query</a> (make test broken; install manually) modules.</i><br>
+<ul>
+ <li><a name="bind">bin/bind.import</a> - Import domain information from BIND named
+ <li><a name="passwd">bin/passwd.import</a> - Just import `passwd' and `shadow' or `master.passwd', no RADIUS import.
+ <li><a name="svc_acct">bin/svc_acct.import</a> - Import `passwd', ( `shadow' or `master.passwd' ) and RADIUS `users'. Before running bin/svc_acct.import, you need <a href="../browse/part_svc.cgi">services</a> (with table svc_acct) as follows:
+ <ul>
+ <li>Most accounts probably have entries in passwd and users (with Port-Limit nonexistant or 1)
+ <li>Some accounts have entries in passwd and users, but with Port-Limit 2 (or more)
+ <li>Some accounts might have entries in users only (Port-Limit 1)
+ <li>Some accounts might have entries in users only (Port-Limit >= 2)
+ <li>POP mail accounts have entries in passwd only, and have a particular shell.
+ <li>Everything else in passwd is a shell account.
+ </ul>
+<!-- <li><a name="svc_acct_sm">bin/svc_acct_sm.import</a> - Import qmail ( `virtualdomains' and `rcpthosts' ), or sendmail ( `virtusertable' and `sendmail.cw' ) files. Before running bin/svc_acct_sm.import, you need <a href="../browse/part_svc.cgi">services</a> as follows:
+ <ul>
+ <li>Domain (table svc_acct)
+ <li>Mail alias (table svc_acct_sm)
+ </ul>
+-->
+ <li><a name="cust_main">Importing customer data</a>
+ <ul>
+ <li>Manually
+ <ul>
+ <li>Add a <a href="../edit/cust_main.cgi">new customer</a>
+ <li>Add one or more packages for this customer
+ <li>Enter a package by clicking on the package number
+ <li>Pick the `Link to existing' option
+ </ul>
+ <li>Batch - You will need to write a script to import your particular legacy data. You can use eg/TEMPLATE_cust_main.import as a starting point.
+ </ul>
+</ul>
+</body>
+
diff --git a/httemplate/docs/license.html b/httemplate/docs/license.html
new file mode 100644
index 000000000..54537307e
--- /dev/null
+++ b/httemplate/docs/license.html
@@ -0,0 +1,116 @@
+<% include('/elements/header-popup.html', 'Freeside') %>
+<CENTER>
+<IMG SRC="<%$fsurl%>images/small-logo.png" BORDER=0"><BR>
+<H3>version <% $FS::VERSION %></H3>
+</CENTER>
+
+<P>
+
+Copyright &copy; 2005-2008 Freeside Internet Services, Inc.<BR>
+Copyright &copy; 2000-2005 Ivan Kohler<BR>
+Copyright &copy; 1999 Silicon Interactive Software Design<BR>
+All rights reserved<BR>
+
+<P>
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU <B>Affero</B> General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or (at
+ your option) any later version.
+
+<P>
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+<P>
+ You should have received a copy of the GNU Affero General Public
+ License along with this program, in the file `<A HREF="AGPL.html" TARGET="_blank">AGPL</A>'; if not,
+ see &lt;<A HREF="http://www.fsf.org/licensing/licenses/agpl-3.0.html" TARGET="_blank"">http://www.fsf.org/licensing/licenses/agpl-3.0.html</a>&gt;.
+
+<P>
+ At your option, you may also redistribute and/or modify the files in the
+ fs_selfservice/ directory (but not the rest of the software) under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+<P>
+ At your option, you may also redistribute and/or modify the
+ fs_selfservice/php/freeside.class.php file (but not the rest of the
+ software) under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+<!--entire other packages-->
+
+<P>
+Contains "Request Tracker" <http://www.bestpractical.com/rt/> and
+"RTx::Extension::ActivityReports" from Best Practical Solutions, licensed under
+the terms of the GNU GPL, version two. Best Practical Solutions considers the
+Request Tracker software in this case to be "merely aggregated" with Freeside,
+and not a "combined work", and as such Request Tracker is distributed only
+under the original GPLv2 license.
+
+<!--important widgets or other "whole" bits-->
+
+<P>
+Latex invoice template based on a template from eBills
+<http://ebills.sourceforge.net/> by Mark Asplen-Taylor <mark@asplen.co.uk>,
+licensed under the terms fo the GNU GPL.
+
+<P>
+Contains "JS Calendar" <http://dynarch.com/mishoo/calendar.epl>
+by Mihai Bazon <mishoo@infoiasi.ro> licensed under the terms of the GNU LGPL.
+
+<P>
+Contains FCKeditor by Frederico Caldeira Knabben, licensed under the terms of
+the GNU GPL.
+
+<P>
+Contains XMenu <http://webfx.eae.net/dhtml/xmenu/xmenu.html>
+by Erik Arvidsson, licensed under the terms of the GNU GPL.
+
+<!--RT add-ons-->
+
+<P>
+Contains "RTx::Statistics Package"
+<http://wiki.bestpractical.com/view/RT3StatisticsPackage> from Kelly Hickel
+<kfh@mqsoftware.com>, licensed under the same terms as Perl (GPL/Artistic).
+
+<P>
+Contains "RTx::WebCronTool" <http://search.cpan.org/dist/RTx-WebCronTool/> from
+Audrey Tang, licensed under the same terms as Perl (GPL/Artistic).
+
+<!--libraries-->
+
+<P>
+Contains the QLIB JavaScript library <http://qlib.quazzle.com/> by
+Quazzle.com, Serge Dolgov, licensed under the terms of the GNU GPL.
+
+<P>
+Contains the overlibmws DHTML Popup Library <http://www.macridesweb.com/oltest/>
+by Foteos Macrides (derived from overLIB <http://www.bosrup.com/web/overlib/>
+by Erik Bosrup), licensed under the terms of the Artistic license
+<http://www.macridesweb.com/oltest/license.html>.
+
+<P>
+XMLHttpRequest implementation based on the SAJAX toolkit, licensed under the
+terms of the BSD license.<BR>
+&copy; 2005 modernmethod, inc<BR>
+Perl backend version &copy; 2005 Nathan Schmidt
+
+<!-- artwork -->
+
+<P>
+Contains public domain artwork from openclipart.org by mimooh and other
+authors.
+
+<P>
+Contains icons from
+<A HREF="http://famfamfam.com/" TARGET="_blank">famfamfam.com</A>
+by Mark James, licensed under the terms of the Creative Commons Attribution
+2.5 License.
+
+</BODY>
+</HTML>
diff --git a/httemplate/docs/man/FS/part_export/.cvs_is_on_crack b/httemplate/docs/man/FS/part_export/.cvs_is_on_crack
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/httemplate/docs/man/FS/part_export/.cvs_is_on_crack
diff --git a/httemplate/docs/overview-new.dia b/httemplate/docs/overview-new.dia
new file mode 100644
index 000000000..d9989a359
--- /dev/null
+++ b/httemplate/docs/overview-new.dia
Binary files differ
diff --git a/httemplate/docs/overview-new.png b/httemplate/docs/overview-new.png
new file mode 100644
index 000000000..bf815463b
--- /dev/null
+++ b/httemplate/docs/overview-new.png
Binary files differ
diff --git a/httemplate/docs/overview.dia b/httemplate/docs/overview.dia
new file mode 100644
index 000000000..a0e34c30e
--- /dev/null
+++ b/httemplate/docs/overview.dia
Binary files differ
diff --git a/httemplate/docs/overview.png b/httemplate/docs/overview.png
new file mode 100644
index 000000000..bf2dbc26c
--- /dev/null
+++ b/httemplate/docs/overview.png
Binary files differ
diff --git a/httemplate/docs/passwd.html b/httemplate/docs/passwd.html
new file mode 100755
index 000000000..fc1dde956
--- /dev/null
+++ b/httemplate/docs/passwd.html
@@ -0,0 +1,23 @@
+<head>
+ <title>fs_passwd</title>
+</head>
+<body>
+ <h1>fs_passwd</h1>
+You may use fs_passwd/fs_passwd as a "passwd", "chfn" and "chsh" replacement on your shell machine(s) to cause password, gecos and shell changes to update your freeside machine. You can also use the fs_passwd/fs_passwd.html and fs_passwd/fs_passwd.cgi to run a public password change CGI on a public web server. This can pose a security risk if not configured correctly. <b>Do not use this feature unless you understand what you are doing!</b>
+<br><br>Currently it is assumed that the the crypt(3) function in the C library is the same on the Freeside machine as on the target machine.
+<ul>
+ <li>Create a freeside account on the shell or web machine(s).
+ <li>Setup SSH keys:
+ <ul>
+ <li>As the freeside user (on your freeside machine), generate an authentication key using <a href="http://www.tac.eu.org/cgi-bin/man-cgi?ssh-keygen+1">ssh-keygen</a>. Since this is for unattended operation, use a blank passphrase.
+ <li>Append the newly-created <code>identity.pub</code> file to <code>~freeside
+/.ssh/authorized_keys</code> on the shell or web machine(s).
+ <li>Some new SSH v2 implementation accept v2 style keys only. Use the <code>-t</code> option to <a href="http://www.tac.eu.org/cgi-bin/man-cgi?ssh-keygen+1">ssh-keygen</a>, and append the created <code>id_dsa.pub</code> or <code>id_rsa.pub</code> to <code>~freeside/.ssh/authorized_keys2</code> on the remote machine(s).
+ </ul>
+ <li>Copy fs_passwd/fs_passwdd to /usr/local/sbin on the shell or web machine(s). (chown freeside, chmod 500)
+ <li>Create /usr/local/freeside on the shell or web machine(s). (chown freeside, chmod 700)
+ <li>Run an iteration of "fs_passwd/fs_passwd_server <i>user</i> shell.machine" as the freeside user for each shell or web machine (this is a daemon process). <i>user</i> refers to a freeside user added by <a href="man/bin/freeside-adduser.html">freeside-adduser</a>.
+ <li>Copy fs_passwd/fs_passwd to /usr/local/bin on the shell machine(s). (chown freeside, chmod 4755). You may link it to passwd, chfn and chsh as well.
+ <li>Copy fs_passwd/fs_passwd.cgi to the cgi-bin directory on your web machine(s). Use <a href="http://www.apache.org/docs/suexec.html">suEXEC</a> or <a href="http://www.perldoc.com/perl5.6.1/pod/perlsec.html">suidperl</a> to run fs_passwd.cgi as the freeside user.
+</ul>
+</body>
diff --git a/httemplate/docs/schema.dia b/httemplate/docs/schema.dia
new file mode 100644
index 000000000..e00f59ce1
--- /dev/null
+++ b/httemplate/docs/schema.dia
Binary files differ
diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html
new file mode 100644
index 000000000..cd4914a6c
--- /dev/null
+++ b/httemplate/docs/schema.html
@@ -0,0 +1,533 @@
+
+ <title>Schema reference</title>
+</head>
+<body>
+ <h1>Schema reference</h1>
+ Schema diagram (1.4.1): <a href="schema.png">as a giant .png</a> or <a href="schema.dia">dia source</a> (<a href="http://www.lysator.liu.se/~alla/dia/">dia homepage</a>).
+ <ul>
+ <li><a name="agent" href="man/FS/agent.html">agent</a> - Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their agent type).
+ <ul>
+ <li>agentnum - primary key
+ <li>agent - name of this agent
+ <li>typenum - <a href="#agent_type">agent type</a>
+ <li>prog - (unimplemented)
+ <li>freq - (unimplemented)
+ <li>disabled - Disabled flag, empty or 'Y'
+ <li>username - Username for the Agent interface
+ <li>_password - Password for the Agent interface
+ </ul>
+ <li><a name="agent_type" href="man/FS/agent_type.html">agent_type</a> - Agent types define groups of packages that you can then assign to particular agents.
+ <ul>
+ <li>typenum - primary key
+ <li>atype - name of this agent type
+ </ul>
+ <li><a name="cust_bill" href="man/FS/cust_bill.html">cust_bill</a> - Invoices. Declarations that a customer owes you money. The specific charges are itemized in <a href="#cust_bill_pkg">cust_bill_pkg</a>.
+ <ul>
+ <li>billpkgnum - primary_key
+ <li>invnum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>_date
+ <li>charged - amount of this invoice
+ <li>printed - how many times this invoice has been printed automatically
+ <li>closed - books closed flag, empty or `Y'
+ </ul>
+ <li><a name="cust_bill_event" href="man/FS/cust_bill_event.html">cust_bill_event</a> - Invoice event history
+ <ul>
+ <li>eventnum - primary key
+ <li>invnum - <a href="#cust_bill">invoice</a>
+ <li>eventpart - <a href="#part_bill_event">event definition</a>
+ <li>_date
+ <li>status
+ <li>statustext
+ </ul>
+ <li><a name="part_bill_event" href="man/FS/part_bill_event.html">part_bill_event</a> - Invoice event definitions
+ <ul>
+ <li>eventpart - primary key
+ <li>payby - CARD, DCRD, CHEK, DCHK, LECB, BILL, or COMP
+ <li>event - event name
+ <li>eventcode - event action
+ <li>seconds - how long after the invoice date (<a href="#cust_bill">cust_bill</a>._date) events of this type are triggered
+ <li>weight - ordering for events with identical seconds
+ <li>plan - eventcode plan
+ <li>plandata - additional plan data
+ <li>disabled - Disabled flag, empty or `Y'
+ <li>taxclass - Texas tax class flag, empty or "none", "access", or "hosting"
+ </ul>
+ <li><a name="cust_bill_pkg" href="man/FS/cust_bill_pkg.html">cust_bill_pkg</a> - Invoice line items
+ <ul>
+ <li>invnum - (multiple) key
+ <li>pkgnum - <a href="#cust_pkg">package</a> or 0 for the special virtual sales tax package
+ <li>setup - setup fee
+ <li>recur - recurring fee
+ <li>sdate - starting date
+ <li>edate - ending date
+ <li>itemdesc - Line item description (currently used only when pkgnum is 0)
+ </ul>
+ <li><a name="cust_bill_pkg_detail" href="man/FS/cust_bill_pkg_detail.html">cust_bill_pkg_detail</a> - Invoice line items detail
+ <ul>
+ <li>detailnum - primary key
+ <li>pkgnum -
+ <li>invnum -
+ <li>detail - Detail description
+ </ul>
+ <li><a name="cust_credit" href="man/FS/cust_credit.html">cust_credit</a> - Credits. The equivalent of a negative <a href="#cust_bill">cust_bill</a> record.
+ <ul>
+ <li>crednum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>amount - amount credited
+ <li>_date
+ <li>otaker - order taker
+ <li>reason
+ <li>closed - books closed flag, empty or `Y'
+ </ul>
+ <li><a name="cust_credit_bill" href="man/FS/cust_credit_bill.html">cust_credit_bill</a> - Credit invoice application. Links a credit to an invoice.
+ <ul>
+ <li>creditbillnum - primary key
+ <li>crednum - <a href="#cust_credit">credit</a> being applied
+ <li>invnum - <a href="#cust_bill">invoice</a> to which credit is applied
+ <li>amount - amount applied
+ <li>_date
+ </ul>
+ <li><a name="cust_pay_refund" href="man/FS/cust_pay_refund.html">cust_credit_bill</a> - Refund payment application. Links a refund to a payment.
+ <ul>
+ <li>payrefundnum - primary key
+ <li>paynum - <a href="#cust_pay">payment</a>
+ <li>refundnum - <a href="#cust_refund">refund</a>
+ <li>amount - amount applied
+ <li>_date
+ </ul>
+ <li><a name="cust_main" href="man/FS/cust_main.html">cust_main</a> - Customers
+ <ul>
+ <li>custnum - primary key
+ <li>agentnum - <a href="#agent">agent</a>
+ <li>refnum - <a href="#part_referral">referral</a>
+ <li>first - name
+ <li>last - name
+ <li>ss - social security number
+ <li>company
+ <li>address1
+ <li>address2
+ <li>city
+ <li>county
+ <li>state
+ <li>zip
+ <li>country
+ <li>daytime - phone
+ <li>night - phone
+ <li>fax - phone
+ <li><i>ship_first</i>
+ <li><i>ship_last</i>
+ <li><i>ship_company</i>
+ <li><i>ship_address1</i>
+ <li><i>ship_address2</i>
+ <li><i>ship_city</i>
+ <li><i>ship_county</i>
+ <li><i>ship_state</i>
+ <li><i>ship_zip</i>
+ <li><i>ship_country</i>
+ <li><i>ship_daytime</i>
+ <li><i>ship_night</i>
+ <li><i>ship_fax</i>
+ <li>payby - CARD, DCHK, CHEK, DCHK, LECB, BILL, or COMP
+ <li>payinfo - card number, P.O.#, or comp issuer
+ <li>paycvv - Card Verification Value, "CVV2" (also known as CVC2 or CID), the 3 or 4 digit number on the back (or front, for American Express) of the credit card
+ <li>paydate - expiration date
+ <li>payname - billing name (name on card)
+ <li>tax - tax exempt, Y or null
+ <li>otaker - order taker
+ <li>referral_custnum
+ <li>comments
+ </ul>
+ (columns in <i>italics</i> are optional)
+ <li><a name="cust_main_invoice" href="man/FS/cust_main_invoice.html">cust_main_invoice</a> - Invoice destinations for email invoices. Note that a customer can have many email destinations for their invoice (either literal or via svcnum), but only one postal destination.
+ <ul>
+ <li>destnum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>dest - Invoice destination. Freeside supports three types of invoice delivery: send directly to a service defined in Freeside, send to an arbitrary email address, or print the invoice to a printer and have someone send it out via snail mail. Freeside determines which method to use based on the contents of the dest field. If the contents are numeric, a <a href="#svc_acct">svcnum</a> pointing to a valid service is expected in the field. If the contents are a string, a literal email address is expected to be in the field. If the special keyword `POST' is present, the snail mail method is used (which is the default if no cust_main_invoice records exist). Snail mail invoices get their address information from <A name="#cust_main">cust_main</A> and are printed with the printer defined in the configuration files.
+ </ul>
+ <li><a name="cust_main_county" href="man/FS/cust_main_county.html">cust_main_county</a> - Tax rates
+ <ul>
+ <li>taxnum - primary key
+ <li>state
+ <li>county
+ <li>country
+ <li>tax - % rate
+ <li>taxclass
+ <li>exempt_amount
+ <li>taxname - if defined, printed on invoices instead of "Tax"
+ <li>setuptax - if 'Y', this tax does not apply to setup fees
+ <li>recurtax - if 'Y', this tax does not apply to recurring fees
+ </ul>
+ <li><a name="cust_tax_exempt" href="man/FS/cust_tax_exempt.html">cust_tax_exempt</a> - Tax exemption record
+ <ul>
+ <li>exemptnum - primary key
+ <li>taxnum - <a href="#cust_main_county">tax rate</a>
+ <li>year
+ <li>month
+ <li>amount
+ </ul>
+ <li><a name="cust_pay" href="man/FS/cust_pay.html">cust_pay</a> - Payments. Money being transferred from a customer.
+ <ul>
+ <li>paynum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>paid - amount
+ <li>_date
+ <li>payby - CARD, CHEK, LECB, BILL, or COMP
+ <li>payinfo - card number, P.O.#, or comp issuer
+ <li>paybatch - text field for tracking card processor batches
+ <li>closed - books closed flag, empty or `Y'
+ </ul>
+ <li><a name="cust_pay-void" href="man/FS/cust_pay_void.html">cust_pay_void</a> - Voided payments.
+ <ul>
+ <li>paynum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>paid - amount
+ <li>_date
+ <li>payby - CARD, CHEK, LECB, BILL, or COMP
+ <li>payinfo - card number, P.O.#, or comp issuer
+ <li>paybatch - text field for tracking card processor batches
+ <li>closed - books closed flag, empty or `Y'
+ <li>void_date
+ <li>reason
+ <li>otaker - order taker
+ </ul>
+ <li><a name="cust_bill_pay" href="man/FS/cust_bill_pay.html">cust_bill_pay</a> - Applicaton of a payment to a specific invoice.
+ <ul>
+ <li>billpaynum
+ <li>invnum - <a href="#cust_bill">invoice</a>
+ <li>paynum - <a href="#cust_pay">payment</a>
+ <li>amount
+ <li>_date
+ </ul>
+ <li><a name="pay_batch" href="man/FS/pay_batch.html">pay_batch</a> - Pending batch
+ <ul>
+ <li>batchnum
+ <li>status
+ <li>download
+ <li>upload
+ </ul>
+ <li><a name="cust_pay_batch" href="man/FS/cust_pay_batch.html">cust_pay_batch</a> - Pending batch members
+ <ul>
+ <li>paybatchnum
+ <li>batchnum
+ <li>payby - CARD, CHEK, LECB, BILL, or COMP
+ <li>payinfo - account number
+ <li>exp - card expiration
+ <li>amount
+ <li>invnum - <a href="#cust_bill">invoice</a>
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>payname - name on card
+ <li>first - name
+ <li>last - name
+ <li>address1
+ <li>address2
+ <li>city
+ <li>state
+ <li>zip
+ <li>country
+ <li>status
+ </ul>
+ <li><a name="cust_pkg" href="man/FS/cust_pkg.html">cust_pkg</a> - Customer billing items
+ <ul>
+ <li>pkgnum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>pkgpart - <a href="#part_pkg">Package definition</a>
+ <li>setup - date
+ <li>bill - next bill date
+ <li>last_bill - last bill date
+ <li>susp - (past) suspension date
+ <li>expire - (future) cancellation date
+ <li>cancel - (past) cancellation date
+ <li>otaker - order taker
+ <li>manual_flag - If this field is set to 1, disables the automatic unsuspensiond of this package when using the <a href="config.html#unsuspendauto">unsuspendauto</a> config file.
+ </ul>
+ <li><a name="cust_refund" href="man/FS/cust_refund.html">cust_refund</a> - Refunds. The transfer of money to a customer; equivalent to a negative <a href="#cust_pay">cust_pay</a> record.
+ <ul>
+ <li>refundnum - primary key
+ <li>custnum - <a href="#cust_main">customer</a>
+ <li>refund - amount
+ <li>_date
+ <li>payby - CARD, CHEK, LECB, BILL or COMP
+ <li>payinfo - card number, P.O.#, or comp issuer
+ <li>otaker - order taker
+ <li>closed - books closed flag, empty or `Y'
+ </ul>
+ <li><a name="cust_credit_refund" href="man/FS/cust_credit_refund.html">cust_credit_refund</a> - Applicaton of a refund to a specific credit.
+ <ul>
+ <li>creditrefundnum - primary key
+ <li>crednum - <a href="#cust_credit">credit</a>
+ <li>refundnum - <a href="#cust_refund">refund</a>
+ <li>amount
+ <li>_date
+ </ul>
+ <li><a name="cust_svc" href="man/FS/cust_svc.html">cust_svc</a> - Customer services
+ <ul>
+ <li>svcnum - primary key
+ <li>pkgnum - <a href="#cust_pkg">package</a>
+ <li>svcpart - <a href="#part_svc">Service definition</a>
+ </ul>
+ <li><a name="nas" href="man/FS/nas.html">nas</a> - Network Access Server (terminal server)
+ <ul>
+ <li>nasnum - primary key
+ <li>nas - NAS name
+ <li>nasip - NAS ip address
+ <li>nasfqdn - NAS fully-qualified domain name
+ <li>last - timestamp indicating the last instant the NAS was in a known state (used by the session monitoring).
+ </ul>
+ <li><a name="part_pkg" href="man/FS/part_pkg.html">part_pkg</a> - Package definitions
+ <ul>
+ <li>pkgpart - primary key
+ <li>pkg - package name
+ <li>comment - non-customer visable package comment
+ <li>promo_code - promotional code
+ <li><i>deprecated</i> setup - setup fee expression
+ <li>freq - recurring frequency (months)
+ <li><i>deprecated</i> recur - recurring fee expression
+ <li>setuptax - Setup fee tax exempt flag, empty or `Y'
+ <li>recurtax - Recurring fee tax exempt flag, empty or `Y'
+ <li>plan - price plan
+ <li><i>deprecated</i> plandata - additional price plan data
+ <li>disabled - Disabled flag, empty or `Y'
+ </ul>
+ <li><a name="part_pkg_option" href="man/FS/part_pkg_option.html">part_pkg_option</a> - Package definition options
+ <ul>
+ <li>optionnum - primary key
+ <li>pkgpart - <a href="#part_pkg">Package definition</a>
+ <li>optionname - option name
+ <li>optionvalue - option value
+ </ul>
+ <li><a name="reg_code" href="man/FS/reg_code.html">reg_code</A> - One-time registration codes
+ <ul>
+ <li>codenum - primary key
+ <li>code
+ <li>agentnum - <a href="#agent">Agent</a>
+ </ul>
+ <li><a name="reg_code_pkg" href="man/FS/reg_code_pkg.html">reg_code_pkg</A> - Registration code link to package definitions
+ <ul>
+ <li>codepkgnum - primary key
+ <li>codenum - <a href="#reg_code">Registration code</a>
+ <li>pkgpart - <a href="#part_pkg">Package definition</a>
+ </ul>
+ <li><a name="part_referral" href="man/FS/part_referral.html">part_referral</a> - Referral listing
+ <ul>
+ <li>refnum - primary key
+ <li>referral - referral
+ </ul>
+ <li><a name="part_svc" href="man/FS/part_svc.html">part_svc</a> - Service definitions
+ <ul>
+ <li>svcpart - primary key
+ <li>svc - name of this service
+ <li>svcdb - table used for this service: svc_acct, svc_forward, svc_domain, svc_charge or svc_wo
+ <li>disabled - Disabled flag, empty or `Y'
+<!-- <li><i>table</i>__<i>field</i> - Default or fixed value for <i>field</i> in <i>table</i>
+ <li><i>table</i>__<i>field</i>_flag - null, D or F
+-->
+ </ul>
+ <li><a name="part_svc_column" href="man/FS/part_svc_column.html">part_svc_column</a>
+ <ul>
+ <li>columnnum - primary key
+ <li>svcpart - <a href="#part_svc">Service definition</a>
+ <li>columnname - column name in part_svc.svcdb table
+ <li>columnvalue - default or fixed value for the column
+ <li>columnflag - null, D or F
+ </ul>
+ <li><a name="pkg_svc" href="man/FS/pkg_svc.html">pkg_svc</a>
+ <ul>
+ <li>pkgsvcnum - primary key
+ <li>pkgpart - <a href="#part_pkg">Package definition</a>
+ <li>svcpart - <a href="#part_svc">Service definition</a>
+ <li>quantity - quantity of this service that this package includes
+ <li>primary_svc - blank or Y: primary service
+ </ul>
+ <li><a name="export_svc" href="man/FS/export_svc.html">export_svc</a>
+ <ul>
+ <li>exportsvcnum - primary key
+ <li>svcpart - <a href="#part_svc">Service definition</a>
+ <li>exportnum - <a href="#exportnum">Export</a>
+ </ul>
+ <li><a name="part_export" href="man/FS/part_export.html">part_export</a> - Export to external provisioning
+ <ul>
+ <li>exportnum - primary key
+ <li>machine - Machine name
+ <li>exporttype - Export type
+ <li>nodomain - blank or Y: usernames are exported to this service with no domain
+ </ul>
+ <li><a name="part_export_option" href="man/FS/part_export_option.html">part_export_option</a> - provisioning options
+ <ul>
+ <li>optionnum - primary key
+ <li>exportnum - <a href="#part_export">Export</a>
+ <li>optionname - option name
+ <li>optionvalue - option value
+ </ul>
+ <li><a name="port" href="man/FS/port.html">port</a> - individual port on a <a href="#nas">nas</a>
+ <ul>
+ <li>portnum - primary key
+ <li>ip - IP address of this port
+ <li>nasport - port number on the NAS
+ <li>nasnum - <a href="#nas">NAS</a>
+ </ul>
+ <li><a name="prepay_credit" href="man/FS/prepay_credit.html">prepay_credit</a> - prepaid cards
+ <ul>
+ <li>prepaynum - primary key
+ <li>identifier - text or numeric string of prepaid card
+ <li>amount - amount of prepayment
+ <li>seconds - prepaid time instead of (or in addition to) monetary value
+ <li>agentnum - optional agent assignment for prepaid cards
+ </ul>
+ <li><a name="session" href="man/FS/session.html">session</a>
+ <ul>
+ <li>sessionnum - primary key
+ <li>portnum - <a href="#port">Port</a>
+ <li>svcnum - <a href="#svc_acct">Account</a>
+ <li>login - timestamp indicating the beginning of this user session.
+ <li>logout - timestamp indicating the end of this user session. May be null, which indicates a currently open session.
+ </ul>
+
+ <li><a name="svc_acct" href="man/FS/svc_acct.html">svc_acct</a> - Accounts
+ <ul>
+ <li>svcnum - <a href="#cust_svc">primary key</a>
+ <li>username
+ <li>_password
+ <li>sec_phrase - security phrase
+ <li>popnum - <a href="#svc_acct_pop">Point of Presence</a>
+ <li>uid
+ <li>gid
+ <li>finger - GECOS
+ <li>dir
+ <li>shell
+ <li>quota - (unimplementd)
+ <li>slipip - IP address
+ <li>seconds
+ <li>domsvc
+ <li>radius_<i>Radius_Reply_Attribute</i> - Radius-Reply-Attribute
+ <li>rc_<i>Radius_Check_Attribute</i> - Radius-Check-Attribute
+ </ul>
+ <li><a name="svc_acct_pop" href="man/FS/svc_acct_pop.html">svc_acct_pop</a> - Points of Presence
+ <ul>
+ <li>popnum - primary key
+ <li>city
+ <li>state
+ <li>ac - area code
+ <li>exch - exchange
+ <li>loc - rest of number
+ </ul>
+ <li><a name="part_pop_local" href="man/FS/part_pop_local.html">part_pop_local</a> - Local calling areas
+ <ul>
+ <li>localnum - primary key
+ <li>popnum - primary key
+ <li>city
+ <li>state
+ <li>npa - area code
+ <li>nxx - exchange
+ </ul>
+ <li><a name="svc_domain" href="man/FS/svc_domain.html">svc_domain</a> - Domains
+ <ul>
+ <li>svcnum - <a href="#cust_svc">primary key</a>
+ <li>domain
+ </ul>
+ <li><a name="svc_forward" href="man/FS/svc_forward.html">svc_forward</a> - Mail forwarding aliases
+ <ul>
+ <li>svcnum - <a href="#cust_svc">primary key</a>
+ <li>srcsvc - <a href="#svc_acct">svcnum of the source of this forward</a>
+ <li>src - literal source (username or full email address)
+ <li>dstsvc - <a href="#svc_acct">svcnum of the destination of this forward</a>
+ <li>dst - literal destination (username or full email address)
+ </ul>
+ <li><a name="domain_record" href="man/FS/domain_record.html">domain_record</a> - Domain zone detail
+ <ul>
+ <li>recnum - primary key
+ <li>svcnum - <a href="#svc_domain">Domain</a> (by svcnum)
+ <li>reczone - zone for this line
+ <li>recaf - address family, usually <b>IN</b>
+ <li>rectype - type for this record (<b>A</b>, <b>MX</b>, etc.)
+ <li>recdata - data for this record
+ </ul>
+ <li><a name="svc_www" href="man/FS/svc_www.html">svc_www</a>
+ <ul>
+ <li>svcnum - <a href="#cust-svc">primary key</a>
+ <li>recnum - <a href="#domain_record">host</a>
+ <li>usersvc - <a href="#svc_acct">account</a>
+ </ul>
+ <li><a name="type_pkgs" href="man/FS/type_pkgs.html">type_pkgs</a>
+ <ul>
+ <li>typepkgnum - primary key
+ <li>typenum - <a href="#agent_type">agent type</a>
+ <li>pkgpart - <a href="#part_pkg">Package definition</a>
+ </ul>
+ <li><a name="queue" href="man/FS/queue.html">queue</a> - job queue
+ <ul>
+ <li>jobnum - primary key
+ <li>job
+ <li>_date
+ <li>status
+ <li>statustext
+ <li>svcnum
+ </ul>
+ <li><a name="queue_arg" href="man/FS/queue_arg.html">queue_arg</a> - job arguments
+ <ul>
+ <li>argnum - primary key
+ <li>jobnum - <a href="#queue">job</a>
+ <li>arg - argument
+ </ul>
+ <li><a name="queue_depend" href="man/FS/queue_depend.html">queue_depend</a> - job dependancies
+ <ul>
+ <li>dependnum - primary key
+ <li>jobnum - source jobnum
+ <li>depend_jobnum - dependancy jobnum
+ </ul>
+ <li><a name="radius_usergroup" href="man/FS/radius_usergroup.html">radius_usergroup</a> - Link users to RADIUS groups.
+ <ul>
+ <li>usergroupnum - primary key
+ <li>svcnum - <a href="#svc_acct">account</a>
+ <li>groupname
+ </ul>
+ <li><a name="rate" href="man/FS/rate.html">rate</a> - Call rate plans
+ <ul>
+ <li>ratenum - primary key
+ <li>ratename
+ </ul>
+ <li><a name="rate_detail" href="man/FS/rate_detail.html">rate_detail</a> - Call rate detail
+ <ul>
+ <li>ratedetailnum - primary key
+ <li>ratenum - <a href="#rate">rate plan</a>
+ <li>orig_regionnum - call origination <a href="#rate_region">region</a>
+ <li>dest_regionnum - call destination <a href="#rate_region">region</a>
+ <li>min_included - included minutes
+ <li>min_charge - charge per minute
+ <li>sec_granularity - granularity in seconds, i.e. 6 or 60
+ </ul>
+ <li><a name="rate_region" href="man/FS/rate_region.html">rate_region</a> - Call rate region
+ <ul>
+ <li>regionnum - primary key
+ <li>regionname
+ </ul>
+ <li><a name="rate_prefix" href="man/FS/rate_prefix.html">rate_prefix</a> - Call rate prefix
+ <ul>
+ <li>prefixnum - primary key
+ <li>regionnum - <a href="#rate_region">rate region</a>
+ <li>countrycode
+ <li>npa
+ <li>nxx
+ </ul>
+ <li><a name="msgcat" href="man/FS/msgcat.html">msgcat</a> - i18n message catalog
+ <ul>
+ <li>msgnum - primary key
+ <li>msgcode - message code
+ <li>locale - locale
+ <li>msg - Message text
+ </ul>
+ <li><a name="clientapi_session" href="man/FS/clientapi_session.html">clientapi_session</a> - ClientAPI session store
+ <ul>
+ <li>sessionnum - primary key
+ <li>sessionid - session ID
+ <li>namespace - session namespace
+ </ul>
+ <li><a name="clientapi_session_field" href="man/FS/clientapi_session_field.html">clientapi_session_field</a> - Client API session store data
+ <ul>
+ <li>fieldnum - primary key
+ <li>sessionnum - <a href="#session">session</a>
+ <li>fieldname
+ <li>fieldvalue
+ </ul>
+ </ul>
+</body>
diff --git a/httemplate/docs/schema.png b/httemplate/docs/schema.png
new file mode 100644
index 000000000..d0392e76f
--- /dev/null
+++ b/httemplate/docs/schema.png
Binary files differ
diff --git a/httemplate/docs/session.html b/httemplate/docs/session.html
new file mode 100644
index 000000000..72e16424e
--- /dev/null
+++ b/httemplate/docs/session.html
@@ -0,0 +1,59 @@
+<head>
+ <title>Session monitor</title>
+</head>
+<body>
+<h1>Session monitor</h1>
+<h2>Installation</h2>
+For security reasons, the client portion of the session montior may run on one
+or more external public machine(s). On these machines, install:
+<ul>
+ <li><a href="http://www.perl.com/CPAN/doc/relinfo/INSTALL.html">Perl</a> (at l
+east 5.004_05 for the 5.004 series or 5.005_03 for the 5.005 series. Don't enable experimental features like threads or the PerlIO abstraction layer.)
+ <li><a href="man/FS/SessionClient.html">FS::SessionClient</a> (copy the fs_session/FS-SessionClient directory to the external machine, then: perl Makefile.PL; make; make install)
+</ul>
+Then:
+<ul>
+ <li>Add the user `freeside' to the the external machine.
+ <li>Create the /usr/local/freeside directory on the external machine (owned by the freeside user).
+ <li>touch /usr/local/freeside/fs_sessiond_socket; chown freeside /usr/local/freeside/fs_sessiond_socket; chmod 600 /usr/local/freeside/fs_sessiond_socket
+ <li>Append the identity.pub from the freeside user on your freeside machine to the authorized_keys file of the newly created freeside user on the external machine(s).
+ <li>Run <pre>fs_session_server <i>user</i> <i>machine</i></pre> on the Freeside machine.
+ <ul>
+ <li><i>user</i> is a user from the mapsecrets file.
+ <li><i>machine</i> is the name of the external machine.
+ </ul>
+</ul>
+<h2>Usage</h2>
+<ul>
+ <li>Web
+ <ul>
+ <li>Copy FS-SessionClient/cgi/login.cgi and logout.cgi to your web
+ server's document space.
+ <li>Use <a href="http://www.apache.org/docs/suexec.html">suEXEC</a> or <a href="http://www.perl.com/CPAN-local/doc/manual/html/pod/perlsec.html#Security_Bugs">setuid</a> (see <a href="install.html">install.html</a> for details) to run login.cgi and logout.cgi as the freeside user.
+ </ul>
+ <li>Command-line
+ <br><pre>freeside-login username ( portnum | ip | nasnum nasport )
+freeside-logout username ( portnum | ip | nasnum nasport )</pre>
+ <ul>
+ <li><i>username</i> is a customer username from the svc_acct table
+ <li><i>portnum</i>, <i>ip</i> or <i>nasport</i> and <i>nasnum</i> uniquely identify a port in the <a href="schema.html#port">port</a> database table.
+ </ul>
+ <li>RADIUS - One of:
+ <ul>
+ <li>Run the <b>freeside-sqlradius-radacctd</b> daemon to import radacct
+ records from all configured sqlradius exports:
+ <tt>freeside-sqlradius-radacctd username</tt>
+ <li>Configure your RADIUS server's login and logout callbacks to use the command-line <tt>freeside-login</tt> and <tt>freeside-logout</tt> utilites.
+ <li> <i>(incomplete)</i>Use the <b>fs_radlog/fs_radlogd</b> tool to
+ import records from a text radacct file.
+ </ul>
+</ul>
+<h2>Callbacks</h2>
+<ul>
+ <li>Sesstion start - The command(s) specified in the <a href="config.html#session-start">session-start</a> configuration file are executed on the Freeside machine. The contents of the file are treated as a double-quoted perl string, with the following variables available: <code>$ip</code>, <code>$nasip</code> and <code>$nasfqdn</code>, which are the IP address of the starting session, and the IP address and fully-qualified domain name of the NAS this session is on.
+ <li>Session end - The command(s) specified in the <a href="config.html#session-stop">session-stop</a> configuration file are executed on the Freeside machine. The contents of the file are treated as a double-quoted perl string, with the following variables available: <code>$ip</code>, <code>$nasip</code> and <code>$nasfqdn</code>, which are the IP address of the starting session, and the IP address and fully-qualified domain name of the NAS this session is on.
+</ul>
+<h2>Dropping expired users</h2>
+Run <pre>bin/freeside-session-kill username</pre> periodically from cron.
+</body>
+</html>
diff --git a/httemplate/docs/signup.html b/httemplate/docs/signup.html
new file mode 100644
index 000000000..97d7aa794
--- /dev/null
+++ b/httemplate/docs/signup.html
@@ -0,0 +1,54 @@
+<head>
+ <title>Signup server</title>
+</head>
+<body>
+ <h1>Signup server</h1>
+For security reasons, the signup server should run on an external public
+webserver. On this machine, install:
+<ul>
+ <li>A web server, such as <a href="http://www.apache-ssl.org">Apache-SSL</a> or <a href="http://www.apache.org">Apache</a>
+ <li><a href="ftp://ftp.cs.hut.fi/pub/ssh/">SSH</a>
+ <li><a href="http://www.perl.com/CPAN/doc/relinfo/INSTALL.html">Perl</a> (at least 5.004_05 for the 5.004 series or 5.005_03 for the 5.005 series. Don't enable experimental features like threads or the PerlIO abstraction layer.)
+ <li><a href="http://search.cpan.org/search?dist=Text-Template">Text::Template</a>
+ <li><a href="http://search.cpan.org/search?dist=Storable">Storable</a>
+ <li><a href="http://search.cpan.org/search?dist=Business-CreditCard">Business-CreditCard</a>
+ <li><a href="http://search.cpan.org/search?dist=HTTP-BrowserDetect">HTTP::BrowserDetect</a>
+
+ <li><a href="man/FS/SignupClient.html">FS::SignupClient</a> (copy the fs_signup/FS-SignupClient directory to the external machine, then: perl Makefile.PL; make; make install)
+</ul>
+Then:
+<ul>
+ <li>Add the user `freeside' to the the external machine.
+ <li>Copy or symlink fs_signup/FS-SignupClient/cgi/signup.cgi into the web server's document space.
+ <li>When linking to signup.cgi, you can include a referring custnum in the URL as follows: <code>http://public.web.server/path/signup.cgi?ref=1542</code>
+ <li>Enable CGI execution for files with the `.cgi' extension. (with <a href="http://www.apache.org/docs/mod/mod_mime.html#addhandler">Apache</a>)
+ <li>Create the /usr/local/freeside directory on the external machine (owned by the freeside user).
+ <li>touch /usr/local/freeside/fs_signupd_socket; chown freeside /usr/local/freeside/fs_signupd_socket; chmod 600 /usr/local/freeside/fs_signupd_socket
+ <li>Use <a href="http://www.apache.org/docs/suexec.html">suEXEC</a> or <a href="http://www.perl.com/CPAN-local/doc/manual/html/pod/perlsec.html#Security_Bugs">setuid</a> (see <a href="install.html">install.html</a> for details) to run signup.cgi as the freeside user.
+ <li>Append the identity.pub from the freeside user on your freeside machine to the authorized_keys file of the newly created freeside user on the external machine(s).
+ <li>Run <pre>fs_signup_server <i>user</i> <i>machine</i> <i>agentnum</i> <i>refnum</i></pre> on the Freeside machine.
+ <ul>
+ <li><i>user</i> is a user from the mapsecrets file.
+ <li><i>machine</i> is the name of the external machine.
+ <li><i>agentnum</i> and <i>refnum</i> are the <a href="schema.html#agent">agent</a> and <a href="schema.html#part_referral">referral</a>, respectively, to use for customers who sign up via this signup server.
+ </ul>
+</ul>
+Optional:
+<ul>
+ <li>If you create a <b>/usr/local/freeside/ieak.template</b> file on the external machine, it will be sent to IE users with MIME type <i>application/x-Internet-signup</i>. This file will be processed with <a href="http://search.cpan.org/doc/MJD/Text-Template-1.23/Template.pm">Text::Template</a> with the variables listed below available.
+ (an example file is included as <b>fs_signup/ieak.template</b>) See the section on <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/INS.HTM">internet settings files</a> in the <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/toc.asp">IEAK documentation</a> for more information.
+ <li>If you create a <b>/usr/local/freeside/success.html</b> file on the external machine, it will be used as the success HTML page. Although template substiutions are available, a regular HTML file will work fine here, unlike signup.html. An example file is included as <b>fs_signup/FS-SignupClient/cgi/success.html</b>
+ <li>Variable substitutions available in <b>ieak.template</b>, <b>cck.template</b> and <b>success.html</b>:
+ <ul>
+ <li>$ac - area code of selected POP
+ <li>$exch - exchange of selected POP
+ <li>$loc - local part of selected POP
+ <li>$username
+ <li>$password
+ <li>$email_name - first and last name
+ <li>$pkg - package name
+ </ul>
+ <li>If you create a <b>/usr/local/freeside/signup.html</b> file on the external machine, it will be used as a template for the form HTML. This requires the template to be constructed appropriately; probably best to start with the example file included as <b>fs_signup/FS-SignupClient/cgi/signup.html</b>.
+ <li>If there are any entries in the <i>prepay_credit</i> table, a user can enter a string matching the <b>identifier</i> column to receive the credit specified in the <b>amount</b> column, and/or the time specified in the <b>seconds</b> column (for use with the <a href="session.html">session monitor</a>), after which that <b>identifier</b> is no longer valid. This can be used to implement pre-paid "calling card" type signups. The <i>bin/generate-prepay</i> script can be used to populate the <i>prepay_credit</i> table.
+</ul>
+</body>
diff --git a/httemplate/docs/ssh.html b/httemplate/docs/ssh.html
new file mode 100755
index 000000000..d2c501e35
--- /dev/null
+++ b/httemplate/docs/ssh.html
@@ -0,0 +1,16 @@
+<head>
+ <title>Unattended SSH</title>
+</head>
+<body>
+ <h1>Unattended SSH</h1>
+ <br><a name=ssh>Unattended remote login</a> - Freeside can login to remote machines unattended using SSH. This can pose a security risk if not configured correctly, and will allow an intruder who breaks into your freeside machine full access to your remote machines. <b>Do not use this feature unless you understand what you are doing!</b>
+ <ul>
+ <li>As the freeside user (on your freeside machine), generate an authentication key using <a href="http://www.tac.eu.org/cgi-bin/man-cgi?ssh-keygen+1">ssh-keygen</a>. Since this is for unattended operation, use a blank passphrase.
+ <li>Append the newly-created <code>identity.pub</code> file to <code>~root/.ssh/authorized_keys</code> (or the appopriate <code>~username/.ssh/authorized_keys</code>) on the remote machine(s).
+ <li>Some new SSH v2 implementation accept v2 style keys only. Use the <code>-t</code> option to <a href="http://www.tac.eu.org/cgi-bin/man-cgi?ssh-keygen+1">ssh-keygen</a>, and append the created <code>id_dsa.pub</code> or <code>id_rsa.pub</code> to <code>~root/.ssh/authorized_keys2</code> (or the appopriate <code>~username/.ssh/authorized_keys</code>) on the remote machine(s).
+ <li>You may need to set <code>PermitRootLogin without-password</code> (meaning with keys only) in your <code>sshd_config</code> file on the remote machine(s).
+ <li>You may want to set <code>ForwardX11 = no</code> in <code>~root/.ssh/config</code> to prevent spurious errors if your distribution turns on X11 forwarding by default.
+ </ul>
+
+</body>
+
diff --git a/httemplate/edit/REAL_cust_pkg.cgi b/httemplate/edit/REAL_cust_pkg.cgi
new file mode 100755
index 000000000..b2c89c32c
--- /dev/null
+++ b/httemplate/edit/REAL_cust_pkg.cgi
@@ -0,0 +1,186 @@
+<% include("/elements/header.html",'Customer package - Edit dates') %>
+
+%#, menubar(
+%# "View this customer (#$custnum)" => popurl(2). "view/cust_main.cgi?$custnum",
+%#));
+
+<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+
+<FORM NAME="formname" ACTION="process/REAL_cust_pkg.cgi" METHOD="POST">
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+% # raw error from below
+% if ( $error ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error %></FONT>
+% }
+% #or, regular error handler
+<% include('/elements/error.html') %>
+
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TD ALIGN="right">Package number</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_pkg->pkgnum %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Package</TD>
+ <TD BGCOLOR="#ffffff"><% $part_pkg->pkg %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Comment</TD>
+ <TD BGCOLOR="#ffffff"><% $part_pkg->comment %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Order taker</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_pkg->otaker %></TD>
+ </TR>
+
+ <& .row_edit, cust_pkg=>$cust_pkg, column=>'setup', label=>'Setup' &>
+ <& .row_edit, cust_pkg=>$cust_pkg, column=>'last_bill', label=>$last_bill_or_renewed &>
+ <& .row_edit, cust_pkg=>$cust_pkg, column=>'bill', label=>$next_bill_or_prepaid_until &>
+ <& .row_display, cust_pkg=>$cust_pkg, column=>'adjourn', label=>'Adjournment', note=>'(will <b>suspend</b> this package when the date is reached)' &>
+ <& .row_display, cust_pkg=>$cust_pkg, column=>'susp', label=>'Suspension' &>
+
+ <& .row_display, cust_pkg=>$cust_pkg, column=>'expire', label=>'Expiration', note=>'(will <b>cancel</b> this package when the date is reached)' &>
+ <& .row_display, cust_pkg=>$cust_pkg, column=>'cancel', label=>'Cancellation' &>
+
+<%def .row_edit>
+<%args>
+ $cust_pkg
+ $column
+ $label
+ $note => ''
+</%args>
+% my $value = $cust_pkg->get($column);
+% $value = $value ? time2str($format, $value) : "";
+
+ <TR>
+ <TD ALIGN="right"><% $label %> date</TD>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "<% $column %>"
+ SIZE = 32
+ ID = "<% $column %>_text"
+ VALUE = "<% $value %>"
+ >
+ <IMG SRC = "../images/calendar.png"
+ ID = "<% $column %>_button"
+ STYLE = "cursor: pointer"
+ TITLE = "Select date"
+ >
+% if ( $note ) {
+ <BR><FONT SIZE=-1><% $note %></FONT>
+% }
+ </TD>
+ </TR>
+
+ <SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "<% $column %>_text",
+ ifFormat: "%m/%d/%Y",
+ button: "<% $column %>_button",
+ align: "BR"
+ });
+ </SCRIPT>
+
+</%def>
+
+<%def .row_display>
+<%args>
+ $cust_pkg
+ $column
+ $label
+ $note => ''
+</%args>
+% if ( $cust_pkg->get($column) ) {
+ <TR>
+ <TD ALIGN="right"><% $label %> date</TD>
+ <TD BGCOLOR="#ffffff"><% time2str($format,$cust_pkg->get($column)) %>
+% if ( $note ) {
+ <BR><FONT SIZE=-1><% $note %></FONT>
+% }
+ </TD>
+ </TR>
+% }
+</%def>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Apply Changes">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%once>
+
+#my $format = "%c %z (%Z)";
+my $format = "%m/%d/%Y %T %z (%Z)";
+
+#false laziness w/view/cust_main/packages.html
+#my( $billed_or_prepaid,
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer package dates');
+
+my $error = '';
+my( $pkgnum, $cust_pkg );
+
+if ( $cgi->param('error') ) {
+
+ $pkgnum = $cgi->param('pkgnum');
+ if ( $cgi->param('error') eq '_bill_areyousure' ) {
+ if ( $cgi->param('bill') =~ /^([\s\d\/\:\-\(\w\)]*)$/ ) {
+ my $bill = $1;
+ $cgi->param('error', '');
+ $error = "You are attempting to set the next bill date to $bill, which is
+ in the past. This will charge the customer for the interval
+ from $bill until now. Are you sure you want to do this? ".
+ '<INPUT TYPE="checkbox" NAME="bill_areyousure" VALUE="1">';
+ }
+ }
+
+ #get package record
+ $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ die "No package!" unless $cust_pkg;
+
+ foreach my $col (qw( setup last_bill bill adjourn expire )) {
+ my $value = $cgi->param($col);
+ $cust_pkg->set( $col, $value ? str2time($value) : '' );
+ }
+
+} else {
+
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "no pkgnum";
+ $pkgnum = $1;
+
+ #get package record
+ $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ die "No package!" unless $cust_pkg;
+
+}
+
+my $part_pkg = qsearchs( 'part_pkg', { 'pkgpart' => $cust_pkg->pkgpart } );
+
+my( $last_bill_or_renewed, $next_bill_or_prepaid_until );
+unless ( $part_pkg->is_prepaid ) {
+ #$billed_or_prepaid = 'billed';
+ $last_bill_or_renewed = 'Last bill';
+ $next_bill_or_prepaid_until = 'Next bill';
+} else {
+ #$billed_or_prepaid = 'prepaid';
+ $last_bill_or_renewed = 'Renewed';
+ $next_bill_or_prepaid_until = 'Prepaid until';
+}
+
+</%init>
diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html
new file mode 100644
index 000000000..1eed26dfe
--- /dev/null
+++ b/httemplate/edit/access_group.html
@@ -0,0 +1,80 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Employee Group',
+ 'table' => 'access_group',
+ 'labels' => {
+ 'groupnum' => 'Group number',
+ 'groupname' => 'Group name',
+ },
+
+ 'viewall_dir' => 'browse',
+
+ 'html_bottom' => $html_bottom_sub,
+ )
+%>
+<%once>
+
+tie my %rights, 'Tie::IxHash', FS::AccessRight->rights_info;
+
+</%once>
+<%init>
+
+my $html_bottom_sub = sub {
+ my $access_group = shift;
+
+ #some false laziness w/browse/access_group.html
+ my $columns = 3;
+ my $count = 0;
+
+ '<BR>'.
+ '<FONT SIZE="+1">Group limited to these agent(s)</FONT><BR>'.
+ 'Employees in this group will only see customers of the selected agents in the system and reports.<BR>'.
+ ntable("#cccccc",2).
+ '<TR><TD>'.
+ include( '/elements/checkboxes-table.html',
+ 'source_obj' => $access_group,
+ 'link_table' => 'access_groupagent',
+ 'target_table' => 'agent',
+ 'name_col' => 'agent',
+ 'target_link' => $p.'edit/agent.cgi?',
+ 'disable-able' => 1,
+ ).
+ '</TD></TR></TABLE>'.
+
+ '<BR><FONT SIZE="+1">Group access rights</FONT><BR>'.
+ include('/elements/table-grid.html', bgcolor=>'#cccccc' ).
+ '<TR>'. join( '', map {
+ '<TD CLASS="inv" VALIGN="top"><TABLE BGCOLOR="#cccccc" WIDTH=100%>'.
+ '<TR><TH BGCOLOR="#dcdcdc">'. $_. '</TH></TR>'.
+ '<TR><TD>'.
+ include( '/elements/checkboxes-table-name.html',
+ 'source_obj' => $access_group,
+ 'link_table' => 'access_right',
+ 'link_static' => { 'righttype' =>
+ 'FS::access_group',
+ },
+ 'num_col' => 'rightobjnum',
+ 'name_col' => 'rightname',
+ 'names_list' => [ map {
+ my $rn =
+ ref($_) ? $_->{'rightname'} : $_;
+ my %hash = ();
+ $hash{'note'} = '&nbsp;*'
+ if ref($_) && $_->{'global'};
+ $hash{'desc'} = $_->{'desc'}
+ if ref($_) && $_->{'desc'};
+ [ $rn => \%hash ];
+ }
+ @{ $rights{$_} }
+ ],
+ ).
+ '<BR>'.
+ '</TD></TR></TABLE></TD>'.
+ ( ++$count % $columns ? '' : '</TR><TR>')
+
+ } keys %rights ). '</TR></TABLE>'.
+
+ '* Global rights. These rights provide access to global data which is shared among all agents. Their use is not recommended for groups which are limited to a subset of agents.<BR>';
+
+};
+
+</%init>
diff --git a/httemplate/edit/access_user.html b/httemplate/edit/access_user.html
new file mode 100644
index 000000000..73488ef9a
--- /dev/null
+++ b/httemplate/edit/access_user.html
@@ -0,0 +1,50 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Employee',
+ 'table' => 'access_user',
+ 'fields' => [
+ 'username',
+ { field=>'_password', type=>'password' },
+ { field=>'_password2', type=>'password' },
+ 'last',
+ 'first',
+ { field=>'disabled', type=>'checkbox', value=>'Y' },
+ ],
+ 'labels' => {
+ 'usernum' => 'User number',
+ 'username' => 'Username',
+ '_password' => 'Password',
+ '_password2'=> 'Re-enter Password',
+ 'last' => 'Last name',
+ 'first' => 'First name',
+ 'disabled' => 'Disable employee',
+ },
+ 'edit_callback' => sub { my( $c, $o ) = @_;
+ $o->set('_password', '');
+ },
+ 'viewall_dir' => 'browse',
+ 'html_bottom' =>
+ sub {
+ my $access_user = shift;
+
+ '<BR>Employee Groups<BR>'.
+ ntable("#cccccc",2).
+ '<TR><TD>'.
+ include( '/elements/checkboxes-table.html',
+ 'source_obj' => $access_user,
+ 'link_table' => 'access_usergroup',
+ 'target_table' => 'access_group',
+ 'name_col' => 'groupname',
+ 'target_link' => $p.'edit/access_group.html?',
+ #'disable-able' => 1,
+ ).
+ '</TR></TD></TABLE>'
+ ;
+ },
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/agent.cgi b/httemplate/edit/agent.cgi
new file mode 100755
index 000000000..215542de3
--- /dev/null
+++ b/httemplate/edit/agent.cgi
@@ -0,0 +1,123 @@
+<% include("/elements/header.html","$action Agent", menubar(
+ 'View all agents' => $p. 'browse/agent.cgi',
+)) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%popurl(1)%>process/agent.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agent->agentnum %>">
+Agent #<% $agent->agentnum ? $agent->agentnum : "(NEW)" %>
+
+<% &ntable("#cccccc", 2, '') %>
+
+ <TR>
+ <TH ALIGN="right">Agent</TH>
+ <TD><INPUT TYPE="text" NAME="agent" SIZE=32 VALUE="<% $agent->agent %>"></TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Agent type</TH>
+ <TD>
+ <SELECT NAME="typenum" SIZE=1>
+% foreach my $agent_type (qsearch('agent_type',{})) {
+
+ <OPTION VALUE="<% $agent_type->typenum %>"<% ( $agent->typenum && ( $agent->typenum == $agent_type->typenum ) ) ? ' SELECTED' : '' %>>
+ <% $agent_type->getfield('typenum') %>: <% $agent_type->getfield('atype') %>
+% }
+
+ </SELECT>
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Master customer</TH>
+ <TD>
+ <% include('/elements/search-cust_main.html',
+ 'field_name' => 'agent_custnum',
+ 'curr_value' => $agent->agent_custnum,
+ 'find_button' => 1,
+ )
+ %>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Disable</TD>
+ <TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $agent->disabled eq 'Y' ? ' CHECKED' : '' %>></TD>
+ </TR>
+
+ <% include('/elements/tr-select-invoice_template.html',
+ 'label' => 'Invoice template',
+ 'field' => 'invoice_template',
+ 'curr_value' => $agent->invoice_template,
+ )
+ %>
+
+% if ( $conf->config('ticket_system') ) {
+% my $default_queueid = $conf->config('ticket_system-default_queueid');
+% my $default_queue = FS::TicketSystem->queue($default_queueid);
+% $default_queue = "(default) $default_queueid: $default_queue"
+% if $default_queueid;
+% my %queues = FS::TicketSystem->queues();
+% my @queueids = sort { $a <=> $b } keys %queues;
+%
+
+ <TR>
+ <TD ALIGN="right">Ticketing queue</TD>
+ <TD>
+ <SELECT NAME="ticketing_queueid">
+ <OPTION VALUE=""><% $default_queue %>
+% foreach my $queueid ( @queueids ) {
+
+ <OPTION VALUE="<% $queueid %>" <% $agent->ticketing_queueid == $queueid ? ' SELECTED' : '' %>><% $queueid %>: <% $queues{$queueid} %>
+% }
+
+ </SELECT>
+ </TD>
+ </TR>
+% }
+
+ <TR>
+ <TD ALIGN="right">Access Groups</TD>
+ <TD><% include('/elements/checkboxes-table.html',
+ 'source_obj' => $agent,
+ 'link_table' => 'access_groupagent',
+ 'target_table' => 'access_group',
+ 'name_col' => 'groupname',
+ 'target_link' => $p. 'edit/access_group.html?',
+ )
+ %>
+ </TD>
+ </TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="<% $agent->agentnum ? "Apply changes" : "Add agent" %>">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agent;
+if ( $cgi->param('error') ) {
+ $agent = new FS::agent ( {
+ map { $_, scalar($cgi->param($_)) } fields('agent')
+ } );
+} elsif ( $cgi->keywords ) {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $agent = qsearchs( 'agent', { 'agentnum' => $1 } );
+} else { #adding
+ $agent = new FS::agent {};
+}
+my $action = $agent->agentnum ? 'Edit' : 'Add';
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/agent_payment_gateway.html b/httemplate/edit/agent_payment_gateway.html
new file mode 100644
index 000000000..4a7cedf79
--- /dev/null
+++ b/httemplate/edit/agent_payment_gateway.html
@@ -0,0 +1,68 @@
+<% include("/elements/header.html","$action payment gateway override for ". $agent->agent, menubar(
+ #'View all payment gateways' => $p. 'browse/payment_gateway.html',
+ 'View all agents' => $p. 'browse/agent.html',
+)) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%popurl(1)%>process/agent_payment_gateway.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agent->agentnum %>">
+
+Use gateway <SELECT NAME="gatewaynum">
+% foreach my $payment_gateway (
+% qsearch('payment_gateway', { 'disabled' => '' } )
+% ) {
+%
+
+ <OPTION VALUE="<% $payment_gateway->gatewaynum %>"><% $payment_gateway->gateway_module %> (<% $payment_gateway->gateway_username %>)
+% }
+
+</SELECT>
+<BR><BR>
+
+for <SELECT NAME="cardtype" MULTIPLE>
+% foreach my $cardtype (
+% "",
+% "VISA card",
+% "MasterCard",
+% "Discover card",
+% "American Express card",
+% "Diner's Club/Carte Blanche",
+% "enRoute",
+% "JCB",
+% "BankCard",
+% "Switch",
+% "Solo",
+% 'ACH',
+%) {
+
+ <OPTION VALUE="<% $cardtype %>"><% $cardtype || '(Default fallback)' %>
+% }
+
+</SELECT>
+<BR><BR>
+
+(optional) when invoice contains only items of taxclass <INPUT TYPE="text" NAME="taxclass">
+<BR><BR>
+
+<INPUT TYPE="submit" VALUE="Add gateway override">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('agentnum') =~ /(\d+)$/ or die "illegal agentnum";
+my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+die "agentnum $1 not found" unless $agent;
+
+#my @agent_payment_gateway;
+if ( $cgi->param('error') ) {
+}
+
+my $action = 'Add';
+
+</%init>
diff --git a/httemplate/edit/agent_type.cgi b/httemplate/edit/agent_type.cgi
new file mode 100755
index 000000000..abf4bf89f
--- /dev/null
+++ b/httemplate/edit/agent_type.cgi
@@ -0,0 +1,57 @@
+<% include("/elements/header.html","$action Agent Type", menubar(
+ 'View all agent types' => "${p}browse/agent_type.cgi",
+))
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/agent_type.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="typenum" VALUE="<% $agent_type->typenum %>">
+Agent Type #<% $agent_type->typenum || "(NEW)" %>
+<BR>
+
+Agent Type
+<INPUT TYPE="text" NAME="atype" SIZE=32 VALUE="<% $agent_type->atype %>">
+<BR><BR>
+
+Select which packages agents of this type may sell to customers<BR>
+<% ntable("#cccccc", 2) %><TR><TD>
+<% include('/elements/checkboxes-table.html',
+ 'source_obj' => $agent_type,
+ 'link_table' => 'type_pkgs',
+ 'target_table' => 'part_pkg',
+ 'name_callback' => sub { $_[0]->pkg. ' - '. $_[0]->comment; },
+ 'target_link' => $p.'edit/part_pkg.cgi?',
+ 'disable-able' => 1,
+
+ )
+%>
+</TD></TR></TABLE>
+<BR>
+
+<INPUT TYPE="submit" VALUE="<% $agent_type->typenum ? "Apply changes" : "Add agent type" %>">
+
+ </FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my($agent_type);
+if ( $cgi->param('error') ) {
+ $agent_type = new FS::agent_type ( {
+ map { $_, scalar($cgi->param($_)) } fields('agent')
+ } );
+} elsif ( $cgi->keywords ) { #editing
+ my( $query ) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $agent_type=qsearchs('agent_type',{'typenum'=>$1});
+} else { #adding
+ $agent_type = new FS::agent_type {};
+}
+my $action = $agent_type->typenum ? 'Edit' : 'Add';
+
+</%init>
diff --git a/httemplate/edit/allocate.html b/httemplate/edit/allocate.html
new file mode 100644
index 000000000..8d1347df2
--- /dev/null
+++ b/httemplate/edit/allocate.html
@@ -0,0 +1,33 @@
+<% include('elements/edit.html',
+ 'name' => 'Allocation',
+ 'table' => 'addr_block',
+ 'labels' => { 'NetAddr' => 'Block',
+ 'routernum' => 'Router',
+ },
+ 'fields' => [ { 'field' => 'NetAddr',
+ 'type' => 'fixed',
+ },
+ { 'field' => 'routernum',
+ 'type' => 'select-table',
+ 'table' => 'router',
+ 'name_col' => 'routername',
+ 'disable_empty' => 1,
+ 'agent_virt' => 1,
+ 'agent_null_right' =>
+ 'Broadband global configuration',
+ },
+ ],
+ 'post_url' => "process/addr_block/allocate.cgi",
+ 'popup' => 1,
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Broadband global configuration',
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+</%init>
diff --git a/httemplate/edit/bulk-cust_main_county.html b/httemplate/edit/bulk-cust_main_county.html
new file mode 100644
index 000000000..bb57fc5d3
--- /dev/null
+++ b/httemplate/edit/bulk-cust_main_county.html
@@ -0,0 +1,130 @@
+<% include('/elements/header-popup.html', 'Bulk Tax rate') %>
+
+<FORM ACTION="<% popurl(1)."process/bulk-cust_main_county.html" %>" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="taxnum" VALUE="<% join(',', @taxnum) %>">
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+<% include('/elements/tr-td-label.html', 'label' => 'Country' ) %>
+ <TD BGCOLOR="#dddddd"><% $countries %>
+ </TD>
+</TR>
+
+<% include('/elements/tr-td-label.html', 'label' => 'State' ) %>
+ <TD BGCOLOR="#dddddd"><% $states %>
+ </TD>
+</TR>
+
+% if ( $counties ) {
+ <% include('/elements/tr-td-label.html', 'label' => 'County' ) %>
+ <TD BGCOLOR="#dddddd"><% $counties %>
+ </TD>
+ </TR>
+% }
+
+% if ( $conf->exists('enable_taxclasses') && $taxclasses ) {
+ <% include('/elements/tr-td-label.html', 'label' => 'Tax Class' ) %>
+ <TD BGCOLOR="#dddddd"><% $taxclasses %>
+ </TD>
+ </TR>
+% }
+
+<% include('/elements/tr-input-text.html',
+ 'field' => 'taxname',
+ 'label' => 'Tax name'
+ )
+%>
+
+<% include('/elements/tr-input-percentage.html',
+ 'field' => 'tax',
+ 'label' => 'Tax rate',
+ )
+%>
+
+<% include('/elements/tablebreak-tr-title.html', value=>'Exemptions' ) %>
+
+<% include('/elements/tr-checkbox.html',
+ 'field' => 'setuptax',
+ 'value' => 'Y',
+ 'label' => 'This tax not applicable to setup fees',
+ )
+%>
+
+<% include('/elements/tr-checkbox.html',
+ 'field' => 'recurtax',
+ 'value' => 'Y',
+ 'label' => 'This tax not applicable to recurring fees',
+ )
+%>
+
+<% include('/elements/tr-input-money.html',
+ 'field' => 'exempt_amount',
+ 'label' => 'Monthly exemption per customer ($25 "Texas tax")',
+ )
+%>
+
+</TABLE>
+
+<BR>
+
+<INPUT TYPE="submit" VALUE="Bulk add tax">
+
+<%init>
+
+my $conf = new FS::Conf;
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @taxnum;
+if ( $cgi->param('error') ) {
+ $cgi->param('taxnum') =~ /^([\d,]+)$/
+ or die "no taxnum, but error: ". $cgi->param('error');
+ @taxnum = split(',', $1);
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^([\d,]+)$/
+ or die 'Nothing selected'; #XXX better error when nothing selected
+ @taxnum = split(',', $1);
+}
+
+my @cust_main_county =
+ map {
+ qsearchs('cust_main_county', { 'taxnum' => $_ })
+ or die "unknown taxnum $1";
+ }
+ @taxnum;
+
+my %seen_country = {};
+my @countries = map code2country($_)."&nbsp;($_)",
+ grep !$seen_country{$_}++,
+ map $_->country,
+ @cust_main_county;
+my $countries = join(', ', @countries);
+
+my %seen_state = {};
+my @states = map state_label($_->[0], $_->[1]),
+ grep !$seen_state{$_->[0]}++,
+ map [ $_->state, $_->country ],
+ @cust_main_county;
+my $states = join(', ', @states);
+
+my %seen_county = {};
+my @counties = grep !$seen_county{$_}++, map $_->county, @cust_main_county;
+my $counties = join(', ', @counties);
+
+my %seen_taxclass = {};
+my @taxclasses = grep !$seen_taxclass{$_}++, map $_->taxclass, @cust_main_county;
+my $taxclasses = join(', ', @taxclasses);
+
+#my @fields = (
+# { field=>'country', type=>'fixed-country', },
+# { field=>'state', type=>'fixed-state', },
+# { field=>'county', type=>'fixed', },
+#);
+
+#push @fields, { field=>'taxclass', type=>'fixed', }
+# if $conf->exists('enable_taxclasses');
+
+</%init>
diff --git a/httemplate/edit/bulk-cust_svc.html b/httemplate/edit/bulk-cust_svc.html
new file mode 100644
index 000000000..a3c21b112
--- /dev/null
+++ b/httemplate/edit/bulk-cust_svc.html
@@ -0,0 +1,95 @@
+<% include('/elements/header.html', 'Bulk customer service change') %>
+
+<% include('/elements/init_overlib.html') %>
+
+<% include('/elements/progress-init.html',
+ 'OneTrueForm',
+ [qw( old_svcpart new_svcpart pkgpart )],
+ 'process/bulk-cust_svc.cgi',
+ $p.'browse/part_svc.cgi',
+ )
+%>
+
+<FORM NAME="OneTrueForm">
+%
+% $cgi->param('svcpart') =~ /^(\d+)$/
+% or die "illegal svcpart: ". $cgi->param('svcpart');
+%
+% my $old_svcpart = $1;
+% my $src_part_svc = qsearchs('part_svc', { 'svcpart' => $old_svcpart } )
+% or die "unknown svcpart: $old_svcpart";
+%
+
+
+<INPUT NAME="old_svcpart" TYPE="hidden" VALUE="<% $old_svcpart %>">
+Change <!-- customer
+<B><% $src_part_svc->svcpart %>: <% $src_part_svc->svc %></B> services
+<BR>
+-->
+
+<SELECT NAME="pkgpart">
+% my $num_cust_svc = $src_part_svc->num_cust_svc;
+% if ( $num_cust_svc > 1 ) {
+
+ <OPTION VALUE="">all <% $num_cust_svc %> <% $src_part_svc->svc %> services
+% } else {
+
+ <OPTION VALUE="">the <% $num_cust_svc %> <% $src_part_svc->svc %> service
+% }
+%
+% my $num_unlinked = $src_part_svc->num_cust_svc(0);
+% if ( $num_unlinked ) {
+%
+
+ <OPTION VALUE="0">the <% $num_unlinked %> unlinked <% $src_part_svc->svc %> services
+% }
+% foreach my $schwartz (
+% grep { $_->[1] }
+% map { [ $_, $src_part_svc->num_cust_svc($_->pkgpart) ] }
+% qsearch('part_pkg', {} )
+% ) {
+% my( $part_pkg, $num_cust_svc ) = @$schwartz;
+%
+
+ <OPTION VALUE="<% $part_pkg->pkgpart %>">the <% $num_cust_svc %>
+ <% $src_part_svc->svc %> service<% $num_cust_svc > 1 ? 's in' : ' in a' %>
+ <% $part_pkg->pkg %> package<% $num_cust_svc > 1 ? 's' : '' %>
+% }
+
+</SELECT>
+<BR>
+
+to new service definition
+<SELECT NAME="new_svcpart">
+% foreach my $dest_part_svc (
+% grep { $_->svcpart != $old_svcpart
+% && $_->svcdb eq $src_part_svc->svcdb
+% }
+% qsearch('part_svc', { 'disabled' => '' } )
+% ) {
+%
+
+ <OPTION VALUE="<% $dest_part_svc->svcpart %>"><% $dest_part_svc->svcpart %>: <% $dest_part_svc->svc %>
+% }
+
+</SELECT>
+<BR>
+
+<BR>
+
+<SCRIPT TYPE="text/javascript">
+var confirm_change = '<P ALIGN="center"><B>Bulk customer service change - Are you sure?</B><BR><P ALIGN="CENTER" <INPUT TYPE="button" VALUE="Yes, make changes" onClick="process();">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="BUTTON" VALUE="Cancel" onClick="cClick()">';
+</SCRIPT>
+
+<INPUT TYPE="button" VALUE="Bulk change customer services" onClick="overlib(confirm_change, CAPTION, 'Confirm bulk customer service change', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 128, TEXTSIZE, 3, BGCOLOR, '#ff0000', CGCOLOR, '#ff0000' );">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/cust_bill_pay.cgi b/httemplate/edit/cust_bill_pay.cgi
new file mode 100755
index 000000000..532db6a6e
--- /dev/null
+++ b/httemplate/edit/cust_bill_pay.cgi
@@ -0,0 +1,14 @@
+<% include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_bill_pay.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'dst_table' => 'cust_bill',
+ 'dst_thing' => 'invoice',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply payment');
+
+</%init>
diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi
new file mode 100755
index 000000000..c9ca31ff3
--- /dev/null
+++ b/httemplate/edit/cust_credit.cgi
@@ -0,0 +1,68 @@
+<% include('/elements/header-popup.html', 'Enter Credit') %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="credit_popup" ACTION="<% $p1 %>process/cust_credit.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="crednum" VALUE="">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum |h %>">
+<INPUT TYPE="hidden" NAME="paybatch" VALUE="">
+<INPUT TYPE="hidden" NAME="_date" VALUE="<% $_date %>">
+<INPUT TYPE="hidden" NAME="credited" VALUE="">
+<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $otaker %>">
+
+Credit
+<% ntable("#cccccc", 2) %>
+
+ <TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#ffffff"><% time2str("%D",$_date) %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#ffffff">$<INPUT TYPE="text" NAME="amount" VALUE="<% $amount |h %>" SIZE=8 MAXLENGTH=8></TD>
+ </TR>
+
+%
+%#print qq! <INPUT TYPE="checkbox" NAME="refund" VALUE="$refund">Also post refund!;
+%
+
+<% include( '/elements/tr-select-reason.html',
+ 'field' => 'reasonnum',
+ 'reason_class' => 'R',
+ 'control_button' => "document.getElementById('confirm_credit_button')",
+ 'cgi' => $cgi,
+ )
+%>
+
+ <TR>
+ <TD ALIGN="right">Auto-apply<BR>to invoices</TD>
+ <TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD>
+ </TR>
+
+</TABLE>
+
+<BR>
+
+<CENTER><INPUT TYPE="submit" ID="confirm_credit_button" VALUE="Enter credit" DISABLED></CENTER>
+
+</FORM>
+</BODY>
+</HTML>
+<%once>
+
+my $conf = new FS::Conf;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post credit');
+
+my $custnum = $cgi->param('custnum');
+my $amount = $cgi->param('amount');
+my $_date = time;
+my $otaker = getotaker;
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/cust_credit_bill.cgi b/httemplate/edit/cust_credit_bill.cgi
new file mode 100755
index 000000000..e3627ff37
--- /dev/null
+++ b/httemplate/edit/cust_credit_bill.cgi
@@ -0,0 +1,14 @@
+<% include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_credit_bill.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'dst_table' => 'cust_bill',
+ 'dst_thing' => 'invoice',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply credit');
+
+</%init>
diff --git a/httemplate/edit/cust_credit_refund.cgi b/httemplate/edit/cust_credit_refund.cgi
new file mode 100755
index 000000000..f5bbb5633
--- /dev/null
+++ b/httemplate/edit/cust_credit_refund.cgi
@@ -0,0 +1,14 @@
+<% include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_credit_refund.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'dst_table' => 'cust_refund',
+ 'dst_thing' => 'refund',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply credit');
+
+</%init>
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
new file mode 100755
index 000000000..d3004f1c6
--- /dev/null
+++ b/httemplate/edit/cust_main.cgi
@@ -0,0 +1,780 @@
+<% include('/elements/header.html',
+ "Customer $action",
+ '',
+ ' onUnload="myclose()"'
+) %>
+
+<% include('/elements/init_overlib.html') %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="topform" STYLE="margin-bottom: 0">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+
+% if ( $custnum ) {
+ Customer #<B><% $cust_main->display_custnum %></B> -
+ <B><FONT COLOR="#<% $cust_main->statuscolor %>">
+ <% ucfirst($cust_main->status) %>
+ </FONT></B>
+ <BR><BR>
+% }
+
+<% &ntable("#cccccc") %>
+
+%# agent
+<% include('/elements/tr-select-agent.html',
+ 'curr_value' => $cust_main->agentnum,
+ 'label' => "<B>${r}Agent</B>",
+ 'empty_label' => 'Select agent',
+ 'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
+ )
+%>
+
+%# agent_custid
+% if ( $conf->exists('cust_main-edit_agent_custid') ) {
+
+ <TR>
+ <TD ALIGN="right">Customer identifier</TD>
+ <TD><INPUT TYPE="text" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>"></TD>
+ </TR>
+
+% } else {
+
+ <INPUT TYPE="hidden" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>">
+
+% }
+
+%# referral (advertising source)
+%my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
+%if ( $custnum && ! $conf->exists('editreferrals') ) {
+
+ <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
+
+% } else {
+
+ <% include('/elements/tr-select-part_referral.html',
+ 'curr_value' => $refnum
+ )
+ %>
+% }
+
+
+%# referring customer
+%my $referring_cust_main = '';
+%if ( $cust_main->referral_custnum
+% and $referring_cust_main =
+% qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
+%) {
+
+ <TR>
+ <TD ALIGN="right">Referring customer</TD>
+ <TD>
+ <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
+ </TD>
+ </TR>
+ <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
+% } elsif ( ! $conf->exists('disable_customer_referrals') ) {
+
+
+ <TR>
+ <TD ALIGN="right">Referring customer</TD>
+ <TD>
+ <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
+ <% include('/elements/search-cust_main.html',
+ 'field_name' => 'referral_custnum',
+ )
+ %>
+ </TD>
+ </TR>
+% } else {
+
+
+ <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
+% }
+
+
+</TABLE>
+
+<!-- birthdate -->
+
+% if ( $conf->exists('cust_main-enable_birthdate') ) {
+
+ <BR>
+ <% ntable("#cccccc", 2) %>
+ <% include ('/elements/tr-input-date-field.html',
+ 'birthdate',
+ $cust_main->birthdate,
+ 'Date of Birth',
+ $conf->config('date_format') || "%m/%d/%Y",
+ 1)
+ %>
+
+ </TABLE>
+
+% }
+
+<!-- contact info -->
+
+% my $same_checked = '';
+% my $ship_disabled = '';
+% unless ( $cust_main->ship_last && $same ne 'Y' ) {
+% $same_checked = 'CHECKED';
+% $ship_disabled = 'DISABLED STYLE="background-color: #dddddd"';
+% foreach (
+% qw( last first company address1 address2 city county state zip country
+% daytime night fax )
+% ) {
+% $cust_main->set("ship_$_", $cust_main->get($_) );
+% }
+% }
+
+<BR><BR>
+Billing address
+<% include('cust_main/contact.html',
+ 'cust_main' => $cust_main,
+ 'pre' => '',
+ 'onchange' => 'bill_changed(this)',
+ 'disabled' => '',
+ 'ss' => $ss,
+ 'stateid' => $stateid,
+ 'same_checked' => $same_checked, #for address2 "Unit #" labeling
+ )
+%>
+
+<SCRIPT>
+function bill_changed(what) {
+ if ( what.form.same.checked ) {
+% for (qw( last first company address1 address2 city zip daytime night fax )) {
+
+ what.form.ship_<%$_%>.value = what.form.<%$_%>.value;
+% }
+
+ what.form.ship_country.selectedIndex = what.form.country.selectedIndex;
+
+ function fix_ship_county() {
+ what.form.ship_county.selectedIndex = what.form.county.selectedIndex;
+ }
+
+ function fix_ship_state() {
+ what.form.ship_state.selectedIndex = what.form.state.selectedIndex;
+ ship_state_changed(what.form.ship_state, fix_ship_county );
+ }
+
+ ship_country_changed(what.form.ship_country, fix_ship_state );
+
+ }
+}
+function samechanged(what) {
+ if ( what.checked ) {
+ bill_changed(what);
+
+% for (qw( last first company address1 address2 city county state zip country daytime night fax )) {
+ what.form.ship_<%$_%>.disabled = true;
+ what.form.ship_<%$_%>.style.backgroundColor = '#dddddd';
+% }
+
+% if ( $conf->exists('cust_main-require_address2') ) {
+ document.getElementById('address2_required').style.visibility = '';
+ document.getElementById('address2_label').style.visibility = '';
+ document.getElementById('ship_address2_required').style.visibility = 'hidden';
+ document.getElementById('ship_address2_label').style.visibility = 'hidden';
+% }
+
+ } else {
+
+% for (qw( last first company address1 address2 city county state zip country daytime night fax )) {
+ what.form.ship_<%$_%>.disabled = false;
+ what.form.ship_<%$_%>.style.backgroundColor = '#ffffff';
+% }
+
+% if ( $conf->exists('cust_main-require_address2') ) {
+ document.getElementById('address2_required').style.visibility = 'hidden';
+ document.getElementById('address2_label').style.visibility = 'hidden';
+ document.getElementById('ship_address2_required').style.visibility = '';
+ document.getElementById('ship_address2_label').style.visibility = '';
+% }
+
+ }
+}
+</SCRIPT>
+
+<BR>
+Service address
+(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$same_checked%>>same as billing address)
+<% include('cust_main/contact.html',
+ 'cust_main' => $cust_main,
+ 'pre' => 'ship_',
+ 'onchange' => '',
+ 'disabled' => $ship_disabled,
+ )
+%>
+
+
+<!-- billing info -->
+
+<% include( 'cust_main/billing.html', $cust_main,
+ 'payinfo' => $payinfo,
+ 'invoicing_list' => \@invoicing_list,
+ )
+%>
+
+<% include( '/elements/xmlhttp.html',
+ 'url' => $p.'misc/xmlhttp-cust_main-address_standardize.html',
+ 'subs' => [ 'address_standardize' ],
+ #'method' => 'POST', #could get too long?
+ )
+%>
+
+<SCRIPT>
+function bottomfixup(what) {
+
+ //i don't think we need to copy things between two forms anymore, modern
+ //browsers are fine with DIVs inside FORMs
+
+ var topvars = new Array(
+ 'birthdate',
+
+ 'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
+
+ 'last', 'first', 'ss', 'company',
+ 'address1', 'address2', 'city',
+ 'county', 'state', 'zip', 'country',
+ 'daytime', 'night', 'fax',
+ 'stateid', 'stateid_state',
+
+ 'same',
+
+ 'ship_last', 'ship_first', 'ship_company',
+ 'ship_address1', 'ship_address2', 'ship_city',
+ 'ship_county', 'ship_state', 'ship_zip', 'ship_country',
+ 'ship_daytime','ship_night', 'ship_fax',
+
+ 'geocode',
+
+ 'select' // XXX key
+ );
+
+ var layervars = new Array(
+ 'payauto',
+ 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+ 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+ 'paystart_month', 'paystart_year', 'payissue',
+ 'payip',
+ 'paid'
+ );
+
+ var billing_bottomvars = new Array(
+ 'tax',
+ 'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
+ 'invoice_terms',
+ 'spool_cdr',
+ 'squelch_cdr'
+ );
+
+ for ( f=0; f < topvars.length; f++ ) {
+ var field = topvars[f];
+ copyelement( document.topform.elements[field],
+ document.bottomform.elements[field]
+ );
+ }
+
+ var layerform = document.topform.select.options[document.topform.select.selectedIndex].value;
+ for ( f=0; f < layervars.length; f++ ) {
+ var field = layervars[f];
+ copyelement( document.forms[layerform].elements[field],
+ document.bottomform.elements[field]
+ );
+ }
+
+ for ( f=0; f < billing_bottomvars.length; f++ ) {
+ var field = billing_bottomvars[f];
+ copyelement( document.billing_bottomform.elements[field],
+ document.bottomform.elements[field]
+ );
+ }
+
+ //this part does USPS address correction
+
+ // XXX should this be first and should we update the form fields that are
+ // displayed???
+
+ //var state_el = document.bottomform.elements['state'];
+
+ //address_standardize(
+ var cust_main = new Array(
+ 'company', document.bottomform.elements['company'].value,
+ 'address1', document.bottomform.elements['address1'].value,
+ 'address2', document.bottomform.elements['address2'].value,
+ 'city', document.bottomform.elements['city'].value,
+ 'state', document.bottomform.elements['state'].value,
+ //'state', state_el.options[ state_el.selectedIndex ].value,
+ 'zip', document.bottomform.elements['zip'].value,
+
+ 'ship_company', document.bottomform.elements['ship_company'].value,
+ 'ship_address1', document.bottomform.elements['ship_address1'].value,
+ 'ship_address2', document.bottomform.elements['ship_address2'].value,
+ 'ship_city', document.bottomform.elements['ship_city'].value,
+ 'ship_state', document.bottomform.elements['ship_state'].value,
+ //'ship_state', state_el.options[ state_el.selectedIndex ].value,
+ 'ship_zip', document.bottomform.elements['ship_zip'].value
+ );
+
+ address_standardize( cust_main, update_address );
+
+}
+
+var standardize_address;
+
+function update_address(arg) {
+
+ var argsHash = eval('(' + arg + ')');
+
+ var changed = argsHash['address_standardized'];
+ var ship_changed = argsHash['ship_address_standardized'];
+ var error = argsHash['error'];
+ var ship_error = argsHash['ship_error'];
+
+ //yay closures
+ standardize_address = function () {
+
+ if ( changed ) {
+ document.bottomform.elements['company'].value = argsHash['new_company'];
+ document.bottomform.elements['address1'].value = argsHash['new_address1'];
+ document.bottomform.elements['address2'].value = argsHash['new_address2'];
+ document.bottomform.elements['city'].value = argsHash['new_city'];
+ document.bottomform.elements['state'].value = argsHash['new_state'];
+ //'state', state_el.options[ state_el.selectedIndex ].value,
+ document.bottomform.elements['zip'].value = argsHash['new_zip'];
+ }
+
+ if ( ship_changed ) {
+ document.bottomform.elements['ship_company'].value = argsHash['new_ship_company'];
+ document.bottomform.elements['ship_address1'].value = argsHash['new_ship_address1'];
+ document.bottomform.elements['ship_address2'].value = argsHash['new_ship_address2'];
+ document.bottomform.elements['ship_city'].value = argsHash['new_ship_city'];
+ document.bottomform.elements['ship_state'].value = argsHash['new_ship_state'];
+ //'state', state_el.options[ state_el.selectedIndex ].value,
+ document.bottomform.elements['ship_zip'].value = argsHash['new_ship_zip'];
+ }
+
+ }
+
+% if ( $conf->exists('enable_taxproducts') ) {
+
+ if ( <% $taxpre %>error ) {
+
+ if ( document.bottomform.elements['country'].value == 'CA' ||
+ document.bottomform.elements['country'].value == 'US'
+ )
+ {
+
+ var url = "cust_main/choose_tax_location.html?data_vendor=cch-zip;city="+document.bottomform.elements['city'].value+";state="+document.bottomform.elements['state'].value+";zip="+document.bottomform.elements['zip'].value+";country="+document.bottomform.elements['country'].value+";";
+ // popup a chooser
+ OLgetAJAX( url, update_geocode, 300 );
+
+ } else {
+
+ document.bottomform.elements['geocode'].value = 'DEFAULT';
+ document.bottomform.submit();
+
+ }
+
+ } else
+
+% }
+
+ if ( changed || ship_changed ) {
+
+% if ( $conf->exists('cust_main-auto_standardize_address') ) {
+
+ standardize_address();
+ document.bottomform.submit();
+
+% } else {
+
+ // popup a confirmation popup
+
+ var confirm_change =
+ '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
+ '<TABLE>';
+
+ if ( changed ) {
+
+ confirm_change = confirm_change +
+ '<TR><TH>Entered billing address</TH>' +
+ '<TH>Standardized billing address</TH></TR>';
+ // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ if ( argsHash['company'] || argsHash['new_company'] ) {
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['company'] +
+ '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['address1'] +
+ '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['address2'] +
+ '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + ' ' + argsHash['zip'] +
+ '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + ' ' + argsHash['new_zip'] + '</TD></TR>' +
+ '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ }
+
+ if ( ship_changed ) {
+
+ confirm_change = confirm_change +
+ '<TR><TH>Entered service address</TH>' +
+ '<TH>Standardized service address</TH></TR>';
+ // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['ship_company'] +
+ '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' + argsHash['ship_address1'] +
+ '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['ship_address2'] +
+ '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
+ '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + ' ' + argsHash['ship_zip'] +
+ '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + ' ' + argsHash['new_ship_zip'] + '</TD></TR>' +
+ '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+ }
+
+ var addresses = 'address';
+ var height = 268;
+ if ( changed && ship_changed ) {
+ addresses = 'addresses';
+ height = 396; // #what
+ }
+
+ confirm_change = confirm_change +
+ '<TR><TD>' +
+ '<BUTTON TYPE="button" onClick="document.bottomform.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' +
+ '</TD><TD>' +
+ '<BUTTON TYPE="button" onClick="standardize_address(); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' +
+ '</TD></TR>' +
+ '<TR><TD COLSPAN=2 ALIGN="center">' +
+ '<BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+
+ '</TABLE></CENTER>';
+
+ overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+% }
+
+ } else {
+
+ document.bottomform.submit();
+
+ }
+
+}
+
+function update_geocode() {
+
+ //yay closures
+ set_geocode = function (what) {
+
+ //alert(what.options[what.selectedIndex].value);
+ var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
+ document.bottomform.elements['city'].value = argsHash['city'];
+ document.bottomform.elements['state'].value = argsHash['state'];
+ document.bottomform.elements['zip'].value = argsHash['zip'];
+ document.bottomform.elements['geocode'].value = argsHash['geocode'];
+
+ }
+
+ // popup a chooser
+
+ overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+}
+
+function copyelement(from, to) {
+ if ( from == undefined ) {
+ to.value = '';
+ } else if ( from.type == 'select-one' ) {
+ to.value = from.options[from.selectedIndex].value;
+ //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
+ } else if ( from.type == 'checkbox' ) {
+ if ( from.checked ) {
+ to.value = from.value;
+ } else {
+ to.value = '';
+ }
+ } else {
+ if ( from.value == undefined ) {
+ to.value = '';
+ } else {
+ to.value = from.value;
+ }
+ }
+ //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
+}
+
+</SCRIPT>
+
+<FORM ACTION="<% popurl(1) %>process/cust_main.cgi" METHOD=POST NAME="bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+% foreach my $hidden (
+% 'birthdate',
+%
+% 'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
+% 'last', 'first', 'ss', 'company',
+% 'address1', 'address2', 'city',
+% 'county', 'state', 'zip', 'country',
+% 'daytime', 'night', 'fax',
+% 'stateid', 'stateid_state',
+%
+% 'same',
+%
+% 'ship_last', 'ship_first', 'ship_company',
+% 'ship_address1', 'ship_address2', 'ship_city',
+% 'ship_county', 'ship_state', 'ship_zip', 'ship_country',
+% 'ship_daytime','ship_night', 'ship_fax',
+%
+% 'geocode',
+%
+% 'select', #XXX key
+%
+% 'payauto',
+% 'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+% 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+% 'paystart_month', 'paystart_year', 'payissue',
+% 'payip',
+% 'paid',
+%
+% 'tax',
+% 'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
+% 'invoice_terms',
+% 'spool_cdr',
+% 'squelch_cdr'
+% ) {
+%
+
+ <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
+% }
+%
+% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
+% if (!$ro_comments || $cust_main->comments) {
+
+<BR>Comments
+<% &ntable("#cccccc") %>
+ <TR>
+ <TD>
+ <TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments" <%$ro_comments%>><% $cust_main->comments %></TEXTAREA>
+ </TD>
+ </TR>
+</TABLE>
+%
+% }
+%
+%unless ( $custnum ) {
+% # pry the wrong place for this logic. also pretty expensive
+% #use FS::part_pkg;
+%
+% #false laziness, copied from FS::cust_pkg::order
+% my $pkgpart;
+% my $agentnum = '';
+% my @agents = $FS::CurrentUser::CurrentUser->agents;
+% if ( scalar(@agents) == 1 ) {
+% # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
+% $pkgpart = $agents[0]->pkgpart_hashref;
+% $agentnum = $agents[0]->agentnum;
+% } else {
+% #can't know (agent not chosen), so, allow all
+% $agentnum = 'all';
+% my %typenum;
+% foreach my $agent ( @agents ) {
+% next if $typenum{$agent->typenum}++;
+% $pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
+% }
+% }
+% #eslaf
+%
+% my @part_pkg = grep { $_->svcpart('svc_acct')
+% && ( $pkgpart->{ $_->pkgpart }
+% || $agentnum eq 'all'
+% || ( $agentnum ne 'all'
+% && $agentnum
+% && $_->agentnum
+% && $_->agentnum == $agentnum
+% )
+% )
+% }
+% qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
+%
+% if ( @part_pkg ) {
+%
+% # print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"),
+% #apiabuse & undesirable wrapping
+%
+%
+
+ <BR>First package
+ <% ntable("#cccccc") %>
+
+ <TR>
+ <TD COLSPAN=2>
+ <% include('cust_main/select-domain.html',
+ 'pkgparts' => \@part_pkg,
+ 'saved_pkgpart' => $saved_pkgpart,
+ 'saved_domsvc' => $saved_domsvc,
+ )
+ %>
+ </TD>
+ </TR>
+%
+% #false laziness: (mostly) copied from edit/svc_acct.cgi
+% #$ulen = $svc_acct->dbdef_table->column('username')->length;
+% my $ulen = dbdef->table('svc_acct')->column('username')->length;
+% my $ulen2 = $ulen+2;
+% my $passwordmax = $conf->config('passwordmax') || 8;
+% my $pmax2 = $passwordmax + 2;
+%
+
+
+ <TR>
+ <TD ALIGN="right">Username</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="username" VALUE="<% $username %>" SIZE=<% $ulen2 %> MAXLENGTH=<% $ulen %>>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Domain</TD>
+ <TD>
+ <SELECT NAME="domsvc">
+ <OPTION>(none)</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Password</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $passwordmax %>>
+ (blank to generate)
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Access number</TD>
+ <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
+ </TR>
+ </TABLE>
+% }
+% }
+
+
+<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
+<BR>
+<INPUT TYPE="button" NAME="submitButton" ID="submitButton" VALUE="<% $custnum ? "Apply Changes" : "Add Customer" %>" onClick="document.bottomform.submitButton.disabled=true; bottomfixup(this.form);">
+<BR>
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+
+#for misplaced logic below
+#use FS::part_pkg;
+
+#for false laziness below (now more properly lazy)
+#use FS::svc_acct_pop;
+
+#for (other) false laziness below
+#use FS::agent;
+#use FS::type_pkgs;
+
+my $conf = new FS::Conf;
+
+my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
+#get record
+
+my($custnum, $username, $password, $popnum, $cust_main, $saved_pkgpart, $saved_domsvc);
+my(@invoicing_list);
+my ($ss,$stateid,$payinfo);
+my $same = '';
+if ( $cgi->param('error') ) {
+ $cust_main = new FS::cust_main ( {
+ map { $_, scalar($cgi->param($_)) } fields('cust_main')
+ } );
+ $custnum = $cust_main->custnum;
+ $saved_domsvc = $cgi->param('domsvc') || '';
+ if ( $saved_domsvc =~ /^(\d+)$/ ) {
+ $saved_domsvc = $1;
+ } else {
+ $saved_domsvc = '';
+ }
+ $saved_pkgpart = $cgi->param('pkgpart_svcpart') || '';
+ if ( $saved_pkgpart =~ /^(\d+)_/ ) {
+ $saved_pkgpart = $1;
+ } else {
+ $saved_pkgpart = '';
+ }
+ $username = $cgi->param('username');
+ $password = $cgi->param('_password');
+ $popnum = $cgi->param('popnum');
+ @invoicing_list = split( /\s*,\s*/, $cgi->param('invoicing_list') );
+ $same = $cgi->param('same');
+ $cust_main->setfield('paid' => $cgi->param('paid')) if $cgi->param('paid');
+ $ss = $cust_main->ss; # don't mask an entered value on errors
+ $stateid = $cust_main->stateid; # don't mask an entered value on errors
+ $payinfo = $cust_main->payinfo; # don't mask an entered value on errors
+} elsif ( $cgi->keywords ) { #editing
+ my( $query ) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $custnum=$1;
+ $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+ if ( $cust_main->dbdef_table->column('paycvv')
+ && length($cust_main->paycvv) ) {
+ my $paycvv = $cust_main->paycvv;
+ $paycvv =~ s/./*/g;
+ $cust_main->paycvv($paycvv);
+ }
+ $saved_pkgpart = 0;
+ $saved_domsvc = 0;
+ $username = '';
+ $password = '';
+ $popnum = 0;
+ @invoicing_list = $cust_main->invoicing_list;
+ $ss = $cust_main->masked('ss');
+ $stateid = $cust_main->masked('stateid');
+ $payinfo = $cust_main->paymask;
+} else {
+ $custnum='';
+ $cust_main = new FS::cust_main ( {} );
+ $cust_main->otaker( &getotaker );
+ $cust_main->referral_custnum( $cgi->param('referral_custnum') );
+ $saved_pkgpart = 0;
+ $saved_domsvc = 0;
+ $username = '';
+ $password = '';
+ $popnum = 0;
+ @invoicing_list = ();
+ push @invoicing_list, 'POST'
+ unless $conf->exists('disablepostalinvoicedefault');
+ $ss = '';
+ $stateid = '';
+ $payinfo = '';
+}
+
+my $error = $cgi->param('error');
+$cgi->delete_all();
+$cgi->param('error', $error);
+
+my $action = $custnum ? 'Edit' : 'Add';
+$action .= ": ". $cust_main->name if $custnum;
+
+my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+</%init>
diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html
new file mode 100644
index 000000000..8724db9dc
--- /dev/null
+++ b/httemplate/edit/cust_main/billing.html
@@ -0,0 +1,484 @@
+%if ( $payby_default eq 'HIDE' ) {
+%
+% $cust_main->payby('BILL') unless $cust_main->payby;
+
+ <INPUT TYPE="hidden" NAME="select" VALUE="<% $cust_main->payby %>">
+
+ </FORM>
+
+ <FORM NAME="<% $cust_main->payby %>" STYLE="margin-top: 0; margin-bottom: 0">
+
+ <INPUT TYPE="hidden" NAME="payinfo" VALUE="<% $cust_main->paymask %>">
+
+% foreach my $field (qw( payname paycvv paystart_month paystart_year payissue payip paytype paystate )) {
+
+ <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $cust_main->getfield($field) %>">
+
+% }
+
+% #false laziness w/elements/select-month_year.html & view/cust_main/billing.html
+% my( $mon, $year );
+% my $date = $cust_main->paydate || '12-2037';
+% if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
+% ( $mon, $year ) = ( $2, $1 );
+% } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+% ( $mon, $year ) = ( $1, $3 );
+% } else {
+% die "unrecognized expiration date format: $date";
+% }
+
+ <INPUT TYPE="hidden" NAME="exp_month" VALUE="<% $mon %>">
+ <INPUT TYPE="hidden" NAME="exp_year" VALUE="<% $year %>">
+
+ </FORM>
+
+ <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+
+ <INPUT TYPE="hidden" NAME="tax" VALUE="<% $cust_main->tax %>">
+
+ <INPUT TYPE="hidden" NAME="invoicing_list" VALUE="<% join(', ', @invoicing_list) %>">
+
+ </FORM>
+
+% } else {
+%
+% my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+ <BR>Billing information
+ <% &ntable("#cccccc") %>
+
+ <TR>
+ <TD ALIGN="right" WIDTH="200"><%$r%>Billing type</TD>
+
+ <SCRIPT>
+
+ var mywindow = -1;
+ function myopen(filename,windowname,properties) {
+ myclose();
+ mywindow = window.open(filename,windowname,properties);
+ }
+ function myclose() {
+ if ( mywindow != -1 )
+ mywindow.close();
+ mywindow = -1;
+ }
+
+ var achwindow = -1;
+ function achopen(filename,windowname,properties) {
+ achclose();
+ achwindow = window.open(filename,windowname,properties);
+ }
+ function achclose() {
+ if ( achwindow != -1 )
+ achwindow.close();
+ achwindow = -1;
+ }
+
+ function card_changed(what) {
+ if (
+ what.form.payinfo.value.substring(0, 4) == '4093'
+ || what.form.payinfo.value.substring(0, 4) == '4911'
+ || what.form.payinfo.value.substring(0, 4) == '4936'
+ || what.form.payinfo.value.substring(0, 6) == '564132'
+ || what.form.payinfo.value.substring(0, 2) == '63'
+ || what.form.payinfo.value.substring(0, 2) == '67'
+ )
+ {
+ what.form.paystart_month.disabled = false;
+ what.form.paystart_year.disabled = false;
+ what.form.payissue.disabled = false;
+ what.form.paystart_month.style.backgroundColor = '#ffffff';
+ what.form.paystart_year.style.backgroundColor = '#ffffff';
+ what.form.payissue.style.backgroundColor = '#ffffff';
+ document.getElementById('paystart_label').style.color = '#000000';
+ document.getElementById('payissue_label').style.color = '#000000';
+ } else {
+ what.form.paystart_month.disabled = true;
+ what.form.paystart_year.disabled = true;
+ what.form.payissue.disabled = true;
+ what.form.paystart_month.style.backgroundColor = '#dddddd';
+ what.form.paystart_year.style.backgroundColor = '#dddddd';
+ what.form.payissue.style.backgroundColor = '#dddddd';
+ document.getElementById('paystart_label').style.color = '#999999';
+ document.getElementById('payissue_label').style.color = '#999999';
+ }
+ return true;
+ }
+
+ </SCRIPT>
+
+ <% include('/elements/init_overlib.html') %>
+
+% my $payby = $cust_main->payby;
+% my $paytype = $cust_main->paytype;
+% my( $account, $aba ) = split('@', $payinfo);
+%
+% my $disabled = 'DISABLED style="background-color: #dddddd"';
+% my $text_disabled = 'style="color: #999999"';
+%
+% if ( $payby =~ /^(CARD|DCRD)$/ && cardtype($payinfo) =~ /^(Switch|Solo)$/ ) {
+% $disabled = 'style="background-color: #ffffff"';
+% $text_disabled = 'style="color: #000000";'
+% }
+%
+% my %payby = (
+%
+% 'CARD' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Card number </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
+% '<TD WIDTH="408">'.
+%
+% include('/elements/select-month_year.html',
+% 'prefix' => 'exp',
+% 'selected_date' =>
+% ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->paydate : '' ),
+% ).
+%
+% '</TD></TR>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">CVV2&nbsp;!.
+%
+% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
+% qq!</TD>!.
+% '<TD WIDTH="408"><INPUT TYPE="text" NAME="paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
+%
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200"><SPAN ID="paystart_label" $text_disabled>Start date </SPAN></TD>!.
+% '<TD WIDTH="408">'.
+%
+% include('/elements/select-month_year.html',
+% 'prefix' => 'paystart',
+% 'disabled' => $disabled,
+% 'empty_option' => 1,
+% 'start_year' => 2000,
+% 'end_year' => (localtime())[5] + 1900,
+% 'selected_date' => (
+% ( $payby =~ /^(CARD|DCRD)$/
+% && cardtype($payinfo) =~ /^(Switch|Solo)$/ )
+% ? $cust_main->paystart_month. '-'.
+% $cust_main->paystart_year
+% : ''
+% )
+% ).
+%
+% qq!<SPAN ID="payissue_label" $text_disabled> or Issue number </SPAN>!.
+% '<INPUT TYPE="text" NAME="payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Exact name on card </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%
+% qq!<TR><TD COLSPAN=2 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCRD' ? '' : 'CHECKED' ). '> Charge future payments to this card automatically</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'CHEK' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Account number </TD>!.
+% qq!<TD><INPUT TYPE="text" SIZE=12 NAME="payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
+% qq!<TD ALIGN="right">Type</TD><TD><SELECT NAME="paytype">!.
+% join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes).
+% qq!</SELECT></TD></TR>!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}ABA/Routing number </TD>!.
+% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!" SIZE=10 MAXLENGTH=9> !.
+% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
+% qq!</TD></TR>!.
+%
+% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Bank name </TD>!.
+% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+% ( $conf->exists('show_bankstate') ?
+% qq!<TR><TD ALIGN="right" WIDTH="200">$paystate_label</TD>!.
+% qq!<TD COLSPAN="3" WIDTH="408">!.
+% include('/elements/select-state.html',
+% 'empty' => '(choose)',
+% 'state' => $cust_main->paystate,
+% 'country' => $cust_main->country,
+% 'prefix' => 'pay',
+% ). "</TD></TR>"
+% : '<INPUT TYPE="hidden" NAME="paystate" VALUE="'.
+% $cust_main->paystate. '">'
+% ).
+%
+%
+% qq!<TR><TD COLSPAN=4 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCHK' ? '' : 'CHECKED' ). '> Charge future payments to this electronic check automatically</TD></TR>'.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'LECB' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Phone number </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
+%
+% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+% qq!<INPUT TYPE="hidden" NAME="payname" VALUE="">!.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'BILL' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">P.O. </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
+%
+% qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
+% qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">Attention </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'COMP' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Approved by </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE=""></TD></TR>!.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
+% '<TD WIDTH="408">'.
+%
+% include('/elements/select-month_year.html',
+% 'prefix' => 'exp',
+% 'selected_date' =>
+% ( $payby eq 'COMP' ? $cust_main->paydate : '' ),
+% ).
+%
+% '</TD></TR>'.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'CASH' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'WEST' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% 'MCRD' =>
+%
+% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
+%
+% qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
+% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+% '<TR><TD>&nbsp;</TD></TR>'.
+%
+% '</TABLE>',
+%
+% );
+%
+% #this should use FS::payby
+% my %allopt = (
+% 'CARD' => 'Credit card',
+% 'CHEK' => 'Electronic check',
+% 'LECB' => 'Phone bill billing',
+% 'BILL' => 'Billing',
+% 'CASH' => 'Cash', # initial payment, then billing',
+% 'WEST' => 'Western Union', # initial payment, then billing',
+% 'MCRD' => 'Manual credit card', # initial payment, then billing',
+% 'COMP' => 'Complimentary',
+% );
+% if ( $cust_main->custnum ) { #don't offer CASH/WEST/MCRD initial payment types
+% # when editing customer
+% delete $allopt{$_} for qw(CASH WEST MCRD);
+% }
+%
+% tie my %options, 'Tie::IxHash',
+% map { $_ => $allopt{$_} }
+% grep { exists $allopt{$_} }
+% @payby;
+%
+% my %payby2option = (
+% ( map { $_ => $_ } keys %options ),
+% 'DCRD' => 'CARD',
+% 'DCHK' => 'CHEK',
+% );
+%
+% my $widget = new HTML::Widgets::SelectLayers(
+% 'options' => \%options,
+% #'form_name' => 'dummy',
+% #'form_action' => 'nothingyet',
+% #chops bottom of page in IE# 'under_position' => 'absolute',
+% 'html_between' => '</TD></TR></TABLE>',
+% 'selected_layer' => $payby2option{$payby || $payby_default || $payby[0] },
+% 'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
+% );
+%
+%
+
+
+ <TD WIDTH="408"><% $widget->html %>
+
+ <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+
+ <% &ntable("#cccccc") %>
+
+ <TR><TD>&nbsp;</TD></TR>
+
+ <TR>
+ <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="tax" VALUE="Y" <% $cust_main->tax eq "Y" ? 'CHECKED' : '' %>> Tax Exempt</TD>
+ </TR>
+
+% unless ( $conf->exists('emailinvoiceonly') ) {
+
+ <TR>
+ <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="invoicing_list_POST" VALUE="POST" <%
+
+ ( grep { $_ eq 'POST' } @invoicing_list )
+
+ ? 'CHECKED'
+ : ''
+
+ %>> Postal mail invoice
+
+ </TD>
+ </TR>
+
+ <TR>
+ <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="invoicing_list_FAX" VALUE="FAX" <%
+
+ ( grep { $_ eq 'FAX' } @invoicing_list )
+ ? 'CHECKED'
+ : ''
+
+ %>> Fax invoice
+
+ </TD>
+ </TR>
+
+% }
+
+ <TR>
+ <TD ALIGN="right" WIDTH="200">
+ <% $conf->exists('cust_main-require_invoicing_list_email') ? $r : '' %>Email address(es)
+ </TD>
+ <TD WIDTH="408"><INPUT TYPE="text" NAME="invoicing_list" VALUE="<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) %>"></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right" WIDTH="200">Invoice terms </TD>
+ <TD WIDTH="408">
+ <SELECT NAME="invoice_terms">
+ <OPTION VALUE="">Default (<% $conf->config('invoice_default_terms') || 'Payable upon receipt' %>)
+% foreach my $term ( 'Payable upon receipt',
+% ( map "Net $_", 0, 10, 15, 30, 45, 60 ),
+% ) {
+ <OPTION VALUE="<% $term %>" <% $cust_main->invoice_terms eq $term ? ' SELECTED' : '' %>><% $term %>
+% }
+ </SELECT>
+ </TD>
+ </TR>
+
+% if ( $conf->exists('voip-cust_cdr_spools') ) {
+ <TR>
+ <TD COLSPAN="2"><INPUT TYPE="checkbox" NAME="spool_cdr" VALUE="Y" <% $cust_main->spool_cdr eq "Y" ? 'CHECKED' : '' %>> Spool CDRs</TD>
+ </TR>
+% } else {
+
+ <INPUT TYPE="hidden" NAME="spool_cdr" VALUE="<% $cust_main->spool_cdr %>">
+% }
+
+% if ( $conf->exists('voip-cust_cdr_squelch') ) {
+ <TR>
+ <TD COLSPAN="2"><INPUT TYPE="checkbox" NAME="squelch_cdr" VALUE="Y" <% $cust_main->squelch_cdr eq "Y" ? 'CHECKED' : '' %>> Omit CDRs from invoices</TD>
+ </TR>
+% } else {
+
+ <INPUT TYPE="hidden" NAME="squelch_cdr" VALUE="<% $cust_main->squelch_cdr %>">
+% }
+
+ </TABLE>
+
+ </FORM>
+
+ <% $r %> required fields
+% }
+
+<%once>
+
+my $paystate_label = FS::Msgcat::_gettext('paystate');
+$paystate_label = 'Bank state' if $paystate_label =~/^paystate$/;
+
+</%once>
+<%init>
+
+my( $cust_main, %options ) = @_;
+my @invoicing_list = @{ $options{'invoicing_list'} };
+my $payinfo = $options{'payinfo'};
+my $conf = new FS::Conf;
+my $payby_default = $conf->config('payby-default');
+
+my @payby = grep /\w/, $conf->config('payby');
+#@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
+@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
+ unless @payby;
+
+</%init>
diff --git a/httemplate/edit/cust_main/choose_tax_location.html b/httemplate/edit/cust_main/choose_tax_location.html
new file mode 100644
index 000000000..bd8b95cb6
--- /dev/null
+++ b/httemplate/edit/cust_main/choose_tax_location.html
@@ -0,0 +1,85 @@
+<FORM NAME="choosegeocodeform">
+<CENTER><BR><B>Choose tax location</B><BR><BR>
+<P STYLE="<% $style %>"><% $header %></P>
+
+<SELECT NAME='geocodes' ID='geocodes' STYLE="<% $style %>">
+% foreach my $location (@cust_tax_location) {
+% my %value = ( zip => $zip5,
+% map { $_ => $location->$_ }
+% qw ( city state geocode )
+% );
+% map { $value{$_} = $location{$_} } qw ( city state )
+% if $location{country} eq 'CA';
+%
+% my $value = encode_entities(objToJson({ %value })
+% );
+% my $content = '';
+% $content .= $location->$_. '&nbsp;' x ( $max{$_} - length($location->$_) )
+% foreach qw( city county state );
+% $content .= $location->cityflag eq 'I' ? 'Y' : 'N' ;
+% my $selected = '' ;
+% if (!$have_selected && lc($location->city) eq lc($location{city})) {
+% $selected = 'SELECTED';
+% }
+ <OPTION VALUE="<% $value %>" STYLE="<% $style %>" <% $selected %>><% $content %>
+% }
+</SELECT><BR><BR>
+
+<TABLE><TR>
+ <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes')); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
+ <TD><BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
+</TR>
+</TABLE>
+
+</CENTER>
+</FORM>
+<%init>
+
+my $conf = new FS::Conf;
+my $have_selected = 0;
+
+my %location = ();
+
+($location{data_vendor}) = $cgi->param('data_vendor') =~ /^([-\w]+)$/;
+($location{city}) = $cgi->param('city') =~ /^([\w ]+)$/;
+($location{state}) = $cgi->param('state') =~ /^(\w+)$/;
+($location{zip}) = $cgi->param('zip') =~ /^([-\w ]+)$/;
+($location{country}) = $cgi->param('country') =~ /^([\w ]+)$/;
+
+my($zip5, $zip4) = split('-', $location{zip});
+
+#only support US & CA
+my $hashref = { 'data_vendor' => $location{data_vendor} };
+$hashref->{zip} = $location{country} eq 'CA' ? substr($zip5,0,1) : $zip5,
+
+my @keys = keys(%$hashref);
+my @cust_tax_location = ();
+until ( @cust_tax_location ) {
+ @cust_tax_location = qsearch({ table => 'cust_tax_location',
+ hashref => $hashref,
+ order_by => 'LIMIT 50',
+ });
+ last unless scalar(@keys);
+ delete $hashref->{ shift @keys };
+}
+
+my %max = ( city => 4, county => 6, state => 5);
+foreach my $location (@cust_tax_location) {
+ foreach ( qw( city county state ) ) {
+ my $length = length($location->$_);
+ $max{$_} = ($length > $max{$_}) ? $length : $max{$_};
+ }
+}
+foreach ( qw( city county state ) ) {
+ $max{$_} = $location{$_} if $location{$_} > $max{$_};
+ $max{$_}++;
+}
+
+my $header = '&nbsp;&nbsp;';
+$header .= $_. '&nbsp;' x ( $max{lc($_)} - length($_) )
+ foreach qw( City County State );
+$header .= "In city?";
+
+my $style = "font-family:monospace;";
+
+</%init>
diff --git a/httemplate/edit/cust_main/contact.html b/httemplate/edit/cust_main/contact.html
new file mode 100644
index 000000000..27dd38516
--- /dev/null
+++ b/httemplate/edit/cust_main/contact.html
@@ -0,0 +1,137 @@
+<% &ntable("#cccccc") %>
+
+<TR>
+ <TH ALIGN="right"><%$r%>Contact&nbsp;name<BR>(last,&nbsp;first)</TH>
+ <TD COLSPAN=5>
+ <INPUT TYPE="text" NAME="<%$pre%>last" VALUE="<% $cust_main->get($pre.'last') %>" onChange="<% $onchange %>" <%$disabled%>> ,
+ <INPUT TYPE="text" NAME="<%$pre%>first" VALUE="<% $cust_main->get($pre.'first') %>" onChange="<% $onchange %>" <%$disabled%>>
+ </TD>
+% if ( $conf->exists('show_ss') && !$pre ) {
+
+ <TD ALIGN="right">SS#</TD>
+ <TD><INPUT TYPE="text" NAME="ss" VALUE="<% $opt{ss} %>" SIZE=11></TD>
+% } elsif ( !$pre ) {
+
+ <TD><INPUT TYPE="hidden" NAME="ss" VALUE="<% $opt{ss} %>"></TD>
+% }
+
+
+</TR>
+
+<TR>
+ <TD ALIGN="right">Company</TD>
+ <TD COLSPAN=7>
+ <INPUT TYPE="text" NAME="<%$pre%>company" VALUE="<% $cust_main->get($pre.'company') %>" SIZE=70 onChange="<% $onchange %>" <%$disabled%>>
+ </TD>
+</TR>
+
+<% include('/elements/location.html',
+ 'prefix' => $pre,
+ 'object' => $cust_main,
+ 'onchange' => $onchange,
+ 'disabled' => $disabled,
+ 'same_checked' => $opt{'same_checked'},
+ 'geocode' => $opt{'geocode'},
+ )
+%>
+
+<TR>
+ <TD ALIGN="right"><% $daytime_label %></TD>
+ <TD COLSPAN=5>
+ <INPUT TYPE="text" NAME="<%$pre%>daytime" VALUE="<% $cust_main->get($pre.'daytime') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%>>
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right"><% $night_label %></TD>
+ <TD COLSPAN=5>
+ <INPUT TYPE="text" NAME="<%$pre%>night" VALUE="<% $cust_main->get($pre.'night') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%>>
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Fax</TD>
+ <TD COLSPAN=5>
+ <INPUT TYPE="text" NAME="<%$pre%>fax" VALUE="<% $cust_main->get($pre.'fax') %>" SIZE=12 onChange="<% $onchange %>" <%$disabled%>>
+ </TD>
+</TR>
+
+% if ( $conf->exists('show_stateid') && !$pre ) {
+
+<TR>
+ <TD ALIGN="right"><% $stateid_label %></TD>
+ <TD><INPUT TYPE="text" NAME="stateid" VALUE="<% $opt{stateid} %>" SIZE=12 onChange="<% $onchange %>" <%$disabled%>></TD>
+ <TD ALIGN="right"><% $stateid_state_label %></TD>
+ <TD><% include('/elements/select-state.html',
+ 'state' => $cust_main->stateid_state,
+ 'country' => $cust_main->country,
+ 'prefix' => 'stateid_',
+ 'onchange' => $onchange,
+ 'disabled' => $disabled,
+ )
+ %>
+ </TD>
+</TR>
+% } elsif ( !$pre ) {
+
+ <TD><INPUT TYPE="hidden" NAME="stateid" VALUE="<% $opt{stateid} %>"></TD>
+ <TD><INPUT TYPE="hidden" NAME="stateid_state" VALUE="<% $cust_main->stateid_state %>"></TD>
+% }
+
+</TABLE>
+<%$r%>required fields<BR>
+
+<%init>
+
+#my( $cust_main, $pre, $onchange, $disabled, %opt ) = @_;
+my %opt = @_;
+my $cust_main = $opt{'cust_main'};
+my $pre = $opt{'pre'};
+my $onchange = $opt{'onchange'};
+my $disabled = $opt{'disabled'};
+
+my $conf = new FS::Conf;
+
+foreach (qw(ss stateid)) {
+ $opt{$_} = $cust_main->masked($_) unless exists $opt{$_};
+}
+
+#false laziness with ship state
+my $countrydefault = $conf->config('countrydefault') || 'US';
+$cust_main->set($pre.'country', $countrydefault )
+ unless $cust_main->get($pre.'country');
+
+my $statedefault = $conf->config('statedefault')
+ || ($countrydefault eq 'US' ? 'CA' : '');
+$cust_main->set($pre.'state', $statedefault )
+ unless $cust_main->get($pre.'state')
+ || $cust_main->get($pre.'country') ne $countrydefault;
+
+$cust_main->set('stateid_state', $cust_main->state )
+ unless $pre || $cust_main->get('stateid_state');
+
+#my($county_html, $state_html, $country_html) =
+# FS::cust_main_county::regionselector( $cust_main->get($pre.'county'),
+# $cust_main->get($pre.'state'),
+# $cust_main->get($pre.'country'),
+# $pre,
+# $onchange,
+# $disabled,
+# );
+
+my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
+ ? 'Day Phone'
+ : FS::Msgcat::_gettext('daytime');
+my $night_label = FS::Msgcat::_gettext('night') =~/^(night)?$/
+ ? 'Night Phone'
+ : FS::Msgcat::_gettext('night') || 'Night Phone';
+my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
+ ? 'Driver&rsquo;s License'
+ : FS::Msgcat::_gettext('stateid') || 'Driver&rsquo;s License';
+my $stateid_state_label = FS::Msgcat::_gettext('stateid_state') =~ /^(stateid_state)?$/
+ ? 'Driver&rsquo;s License State'
+ : FS::Msgcat::_gettext('stateid_state') || 'Driver&rsquo;s License State';
+
+my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+</%init>
diff --git a/httemplate/edit/cust_main/select-domain.html b/httemplate/edit/cust_main/select-domain.html
new file mode 100644
index 000000000..bec1e834c
--- /dev/null
+++ b/httemplate/edit/cust_main/select-domain.html
@@ -0,0 +1,67 @@
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/svc_acct-domains.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_domains' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function selopt(what,value,text,selected) {
+ var optionName = new Option(text, value, false, selected);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $opt{'prefix'} %>pkgpart_svcpart_changed(what,selected) {
+
+ pkgpart_svcpart = what.options[what.selectedIndex].value;
+
+ function <% $opt{'prefix'} %>update_domains(domains) {
+
+ // blank the current domain list
+ for ( var i = what.form.<% $opt{'prefix'} %>domsvc.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>domsvc.options[i] = null;
+
+ // add the new domains
+ var domainArray = eval('(' + domains + ')' );
+ for ( var s = 0; s < domainArray.length; s=s+2 ) {
+ var domainLabel = domainArray[s+1];
+ if ( domainLabel == "" )
+ domainLabel = '(n/a)';
+ selopt(what.form.<% $opt{'prefix'} %>domsvc, domainArray[s], domainLabel, (domainArray[s] == selected) ? true : false);
+ }
+
+ }
+
+ // go get the new domains
+ <% $opt{'prefix'} %>get_domains( pkgpart_svcpart, <% $opt{'prefix'} %>update_domains );
+
+ }
+
+</SCRIPT>
+
+<SELECT NAME="<% $opt{'prefix'} %>pkgpart_svcpart" onchange="<% $opt{'prefix'} %>pkgpart_svcpart_changed(this,0);" >
+ <OPTION VALUE="">(none)
+
+% foreach my $part_pkg ( @part_pkg ) {
+
+ <OPTION VALUE="<% $part_pkg->pkgpart. "_". $part_pkg->svcpart('svc_acct') %>"<% ( $opt{saved_pkgpart} && $part_pkg->pkgpart == $opt{saved_pkgpart} ) ? ' SELECTED' : '' %>><% $part_pkg->pkg. " - ". $part_pkg->comment %>
+
+% }
+
+</SELECT>
+<SCRIPT>
+ pkgpart_svcpart_changed(document.bottomform.pkgpart_svcpart, <% $opt{saved_domsvc} %>);
+</SCRIPT>
+
+<%init>
+my %opt = @_;
+foreach my $opt (qw( svc_part pkgparts saved_pkgpart saved_domsvc prefix)) {
+ $opt{$_} = '' unless exists($opt{$_}) && defined($opt{$_});
+}
+$opt{saved_domsvc} = 0 unless $opt{saved_domsvc};
+my @part_pkg = @{$opt{'pkgparts'}};
+
+</%init>
+
diff --git a/httemplate/edit/cust_main_county-expand.cgi b/httemplate/edit/cust_main_county-expand.cgi
new file mode 100755
index 000000000..d5297ab0a
--- /dev/null
+++ b/httemplate/edit/cust_main_county-expand.cgi
@@ -0,0 +1,50 @@
+<% include('/elements/header-popup.html', "Enter $title") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/cust_main_county-expand.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="taxnum" VALUE="<% $taxnum %>">
+
+<TEXTAREA NAME="expansion" COLS="50" ROWS="16"><% $expansion |h %></TEXTAREA>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Add <% $title %>">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my($taxnum, $expansion);
+my($query) = $cgi->keywords;
+if ( $cgi->param('error') ) {
+ $taxnum = $cgi->param('taxnum');
+ $expansion = $cgi->param('expansion');
+} else {
+ $query =~ /^(\d+)$/
+ or die "Illegal taxnum (query $query)";
+ $taxnum = $1;
+ $expansion = '';
+}
+
+my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum})
+ or die "cust_main_county.taxnum $taxnum not found";
+
+my $title;
+
+die "Can't expand entry!" if $cust_main_county->county;
+
+if ( $cust_main_county->state ) {
+ $title = 'Counties';
+} else {
+ $title = 'States/Provinces';
+}
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/cust_main_county.html b/httemplate/edit/cust_main_county.html
new file mode 100644
index 000000000..5d7f9e62e
--- /dev/null
+++ b/httemplate/edit/cust_main_county.html
@@ -0,0 +1,62 @@
+<% include('elements/edit.html',
+ 'popup' => 1,
+ 'name' => 'Tax rate', #Edit tax rate
+ 'table' => 'cust_main_county',
+ 'labels' => { 'taxnum' => 'Tax',
+ 'country' => 'Country',
+ 'state' => 'State',
+ 'county' => 'County',
+ 'taxclass' => 'Tax class',
+ 'taxname' => 'Tax name',
+ 'tax' => 'Tax rate',
+ 'setuptax' => 'This tax not applicable to setup fees',
+ 'recurtax' => 'This tax not applicable to recurring fees',
+ 'exempt_amount' => 'Monthly exemption per customer ($25 "Texas tax")',
+ },
+ 'fields' => \@fields,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $taxnum;
+if ( $cgi->param('error') ) {
+ $cgi->param('taxnum') =~ /^(\d+)$/
+ or die "no taxnum, but error: ". $cgi->param('error');
+ $taxnum = $1;
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die 'no taxnum';
+ $taxnum = $1;
+}
+
+my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum })
+ or die "unknown taxnum $1";
+
+my @fields = (
+ { field=>'country', type=>'fixed-country', },
+ { field=>'state', type=>'fixed-state', },
+ { field=>'county', type=>'fixed', },
+);
+
+push @fields, { field=>'taxclass', type=>'fixed', }
+ if $conf->exists('enable_taxclasses');
+
+push @fields,
+ 'taxname',
+ { field=>'tax', type=>'percentage', },
+
+ { type=>'tablebreak-tr-title', value=>'Exemptions' },
+ { field=>'setuptax', type=>'checkbox', value=>'Y', },
+ { field=>'recurtax', type=>'checkbox', value=>'Y', },
+ { field=>'exempt_amount', type=>'money', },
+;
+
+</%init>
diff --git a/httemplate/edit/cust_main_note.cgi b/httemplate/edit/cust_main_note.cgi
new file mode 100755
index 000000000..6c6a1a9a0
--- /dev/null
+++ b/httemplate/edit/cust_main_note.cgi
@@ -0,0 +1,45 @@
+<% include('/elements/header-popup.html', "$action Customer Note") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/cust_main_note.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+<INPUT TYPE="hidden" NAME="notenum" VALUE="<% $notenum %>">
+
+
+<BR><BR>
+<TEXTAREA NAME="comment" ROWS="12" COLS="60">
+<% $comment %>
+</TEXTAREA>
+
+<BR><BR>
+<INPUT TYPE="submit" VALUE="<% $notenum ? "Apply Changes" : "Add Note" %>">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $comment;
+my $notenum = '';
+if ( $cgi->param('error') ) {
+ $comment = $cgi->param('comment');
+} elsif ( $cgi->param('notenum') =~ /^(\d+)$/ ) {
+ $notenum = $1;
+ die "illegal query ". $cgi->keywords unless $notenum;
+ my $note = qsearchs('cust_main_note', { 'notenum' => $notenum });
+ die "no such note: ". $notenum unless $note;
+ $comment = $note->comments;
+}
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die "illeagl custnum";
+my $custnum = $1;
+
+my $action = $notenum ? 'Edit' : 'Add';
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right("$action customer note");
+
+</%init>
+
diff --git a/httemplate/edit/cust_pay.cgi b/httemplate/edit/cust_pay.cgi
new file mode 100755
index 000000000..3c2877498
--- /dev/null
+++ b/httemplate/edit/cust_pay.cgi
@@ -0,0 +1,138 @@
+% if ( $link eq 'popup' ) {
+ <% include('/elements/header-popup.html', $title ) %>
+% } else {
+ <% include("/elements/header.html", $title, '') %>
+% }
+
+<% include('/elements/init_calendar.html') %>
+
+<% include('/elements/error.html') %>
+
+% unless ( $link eq 'popup' ) {
+ <% small_custview($custnum, $conf->config('countrydefault')) %>
+% }
+
+<FORM NAME="PaymentForm" ACTION="<% popurl(1) %>process/cust_pay.cgi" METHOD=POST onSubmit="document.PaymentForm.submit.disabled=true">
+<INPUT TYPE="hidden" NAME="link" VALUE="<% $link %>">
+<INPUT TYPE="hidden" NAME="linknum" VALUE="<% $linknum %>">
+<INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
+<INPUT TYPE="hidden" NAME="paybatch" VALUE="<% $paybatch %>">
+
+<BR><BR>
+
+Payment
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD COLSPAN=2>
+ <INPUT TYPE="text" NAME="_date" ID="_date_text" VALUE="<% time2str("%m/%d/%Y %r",$_date) %>">
+ <IMG SRC="../images/calendar.png" ID="_date_button" STYLE="cursor: pointer" TITLE="Select date">
+ </TD>
+</TR>
+
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "_date_text",
+ ifFormat: "%m/%d/%Y",
+ button: "_date_button",
+ align: "BR"
+ });
+</SCRIPT>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#ffffff" ALIGN="right"><% $money_char %></TD>
+ <TD><INPUT TYPE="text" NAME="paid" VALUE="<% $paid %>" SIZE=8 MAXLENGTH=8> by <B><% FS::payby->payname($payby) %></B></TD>
+</TR>
+
+% if ( $payby eq 'BILL' ) {
+ <TR>
+ <TD ALIGN="right">Check #</TD>
+ <TD COLSPAN=2><INPUT TYPE="text" NAME="payinfo" VALUE="<% $payinfo %>" SIZE=10></TD>
+ </TR>
+% }
+
+<TR>
+% if ( $link eq 'custnum' || $link eq 'popup' ) {
+
+ <TD ALIGN="right">Auto-apply<BR>to invoices</TD>
+ <TD COLSPAN=2>
+ <SELECT NAME="apply">
+ <OPTION VALUE="yes" SELECTED>yes
+ <OPTION>no</SELECT>
+ </TD>
+
+% } elsif ( $link eq 'invnum' ) {
+
+ <TD ALIGN="right">Apply to</TD>
+ <TD COLSPAN=2 BGCOLOR="#ffffff">Invoice #<B><% $linknum %></B> only</TD>
+ <INPUT TYPE="hidden" NAME="apply" VALUE="no">
+
+% }
+</TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Post payment">
+
+</FORM>
+
+% if ( $link eq 'popup' ) {
+ </BODY>
+ </HTML>
+% } else {
+ <% include('/elements/footer.html') %>
+% }
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post payment');
+
+my($link, $linknum, $paid, $payby, $payinfo, $_date);
+if ( $cgi->param('error') ) {
+ $link = $cgi->param('link');
+ $linknum = $cgi->param('linknum');
+ $paid = $cgi->param('paid');
+ $payby = $cgi->param('payby');
+ $payinfo = $cgi->param('payinfo');
+ $_date = $cgi->param('_date') ? str2time($cgi->param('_date')) : time;
+} elsif ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $link = $cgi->param('popup') ? 'popup' : 'custnum';
+ $linknum = $1;
+ $paid = '';
+ $payby = $cgi->param('payby') || 'BILL';
+ $payinfo = '';
+ $_date = time;
+} elsif ( $cgi->param('invnum') =~ /^(\d+)$/ ) {
+ $link = 'invnum';
+ $linknum = $1;
+ $paid = '';
+ $payby = $cgi->param('payby') || 'BILL';
+ $payinfo = "";
+ $_date = time;
+} else {
+ die "illegal query ". $cgi->keywords;
+}
+
+my $paybatch = "webui-$_date-$$-". rand() * 2**32;
+
+my $title = 'Post '. FS::payby->payname($payby). ' payment';
+$title .= " against Invoice #$linknum" if $link eq 'invnum';
+
+my $custnum;
+if ( $link eq 'invnum' ) {
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $linknum } )
+ or die "unknown invnum $linknum";
+ $custnum = $cust_bill->custnum;
+} elsif ( $link eq 'custnum' ) {
+ $custnum = $linknum;
+}
+
+</%init>
diff --git a/httemplate/edit/cust_pay_pending.html b/httemplate/edit/cust_pay_pending.html
new file mode 100644
index 000000000..0916a1c0c
--- /dev/null
+++ b/httemplate/edit/cust_pay_pending.html
@@ -0,0 +1,154 @@
+<% include('/elements/header-popup.html', $title ) %>
+
+% if ( $action eq 'delete' ) {
+
+ <CENTER><FONT SIZE="+1"><B>Are you sure you want to delete this pending payment?</B></FONT></CENTER>
+
+% } elsif ( $action eq 'complete' ) {
+
+ <CENTER><FONT SIZE="+1"><B>No response was received from <% $cust_pay_pending->processor || 'the payment gateway' %> for this transaction. Check <% $cust_pay_pending->processor || 'the payment gateway' %>'s reporting and determine if this transaction completed successfully.</B></FONT></CENTER>
+
+% }
+
+<BR>
+
+%#false laziness w/view/cust_pay.html
+<% include('/elements/small_custview.html',
+ $cust_pay_pending->custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #no balance
+ )
+%>
+<BR>
+
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Pending payment#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->paypendingnum %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_pay_pending->_date %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_pay_pending->paid %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Payment method</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->payby_name %> #<% $cust_pay_pending->paymask %></B></TD>
+</TR>
+
+% #if ( $cust_pay_pending->payby =~ /^(CARD|CHEK|LECB)$/ && $cust_pay_pending->paybatch ) {
+
+ <TR>
+ <TD ALIGN="right">Processor</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->processor %></B></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Authorization#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->authorization %></B></TD>
+ </TR>
+
+% if ( $cust_pay_pending->order_number ) {
+ <TR>
+ <TD ALIGN="right">Order#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->order_number %></B></TD>
+ </TR>
+% }
+
+% #}
+
+</TABLE>
+
+<BR>
+
+<FORM NAME = "pendingform"
+ METHOD = "POST"
+ ACTION = "process/cust_pay_pending.html"
+>
+
+<INPUT TYPE="hidden" NAME="paypendingnum" VALUE="<% $paypendingnum %>">
+
+<% itable() %>
+
+% if ( $action eq 'delete' ) {
+
+ <INPUT TYPE="hidden" NAME="action" VALUE="<% $action %>">
+
+ <TR>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, delete payment</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="parent.cClick();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, cancel deletion</BUTTON>
+ </TD>
+ </TR>
+
+% } elsif ( $action eq 'complete' ) {
+
+ <INPUT TYPE="hidden" NAME="action" VALUE="">
+
+ <TR>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'insert_cust_pay'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, transaction completed sucessfully.</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'decline'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was declined</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'delete'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was not received</BUTTON>
+ </TD>
+ </TR>
+
+ <TR><TD COLSPAN=5></TD></TR>
+
+ <TR>
+ <TD COLSPAN=5 ALIGN="center">
+ <BUTTON TYPE="button" onClick="parent.cClick();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->Cancel payment completion; transaction status not yet known</BUTTON>
+ </TD>
+ </TR>
+
+% }
+
+</TABLE>
+
+</FORM>
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Edit customer pending payments');
+
+$cgi->param('action') =~ /^(\w+)$/ or die 'illegal action';
+my $action = $1;
+my $title = ucfirst($action). ' pending payment';
+
+$cgi->param('paypendingnum') =~ /^(\d+)$/ or die 'illegal paypendingnum';
+my $paypendingnum = $1;
+my $cust_pay_pending =
+ qsearchs({
+ 'select' => 'cust_pay_pending.*',
+ 'table' => 'cust_pay_pending',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'paypendingnum' => $paypendingnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ })
+ or die 'unknown paypendingnum';
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/edit/cust_pay_refund.cgi b/httemplate/edit/cust_pay_refund.cgi
new file mode 100755
index 000000000..f82fe36fe
--- /dev/null
+++ b/httemplate/edit/cust_pay_refund.cgi
@@ -0,0 +1,14 @@
+<% include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_pay_refund.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'dst_table' => 'cust_refund',
+ 'dst_thing' => 'refund',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply payment');
+
+</%init>
diff --git a/httemplate/edit/cust_pkg.cgi b/httemplate/edit/cust_pkg.cgi
new file mode 100755
index 000000000..f927e1042
--- /dev/null
+++ b/httemplate/edit/cust_pkg.cgi
@@ -0,0 +1,150 @@
+<% include('/elements/header.html', "Add/Edit Packages", '') %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/cust_pkg.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="action" VALUE="bulk">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+
+%#current packages
+%my @cust_pkg = qsearch('cust_pkg', { 'custnum' => $custnum, 'cancel' => '' } );
+%if (@cust_pkg) {
+
+ Current packages - select to remove (services are moved to a new package below)
+ <TABLE>
+ <TR STYLE="background-color: #cccccc;">
+ <TH COLSPAN="2">Pkg #</TH>
+ <TH>Package description</TH>
+ </TR>
+ <BR><BR>
+%
+%
+% foreach ( sort { $all_pkg{ $a->getfield('pkgpart') }
+% cmp $all_pkg{ $b->getfield('pkgpart') }
+% }
+% @cust_pkg
+% )
+% {
+% my($pkgnum,$pkgpart)=( $_->getfield('pkgnum'), $_->getfield('pkgpart') );
+% my $checked = $remove_pkg{$pkgnum} ? ' CHECKED' : '';
+%
+%
+
+
+ <TR>
+ <TD><INPUT TYPE="checkbox" NAME="remove_pkg" VALUE="<% $pkgnum %>"<% $checked %>></TD>
+ <TD ALIGN="right"><% $pkgnum %>:</TD>
+ <TD><% $all_pkg{$pkgpart} %> - <% $all_comment{$pkgpart} %></TD>
+ </TR>
+% }
+
+
+ </TABLE>
+ <BR><BR>
+% }
+
+
+Order new packages
+<BR><BR>
+%
+%my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum});
+%my $agent = qsearchs('agent',{'agentnum'=> $cust_main->agentnum });
+%
+%my %agent_pkgs = map { ( $_->pkgpart , $all_pkg{$_->pkgpart} ) }
+% qsearch('type_pkgs',{'typenum'=> $agent->typenum });
+%
+%my $count = 0;
+%my $pkgparts = 0;
+%
+
+
+<TABLE>
+ <TR STYLE="background-color: #cccccc;">
+ <TH>Qty.</TH>
+ <TH COLSPAN="2">Package Description</TH>
+ </TR>
+%
+%#foreach my $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {
+%foreach my $pkgpart ( sort { $agent_pkgs{$a} cmp $agent_pkgs{$b} }
+% keys(%agent_pkgs) ) {
+% $pkgparts++;
+% next unless exists $pkg{$pkgpart}; #skip disabled ones
+% #print qq!<TR>! if ( $count == 0 );
+% my $value = $cgi->param("pkg$pkgpart") || 0;
+%
+
+
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="<% "pkg$pkgpart" %>" VALUE="<% $value %>" SIZE="2" MAXLENGTH="2">
+ </TD>
+ <TD ALIGN="right"><% $pkgpart %>:</TD>
+ <TD><% $pkg{$pkgpart} %> - <% $comment{$pkgpart}%></TD>
+ </TR>
+%
+% $count ++ ;
+% #if ( $count == 2 ) {
+% # print qq!</TR>\n! ;
+% # $count = 0;
+% #}
+%}
+%
+
+
+</TABLE>
+% unless ( $pkgparts ) {
+% my $p2 = popurl(2);
+% my $typenum = $agent->typenum;
+% my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } );
+% my $atype = $agent_type->atype;
+%
+
+
+ (No <A HREF="<% $p2 %>browse/part_pkg.cgi">package definitions</A>,
+ or agent type
+ <A HREF="<% $p2 %>edit/agent_type.cgi?<% $typenum %>"><% $atype %></a>
+ is not allowed to purchase any packages.)
+% }
+
+
+<P><INPUT TYPE="submit" VALUE="Order">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages');
+
+my %pkg = ();
+my %comment = ();
+my %all_pkg = ();
+my %all_comment = ();
+#foreach (qsearch('part_pkg', { 'disabled' => '' })) {
+# $pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
+# $comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+#}
+foreach (qsearch('part_pkg', {} )) {
+ $all_pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
+ $all_comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+ next if $_->disabled;
+ $pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
+ $comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+}
+
+my($custnum, %remove_pkg);
+if ( $cgi->param('error') ) {
+ $custnum = $cgi->param('custnum');
+ %remove_pkg = map { $_ => 1 } $cgi->param('remove_pkg');
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $custnum = $1;
+ %remove_pkg = ();
+}
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/cust_pkg_detail.html b/httemplate/edit/cust_pkg_detail.html
new file mode 100644
index 000000000..009ed5c6e
--- /dev/null
+++ b/httemplate/edit/cust_pkg_detail.html
@@ -0,0 +1,142 @@
+<% include("/elements/header-popup.html", $title, '',
+ ( $cgi->param('error') ? '' : 'onload="addRow()"' ),
+ )
+%>
+
+%# <% include('/elements/error.html') %>
+
+<FORM ACTION="process/cust_pkg_detail.html" NAME="DetailForm" ID="DetailForm" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="detailtype" VALUE="<% $detailtype %>">
+
+<TABLE ID="DetailTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=1 STYLE="background-color: #cccccc">
+
+% if ( $curuser->option('show_pkgnum') ) {
+
+ <TR>
+ <TD ALIGN="right">Package #</TD>
+ <TD BGCOLOR="#ffffff"><% $pkgnum %></TD>
+ </TR>
+
+% }
+
+ <TR>
+ <TD ALIGN="right">Package</TD>
+ <TD BGCOLOR="#ffffff"><% $part_pkg->pkg %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Comment</TD>
+ <TD BGCOLOR="#ffffff"><% $part_pkg->comment %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Status</TD>
+ <TD BGCOLOR="#ffffff"><FONT COLOR="#<% $cust_pkg->statuscolor %>"><B><% ucfirst($cust_pkg->status) %></B></FONT></TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2><% ucfirst($name{$detailtype}) %>: </TD>
+ </TR>
+
+% my $row = 0;
+% for ( @details ) {
+
+ <TR>
+ <TD></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="detail<% $row %>" SIZE="60" MAXLENGTH="65" VALUE="<% $_->detail |h %>" rownum="<% $row++ %>" onkeyup = "possiblyAddRow;" >
+ </TD>
+ </TR>
+
+% }
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" ID="submit" NAME="submit" VALUE="<% $title %>">
+
+</FORM>
+
+<SCRIPT TYPE="text/javascript">
+
+ var rownum = <% $row %>;
+
+ function possiblyAddRow() {
+ if ( ( rownum - this.getAttribute('rownum') ) == 1 ) {
+ addRow();
+ }
+ }
+
+ function addRow() {
+
+ var table = document.getElementById('DetailTable');
+ var tablebody = table.getElementsByTagName('tbody').item(0);
+
+ var row = document.createElement('TR');
+
+ var empty_cell = document.createElement('TD');
+ row.appendChild(empty_cell);
+
+ var detail_cell = document.createElement('TD');
+
+ var detail_input = document.createElement('INPUT');
+ detail_input.setAttribute('name', 'detail'+rownum);
+ detail_input.setAttribute('id', 'detail'+rownum);
+ detail_input.setAttribute('size', 60);
+ detail_input.setAttribute('maxLength', 65);
+ detail_input.setAttribute('rownum', rownum);
+ detail_input.onkeyup = possiblyAddRow;
+ detail_cell.appendChild(detail_input);
+
+ row.appendChild(detail_cell);
+
+ tablebody.appendChild(row);
+
+ rownum++;
+
+ }
+
+</SCRIPT>
+
+</BODY>
+</HTML>
+<%init>
+
+my %access_right = (
+ 'I' => 'Edit customer package invoice details',
+ 'C' => 'Edit customer package comments',
+);
+
+my %name = (
+ 'I' => 'invoice details',
+ 'C' => 'package comments',
+);
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+$cgi->param('detailtype') =~ /^(\w)$/ or die 'illegal detailtype';
+my $detailtype = $1;
+
+my $right = $access_right{$detailtype};
+die "access denied"
+ unless $curuser->access_right($right);
+
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'illegal pkgnum';
+my $pkgnum = $1;
+
+my $cust_pkg = qsearchs({
+ 'table' => 'cust_pkg',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'pkgnum' => $pkgnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+my @details = $cust_pkg->cust_pkg_detail($detailtype);
+
+my $title = ( scalar(@details) ? 'Edit ' : 'Add ' ). $name{$detailtype};
+
+</%init>
diff --git a/httemplate/edit/cust_refund.cgi b/httemplate/edit/cust_refund.cgi
new file mode 100755
index 000000000..94c0993d7
--- /dev/null
+++ b/httemplate/edit/cust_refund.cgi
@@ -0,0 +1,165 @@
+% if ( $link eq 'popup' ) {
+ <% include('/elements/header-popup.html', $title ) %>
+% } else {
+ <% include("/elements/header.html", $title, '') %>
+% }
+
+<% include('/elements/error.html') %>
+
+% unless ( $link eq 'popup' ) {
+ <% small_custview($custnum, $conf->config('countrydefault')) %>
+% }
+
+<FORM NAME="RefundForm" ACTION="<% $p1 %>process/cust_refund.cgi" METHOD=POST onSubmit="document.RefundForm.submit.disabled=true">
+<INPUT TYPE="hidden" NAME="popup" VALUE="<% $link %>">
+<INPUT TYPE="hidden" NAME="refundnum" VALUE="">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+<INPUT TYPE="hidden" NAME="paynum" VALUE="<% $paynum %>">
+<INPUT TYPE="hidden" NAME="_date" VALUE="<% $_date %>">
+<INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
+<INPUT TYPE="hidden" NAME="paybatch" VALUE="">
+<INPUT TYPE="hidden" NAME="credited" VALUE="">
+
+<BR>
+
+% if ( $cust_pay ) {
+%
+% #false laziness w/FS/FS/cust_pay.pm
+% my $payby = FS::payby->payname($cust_pay->payby);
+% my $paymask = $cust_pay->paymask;
+% my $paydate = $cust_pay->paydate;
+% if ( $cgi->param('error') ) {
+% $paydate = $cgi->param('exp_year'). '-'. $cgi->param('exp_month'). '-01';
+% $paydate = '' unless ($paydate =~ /^\d{2,4}-\d{1,2}-01$'/);
+% }
+
+ <BR>Payment
+ <% ntable("#cccccc", 2) %>
+
+ <TR>
+ <TD ALIGN="right">Amount</TD><TD BGCOLOR="#ffffff">$<% $cust_pay->paid %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Date</TD><TD BGCOLOR="#ffffff"><% time2str("%D",$cust_pay->_date) %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Method</TD><TD BGCOLOR="#ffffff"><% $payby %> # <% $paymask %></TD>
+ </TR>
+
+% unless ( $paydate ) { # possibly other reasons: i.e. card has since expired
+ <TR>
+ <TD ALIGN="right">Expiration</TD><TD BGCOLOR="#ffffff">
+ <% include( '/elements/select-month_year.html',
+ 'prefix' => 'exp',
+ 'selected_date' => $paydate,
+ 'empty_option' => !$paydate,
+ ) %>
+ </TD>
+ </TR>
+% }
+
+%
+% #false laziness w/FS/FS/cust_main::realtime_refund_bop
+% if ( $cust_pay->paybatch =~ /^(\w+):(\w+)(:(\w+))?$/ ) {
+% my ( $processor, $auth, $order_number ) = ( $1, $2, $4 );
+%
+
+
+ <TR>
+ <TD ALIGN="right">Processor</TD><TD BGCOLOR="#ffffff"><% $processor %></TD>
+ </TR>
+% if ( length($auth) ) {
+
+ <TR>
+ <TD ALIGN="right">Authorization</TD><TD BGCOLOR="#ffffff"><% $auth %></TD>
+ </TR>
+% }
+% if ( length($order_number) ) {
+
+ <TR>
+ <TD ALIGN="right">Order number</TD><TD BGCOLOR="#ffffff"><% $order_number %></TD>
+ </TR>
+% }
+% }
+
+ </TABLE>
+% }
+
+
+<BR>Refund
+<% ntable("#cccccc", 2) %>
+
+ <TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#ffffff"><% time2str("%D",$_date) %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#ffffff">$<INPUT TYPE="text" NAME="refund" VALUE="<% $refund %>" SIZE=8 MAXLENGTH=8> by <B><% FS::payby->payname($payby) %></B></TD>
+ </TR>
+
+% if ( $payby eq 'BILL' ) {
+ <TR>
+ <TD ALIGN="right">Check #</TD>
+ <TD COLSPAN=2><INPUT TYPE="text" NAME="payinfo" VALUE="<% $payinfo %>" SIZE=10></TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="payinfo" VALUE="">
+% }
+
+ <TR>
+ <TD ALIGN="right">Reason</TD>
+ <TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="reason" VALUE="<% $reason %>"></TD>
+ </TR>
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Post refund">
+
+</FORM>
+
+% if ( $link eq 'popup' ) {
+ </BODY>
+ </HTML>
+% } else {
+ <% include('/elements/footer.html') %>
+% }
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Refund payment');
+
+my $conf = new FS::Conf;
+my $custnum = $cgi->param('custnum');
+my $refund = $cgi->param('refund');
+my $payby = $cgi->param('payby');
+my $payinfo = $cgi->param('payinfo');
+my $reason = $cgi->param('reason');
+my $link = $cgi->param('popup') ? 'popup' : '';
+
+my( $paynum, $cust_pay ) = ( '', '' );
+if ( $cgi->param('paynum') =~ /^(\d+)$/ ) {
+ $paynum = $1;
+ $cust_pay = qsearchs('cust_pay', { paynum=>$paynum } )
+ or die "unknown payment # $paynum";
+ $refund ||= $cust_pay->unrefunded;
+ if ( $custnum ) {
+ die "payment # $paynum is not for specified customer # $custnum"
+ unless $custnum == $cust_pay->custnum;
+ } else {
+ $custnum = $cust_pay->custnum;
+ }
+}
+die "no custnum or paynum specified!" unless $custnum;
+
+my $_date = time;
+
+my $p1 = popurl(1);
+
+my $title = 'Refund '. FS::payby->payname($payby). ' payment';
+
+</%init>
diff --git a/httemplate/edit/elements/ApplicationCommon.html b/httemplate/edit/elements/ApplicationCommon.html
new file mode 100644
index 000000000..a485d37de
--- /dev/null
+++ b/httemplate/edit/elements/ApplicationCommon.html
@@ -0,0 +1,177 @@
+<%doc>
+
+Examples:
+
+ #cust_bill_pay
+ include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_bill_pay.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'dst_table' => 'cust_bill',
+ 'dst_thing' => 'invoice',
+ )
+
+ #cust_credit_bill
+ include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_credit_bill.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'dst_table' => 'cust_bill',
+ 'dst_thing' => 'invoice',
+ )
+
+ #cust_pay_refund
+ include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_pay_refund.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'dst_table' => 'cust_refund',
+ 'dst_thing' => 'refund',
+ )
+
+ #cust_credit_refund
+ include('elements/ApplicationCommon.html',
+ 'form_action' => 'process/cust_credit_refund.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'dst_table' => 'cust_refund',
+ 'dst_thing' => 'refund',
+ )
+
+</%doc>
+<% include('/elements/header-popup.html', "Apply $src_thing$to" ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1. $opt{'form_action'} %>" NAME="ApplicationForm" ID="ApplicationForm" METHOD=POST>
+
+<% $src_thing %> #<B><% $src_pkeyvalue %></B><BR>
+<INPUT TYPE="hidden" NAME="<% $src_pkey %>" VALUE="<% $src_pkeyvalue %>">
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+<TR>
+ <TD ALIGN="right">Date: </TD>
+ <TD><B><% time2str("%D", $src->_date) %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount: </TD>
+ <TD><B><% $money_char %><% $src->amount %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Unapplied amount: </TD>
+ <TD><B><% $money_char %><% $unapplied %></B></TD>
+</TR>
+
+% if ( $src_table eq 'cust_credit' ) {
+ <TR>
+ <TD ALIGN="right">Reason: </TD>
+ <TD><B><% $src->reason %></B></TD>
+ </TR>
+% }
+
+</TABLE>
+<BR>
+
+<SCRIPT TYPE="text/javascript">
+function changed(what) {
+ dst = what.options[what.selectedIndex].value;
+
+ if ( dst == '' ) {
+ what.form.submit.disabled=true;
+ return true;
+ }
+
+ what.form.submit.disabled=false;
+
+% foreach my $dst ( @dst ) {
+
+ if ( dst == <% $dst->$dst_pkey %> ) {
+ what.form.amount.value = "<% min($dst->$dst_unapplied, $unapplied) %>";
+ }
+
+% }
+
+}
+</SCRIPT>
+
+Apply to:
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+<TR>
+ <TD ALIGN="right"><% $dst_thing %>: </TD>
+ <TD><SELECT NAME="<% $dst_pkey %>" SIZE=1 onChange="changed(this)">
+<OPTION VALUE="">Select <% $dst_thing %>
+
+% foreach my $dst ( @dst ) {
+ <OPTION<% $dst->$dst_pkey eq $dst_pkeyvalue ? ' SELECTED' : '' %> VALUE="<% $dst->$dst_pkey %>">#<% $dst->$dst_pkey %> - <% time2str("%D", $dst->_date) %> - $<% $dst->$dst_unapplied %>
+% }
+
+</SELECT>
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount: </TD>
+ <TD><% $money_char %><INPUT TYPE="text" NAME="amount" VALUE="<% $amount %>" SIZE=8 MAXLENGTH=8></TD>
+</TR>
+
+</TABLE>
+
+<BR>
+<CENTER><INPUT TYPE="submit" VALUE="Apply" NAME="submit" ID="submit" DISABLED></CENTER>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+my %opt = @_;
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $src_thing = ucfirst($opt{'src_thing'});
+my $src_table = $opt{'src_table'};
+my $src_pkey = dbdef->table($src_table)->primary_key;
+
+my $dst_thing = ucfirst($opt{'dst_thing'});
+my $dst_table = $opt{'dst_table'};
+my $dst_pkey = dbdef->table($dst_table)->primary_key;
+my $dst_unapplied = $dst_table eq 'cust_bill' ? 'owed' : 'unapplied';
+
+my $to = $dst_table eq 'cust_refund' ? ' to Refund' : '';
+
+my($src_pkeyvalue, $amount, $dst_pkeyvalue);
+if ( $cgi->param('error') ) {
+ $src_pkeyvalue = $cgi->param($src_pkey);
+ $amount = $cgi->param('amount');
+ $dst_pkeyvalue = $cgi->param($dst_pkey);
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $src_pkeyvalue = $1;
+ $amount = '';
+ $dst_pkeyvalue = '';
+}
+
+my $otaker = getotaker;
+
+my $p1 = popurl(1);
+
+my $src = qsearchs($src_table, { $src_pkey => $src_pkeyvalue } );
+die "$src_thing $src_pkeyvalue not found!" unless $src;
+
+my $unapplied = $src->unapplied;
+
+my @dst = sort { $a->_date <=> $b->_date
+ or $a->$dst_pkey <=> $b->$dst_pkey
+ }
+ grep { $_->$dst_unapplied != 0 }
+ qsearch($dst_table, { 'custnum' => $src->custnum } );
+
+</%init>
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
new file mode 100644
index 000000000..d18a37d5a
--- /dev/null
+++ b/httemplate/edit/elements/edit.html
@@ -0,0 +1,700 @@
+<%doc>
+
+Example:
+
+ include( 'elements/edit.html',
+ 'name_singular' => #singular name for the record
+ # (preferred, will be pluralized automatically)
+ 'name' => #name for the record
+ # (deprecated, will be pluralized simplistically)
+ 'table' =>
+
+ #? 'primary_key' => #required when the dbdef doesn't know...???
+ 'labels' => {
+ 'column' => 'Label',
+ }
+
+ #listref - each item is a literal column name (or method) or hashref
+ # or (notyet) coderef
+ #if not specified all columns (except for the primary key) will be editable
+ 'fields' => [
+ 'columname',
+ { 'field' => 'another_columname',
+ 'type' => 'text', #text
+ #password
+ #money
+ #percentage
+ #checkbox
+ #select
+ #selectlayers (can now use after a tablebreak-tr-title... but not inside columnstart/columnnext/columnend)
+ #title
+ #tablebreak-tr-title
+ #columnstart
+ #columnnext
+ #columnend
+ #hidden - hidden value from object
+ #fixed - display fixed value from object or here
+ #fixed-country
+ #fixed-state
+ 'value' => 'Y', #for checkbox, title, fixed, hidden
+ 'disabled' => 0,
+ 'onchange' => 'javascript_function',
+
+ #m2 stuff only tested w/selectlayers so far
+ #might work w/select too, dunno others
+ 'm2name_table' => 'table_name',
+ 'm2name_namecol' => 'name_column',
+ #OR#
+ 'm2m_method' =>
+ #'m2m_srccol' => #opt, if not the same as this table
+ 'm2m_dstcol' => #required for now, eventuaully opt, if not the same as target table
+
+ 'm2_label' => 'Label', #
+ 'm2_new_default' => \@table_name_objects, #default
+ #m2 objects for
+ #new records
+ 'm2_error_callback' => sub { my($cgi, $object) = @_; },
+ 'm2_remove_warnings' => \%warnings, #hashref of warning
+ #messages for m2
+ #removal
+ 'm2_new_js' => 'function_name', #javascript function called
+ #on spawned rows (one arg:
+ #new_element)
+ 'm2_remove_js' => 'function_name', #js function called when
+ #a row is deleted (three
+ #args: value, text,
+ #'no_match')
+ #layer_fields & layer_values_callback only for selectlayer
+ 'layer_fields' => [
+ 'fieldname' => 'Label',
+ 'another_field' => {
+ label=>'Label',
+ type =>'text', #text, money
+ },
+ ],
+ 'layer_values_callback' =>
+ sub {
+ my( $cgi, $object ) = @_;
+ { 'layer' => { 'fieldname' => 'current_value',
+ 'fieldname2' => 'field2value',
+ ...
+ },
+ 'layer2' => { 'l2fieldname' => 'l2value',
+ ...
+ },
+ ...
+ };
+ },
+ },
+ ]
+
+ 'menubar' => '', #menubar arrayref
+
+ #agent virtualization
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Access Right Name',
+ 'agent_clone_extra_sql' => '', #if provided, this overrides the extra_sql
+ #implementing agent virt, for clone
+ #operations. i.e. pass "1=1" to allow
+ #cloning anything
+
+ 'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
+
+ # overrides default popurl(1)."process/$table.html"
+ 'post_url' => popurl(1).'process/something',
+
+ #we're in a popup (no title/menu/searchboxes)
+ 'popup' => 1,
+
+ ###
+ # HTML callbacks
+ ###
+
+ 'body_etc' => '', # Additional BODY attributes, i.e. onLoad=""
+
+ 'html_init' => '', #after the header/menubar
+
+ #string or coderef of additional HTML to add before </TABLE>
+ 'html_table_bottom' => '',
+
+ #after </TABLE> but before the submit
+ 'html_bottom' => '', #string
+ 'html_bottom' => sub {
+ my $object = shift;
+ # ...
+ "html_string";
+ },
+
+ #at the very bottom (well, as low as you can go from here)
+ 'html_foot' => '',
+
+ ###
+ # initialization callbacks
+ ###
+
+ ###global callbacks
+
+ #always run if provided, after decoding long CGI "redirect=" responses but
+ # before object creation/search
+ # (useful if you have a long form that might trigger redirect= and you need
+ # to do things with $cgi params - they're not decoded in the calling
+ # <%init> block yet)
+ 'begin_callback' = sub { my( $cgi, $fields_listref, $opt_hashref ) = @_; },
+
+ #always run, after the mode-specific object creation/search
+ 'end_callback' = sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
+ ###mode-specific callbacks
+
+ #run when re-displaying with an error
+ 'error_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
+ #run when editing
+ 'edit_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; },
+
+ # returns a hashref for the new object
+ 'new_hashref_callback'
+
+ # returns the new object iself (otherwise, ->new is called)
+ 'new_object_callback'
+
+ #run when adding
+ 'new_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; },
+
+ #run when cloning
+ 'clone_callback' => sub { my( $cgi, $object, $fields_listref, $opt_hashref ) = @_; },
+
+ ###display callbacks
+
+ #run before display to return a different value
+ 'value_callback' => sub { my( $columname, $value ) = @_; },
+
+ #run before display to manipulate element of the 'fields' arrayref
+ 'field_callback' => sub { my( $cgi, $object, $field_hashref ) = @_; },
+
+ );
+
+</%doc>
+
+<% include('/elements/header'. ( $opt{popup} ? '-popup' : '' ). '.html',
+ $title,
+ include( '/elements/menubar.html', @menubar ),
+ $opt{'body_etc'},
+ )
+%>
+
+<% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+%>
+
+<% include('/elements/error.html') %>
+
+% my $url = $opt{'post_url'} || popurl(1)."process/$table.html";
+
+<FORM ACTION="<% $url %>" METHOD=POST NAME="edit_topform">
+
+<INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>">
+<INPUT TYPE="hidden" NAME="<% $pkey %>" VALUE="<% $clone ? '' : $object->$pkey() %>">
+
+<FONT SIZE="+1"><B>
+<% ( $opt{labels} && exists $opt{labels}->{$pkey} )
+ ? $opt{labels}->{$pkey}
+ : $pkey
+%>
+</B></FONT>
+#<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+
+% my $tablenum = 0;
+<TABLE ID="TableNumber<% $tablenum++ %>" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+% my $g_row = 0;
+% my @g_row_stack = ();
+% foreach my $f ( map { ref($_) ? $_ : {'field'=>$_} }
+% @$fields
+% ) {
+%
+% my $trash = &{ $opt{'field_callback'} }( $cgi, $object, $f )
+% if $opt{'field_callback'};
+%
+% my $field = $f->{'field'};
+% my $type = $f->{'type'} ||= 'text';
+%
+% my $label = ( $opt{labels} && exists $opt{labels}->{$field} )
+% ? $opt{labels}->{$field}
+% : $field;
+%
+% my $onchange = $f->{'onchange'};
+%
+% my $layer_values = {};
+% $layer_values = &{ $f->{'layer_values_callback'} }( $cgi, $object )
+% if $f->{'layer_values_callback'}
+% && ! $f->{'m2name_table'}
+% && ! $f->{'m2m_method'};
+%
+% warn "layer values: ". Dumper($layer_values)
+% if $opt{'debug'};
+%
+% my %include_common = (
+%
+% #text and derivitives
+% 'size' => $f->{'size'},
+% 'maxlength' => $f->{'maxlength'},
+%
+% #checkbox, title, fixed, hidden
+% #& deprecated weird value hashref used only by reason.html
+% 'value' => $f->{'value'},
+%
+% #select(-*)
+% 'options' => $f->{'options'},
+% 'labels' => $f->{'labels'},
+% 'multiple' => $f->{'multiple'},
+% 'disable_empty' => $f->{'disable_empty'},
+% #select-reason
+% 'reason_class' => $f->{'reason_class'},
+%
+% #selectlayers
+% 'layer_fields' => $f->{'layer_fields'},
+% 'layer_values' => $layer_values,
+% 'html_between' => $f->{'html_between'},
+%
+% #umm. for select-agent_types at least
+% 'disabled' => $f->{'disabled'},
+% );
+%
+% #selectlayers, others?
+% $include_common{$_} = $f->{$_}
+% foreach grep exists($f->{$_}),
+% qw( js_only html_only select_only layers_only cell_style);
+%
+% #select-*
+% $include_common{$_} = $f->{$_}
+% foreach grep exists($f->{$_}), qw( empty_label );
+%
+% #select-table, checkboxes-table
+% $include_common{$_} = $f->{$_}
+% foreach grep exists($f->{$_}), qw( table name_col );
+%
+% #checkboxes-table
+% $include_common{$_} = $f->{$_}
+% foreach grep exists($f->{$_}), qw( target_table link_table );
+%
+% #*-table
+% $include_common{$_} = $f->{$_}
+% foreach grep exists($f->{$_}), qw( hashref agent_virt agent_null_right );
+%
+% if ( $type eq 'tablebreak-tr-title' ) {
+% $include_common{'table_id'} = 'TableNumber'. $tablenum++
+% }
+%
+% my $layer_prefix_on = '';
+%
+% my $include_sub = sub {
+% my %opt = @_;
+%
+% my $fieldnum = delete $opt{'fieldnum'};
+%
+% my $include = $type;
+% $include = "input-$include" if $include =~ /^(text|money|percentage)$/;
+% $include = "tr-$include" unless $include =~ /^(hidden|tablebreak|column)/;
+%
+% $include_common{'layer_prefix'} = "$field$fieldnum."
+% if $layer_prefix_on;
+%
+% my @include =
+% ( "/elements/$include.html",
+% 'field' => "$field$fieldnum",
+% 'id' => "$field$fieldnum", #separate?
+% 'label_id' => $field."_label$fieldnum", #don't want field0_label0...
+% %include_common,
+% %opt,
+% );
+% @include;
+% };
+%
+% unless ( $type =~ /^column/ ) {
+% $g_row = 1 if $type eq 'tablebreak-tr-title';
+% $g_row++;
+% $g_row++ if $type eq 'title';
+% } else {
+% if ( $type eq 'columnstart' ) {
+% push @g_row_stack, $g_row;
+% $g_row = 0;
+% #} elsif ( $type eq 'columnnext' ) {
+% } elsif ( $type eq 'columnend' ) {
+% $g_row = pop @g_row_stack;
+% }
+%
+% }
+%
+% my $fieldnum = '';
+% my $curr_value = '';
+% if ( $f->{'m2name_table'} || $f->{'m2m_method'} ) { #XXX test this for all
+% #types of fields
+% my($table, $col);
+% if ( $f->{'m2name_table'} ) {
+% $table = $f->{'m2name_table'};
+% $col = $f->{'m2name_namecol'};
+% } elsif ( $f->{'m2m_method'} ) {
+% $table = $f->{'m2m_method'};
+% $col = $f->{'m2m_dstcol'};
+% }
+% $fieldnum = 0;
+% $layer_prefix_on = 1;
+% #print out the fields for the existing m2s
+% my @existing = ();
+% if ( $mode eq 'error' ) {
+% @existing = &{ $f->{'m2_error_callback'} }( $cgi, $object );
+% } elsif ( $object->$pkey() ) { # $mode eq 'edit'||'clone'
+% @existing = $object->$table();
+% warn scalar(@existing). " from $object->$table: ". join('/', @existing)
+% if $opt{'debug'};
+% } elsif ( $f->{'m2_new_default'} ) { # && $mode eq 'new'
+% @existing = @{ $f->{'m2_new_default'} };
+% }
+% foreach my $name_obj ( @existing ) {
+%
+% my $ex_label = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this '.
+% lc($f->{'m2_label'}).
+% qq(" onClick="remove_$field($fieldnum);").
+% ' STYLE="color:#ff0000;font-weight:bold;'.
+% 'padding-left:2px;padding-right:2px"'.
+% '>&nbsp;'. ($f->{'m2_label'} || $field ). ' ';
+%
+% if ( $f->{'layer_values_callback'} ) {
+% my %switches = ( 'mode' => $mode );
+% $layer_values =
+% &{ $f->{'layer_values_callback'} }( $cgi, $name_obj, \%switches );
+% }
+% warn "layer values: ". Dumper($layer_values)
+% if $opt{'debug'};
+%
+% my @existing = &{ $include_sub }(
+% 'label' => $ex_label,
+% 'fieldnum' => $fieldnum,
+% 'curr_value' => $name_obj->$col(),
+% 'onchange' => $onchange,
+% 'layer_values' => $layer_values,
+% 'cell_style' => ( $fieldnum ? 'border-top:1px solid black' : '' ),
+% );
+
+ <% include( @existing ) %>
+
+% $fieldnum++;
+% $g_row++;
+% }
+% #$field .= $fieldnum;
+% $onchange .= "\nspawn_$field(what);";
+% } else {
+% if ( $f->{curr_value_callback} ) {
+% $curr_value = &{ $f->{curr_value_callback} }( $cgi, $object, $field ),
+% } else {
+% $curr_value = $object->$field();
+% }
+% $curr_value = &{ $opt{'value_callback'} }( $f->{'field'}, $curr_value )
+% if $opt{'value_callback'} && $mode ne 'error';
+% }
+%
+% my @include = &{ $include_sub }(
+% 'label' => $label,
+% 'fieldnum' => $fieldnum,
+% 'curr_value' => $curr_value,
+% 'object' => $object,
+% 'cgi' => $cgi,
+% 'onchange' => $onchange,
+% ( $fieldnum ? ('cell_style' => 'border-top:1px solid black') : () ),
+% );
+
+ <% include( @include ) %>
+
+% if ( $f->{'m2name_table'} || $f->{'m2m_method'} ) {
+
+ <SCRIPT TYPE="text/javascript">
+
+ var <%$field%>_rownum = <% $g_row %>;
+ var <%$field%>_fieldnum = <% $fieldnum %>;
+
+ function spawn_<%$field%>(what) {
+
+ // only spawn if we're the last element... return if not
+
+ var field_regex = /(\d+)$/;
+ var match = field_regex.exec(what.name);
+ if ( !match ) {
+ alert(what.name + " didn't match?!");
+ return;
+ }
+ if ( match[1] != <%$field%>_fieldnum ) {
+ return;
+ }
+
+ // change the label on the last entry & add a remove button
+ var prev_label = document.getElementById('<% $field %>_label' + <%$field%>_fieldnum );
+ prev_label.innerHTML = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this <% lc($f->{'m2_label'}) %>" onClick="remove_<% $field %>(' + <%$field%>_fieldnum + ');" STYLE="color:#ff0000;font-weight:bold;padding-left:2px;padding-right:2px" >&nbsp;<% $f->{'m2_label'} || $field %>';
+
+ <%$field%>_fieldnum++;
+
+ //get the new widget
+
+% $include[0] =~ s(^/elements/tr-)(/elements/);
+% my @layer_opt = ( @include,
+% 'field' => $field."MAGIC_NUMBER",
+% 'id' => $field."MAGIC_NUMBER",
+% 'layer_prefix' => $field."MAGIC_NUMBER.",
+% );
+% warn @layer_opt if $opt{'debug'};
+
+ var newrow = <% include(@layer_opt, html_only=>1) |js_string %>;
+
+% if ( $type eq 'selectlayers' ) { #until the rest have html/js_only
+ var newfunc = <% include(@layer_opt, js_only =>1) |js_string %>;
+% } else {
+ var newfunc = '';
+% }
+
+ // substitute in the new field name
+ var magic_regex = /MAGIC_NUMBER/g;
+ newrow = newrow.replace( magic_regex, <%$field%>_fieldnum );
+ newfunc = newfunc.replace( magic_regex, <%$field%>_fieldnum );
+
+ // evaluate new_func
+ if (window.ActiveXObject) {
+ window.execScript(newfunc);
+ } else { /* (window.XMLHttpRequest) */
+ //window.eval(newfunc);
+ setTimeout(newfunc, 0);
+ }
+
+ // add new row
+
+ //hmm, can't use selectlayers after a tablebreak-title for now
+ var table = document.getElementById('TableNumber<% $tablenum-1 %>');
+
+ var row = table.insertRow(<%$field%>_rownum++);
+
+ var label_cell = document.createElement('TD');
+
+ label_cell.id = '<% $field %>_label' + <%$field%>_fieldnum;
+
+ label_cell.style.textAlign = "right";
+ label_cell.style.verticalAlign = "top";
+ label_cell.style.borderTop = "1px solid black";
+ label_cell.style.paddingTop = "5px";
+
+ label_cell.innerHTML = '<% $label %>';
+
+ row.appendChild(label_cell);
+
+ var widget_cell = document.createElement('TD');
+
+ widget_cell.style.borderTop = "1px solid black";
+ widget_cell.style.paddingTop = "3px";
+
+ widget_cell.innerHTML = newrow;
+
+ row.appendChild(widget_cell);
+
+% if ( $f->{'m2_new_js'} ) {
+ // take out items selected in previous dropdowns
+ var new_element = document.getElementById("<%$field%>" + <%$field%>_fieldnum );
+ <% $f->{'m2_new_js'} %>(new_element);
+
+ if ( new_element.length < 2 ) {
+ //just the ** Select new **, so don't display the row
+ row.style.display = 'none';
+ }
+% }
+
+ }
+
+ function remove_<%$field%>(remove_fieldnum) {
+ //alert("remove <%$field%> " + remove_fieldnum);
+ var select = document.getElementById('<%$field%>' + remove_fieldnum);
+
+ if ( ! select ) {
+ alert("can't find element <%$field%>" + remove_fieldnum);
+ return;
+ }
+
+% my $warnings = $f->{'m2_remove_warnings'};
+% if ( $warnings ) {
+ var sel_value = select.options[select.selectedIndex].value;
+% foreach my $value ( keys %$warnings ) {
+ if ( sel_value == '<% $value %>' ) {
+ if ( ! confirm( <% $warnings->{$value} |js_string %> ) ) {
+ return;
+ }
+ }
+% }
+% }
+
+ select.disabled = 'disabled'; // this seems to prevent it from being submitted on tested browsers so far (IE, moz, konq at least)
+ var label_td = document.getElementById('<%$field%>_label' + remove_fieldnum );
+ label_td.parentNode.style.display = 'none';
+
+% if ( $f->{m2_remove_js} ) {
+ var opt = select.options[select.selectedIndex];
+ <% $f->{m2_remove_js} %>( opt.value, opt.text, 'no_match');
+% }
+
+ }
+
+ </SCRIPT>
+
+% }
+
+% }
+
+<% ref( $opt{'html_table_bottom'} )
+ ? &{ $opt{'html_table_bottom'} }( $object )
+ : $opt{'html_table_bottom'}
+%>
+
+</TABLE>
+
+<% ref( $opt{'html_bottom'} )
+ ? &{ $opt{'html_bottom'} }( $object )
+ : $opt{'html_bottom'}
+%>
+
+<BR>
+
+<INPUT TYPE="submit" ID="submit" VALUE="<% ( !$clone && $object->$pkey() ) ? "Apply changes" : "Add $opt{'name'}" %>">
+
+</FORM>
+
+<% ref( $opt{'html_foot'} )
+ ? &{ $opt{'html_foot'} }( $object )
+ : $opt{'html_foot'}
+%>
+
+<% include("/elements/footer.html") %>
+<%init>
+
+my(%opt) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+#false laziness w/process.html
+my $table = $opt{'table'};
+my $class = "FS::$table";
+my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} ||
+my $fields = $opt{'fields'}
+ #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ];
+ || [ grep { $_ ne $pkey } fields($table) ];
+#my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields;
+
+if ( $cgi->param('redirect') ) {
+ my $session = $cgi->param('redirect');
+ my $pref = $curuser->option("redirect$session");
+ die "unknown redirect session $session\n" unless length($pref);
+ $cgi = new CGI($pref);
+}
+
+&{$opt{'begin_callback'}}( $cgi, $fields, \%opt )
+ if $opt{'begin_callback'};
+
+my %qsearch = (
+ 'table' => $table,
+ 'extra_sql' => ( $opt{'agent_virt'}
+ ? ' AND '. $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ )
+ : ''
+ ),
+);
+
+my $mode;
+my $object;
+my $clone = '';
+if ( $cgi->param('error') ) {
+
+ $mode = 'error';
+
+ $object = $class->new( {
+ map { $_ => scalar($cgi->param($_)) } fields($table)
+ });
+
+ &{$opt{'error_callback'}}($cgi, $object, $fields, \%opt )
+ if $opt{'error_callback'};
+
+} elsif ( $cgi->param('clone') =~ /^(\d+)$/ ) {
+
+ $mode = 'clone';
+
+ $clone = $1;
+
+ $qsearch{'extra_sql'} = ' AND '. $opt{'agent_clone_extra_sql'}
+ if $opt{'agent_clone_extra_sql'};
+
+ $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } });
+
+ &{$opt{'clone_callback'}}($cgi, $object, $fields, \%opt )
+ if $opt{'clone_callback'};
+
+ #$object->$pkey('');
+
+ $opt{action} ||= 'Add';
+
+} elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing
+
+ $mode = 'edit';
+
+ my $value;
+ if ( $cgi->param($pkey) ) {
+ $value = $cgi->param($pkey)
+ } else {
+ my( $query ) = $cgi->keywords;
+ $value = $query;
+ }
+ $value =~ /^(\d+)$/ or die "unparsable $pkey";
+ $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $1 } })
+ or die "$pkey $1 not found in $table";
+
+ warn "$table $pkey => $1"
+ if $opt{'debug'};
+
+ &{$opt{'edit_callback'}}($cgi, $object, $fields)
+ if $opt{'edit_callback'};
+
+} else { #adding
+
+ $mode = 'new';
+
+ my $hashref = $opt{'new_hashref_callback'}
+ ? &{$opt{'new_hashref_callback'}}
+ : {};
+
+ $object = $opt{'new_object_callback'}
+ ? &{$opt{'new_object_callback'}}( $cgi, $hashref, $fields, \%opt )
+ : $class->new( $hashref );
+
+ &{$opt{'new_callback'}}($cgi, $object, $fields)
+ if $opt{'new_callback'};
+
+}
+
+&{$opt{'end_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'end_callback'};
+
+$opt{action} ||= $object->$pkey() ? 'Edit' : 'Add';
+
+my $title = $opt{action}. ' '. $opt{name};
+
+my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html";
+$viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'};
+
+my @menubar = ();
+if ( $opt{'menubar'} ) {
+ @menubar = @{ $opt{'menubar'} };
+} else {
+ my $items = $opt{'name'} ? $opt{'name'}.'s' : PL($opt{'name_singular'});
+ @menubar = (
+ "View all $items" => $viewall_url,
+ );
+}
+
+</%init>
diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html
new file mode 100644
index 000000000..0b64120fb
--- /dev/null
+++ b/httemplate/edit/elements/svc_Common.html
@@ -0,0 +1,122 @@
+<% include( 'edit.html',
+
+ 'menubar' => [],
+
+ 'error_callback' => sub {
+ my( $cgi, $svc_x ) = @_;
+ #$svcnum = $svc_x->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+
+ $part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart });
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_x->setfield('svcpart', $svcpart);
+ },
+
+ 'edit_callback' => sub {
+ my( $cgi, $svc_x ) = @_;
+ #$svcnum = $svc_x->svcnum;
+ my $cust_svc = $svc_x->cust_svc
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum = $cust_svc->pkgnum;
+ $svcpart = $cust_svc->svcpart;
+
+ $part_svc = qsearchs ('part_svc', { svcpart=>$svcpart });
+ die "No part_svc entry!" unless $part_svc;
+ },
+
+ 'new_hashref_callback' => sub {
+ #my( $cgi, $svc_x ) = @_;
+
+ { svcpart => $svcpart };
+
+ },
+
+ 'new_callback' => sub {
+ my( $cgi, $svc_x ) = @_;;
+
+ $part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart });
+ die "No part_svc entry!" unless $part_svc;
+
+ #$svcnum='';
+
+ $svc_x->set_default_and_fixed;
+
+ },
+
+ 'field_callback' => sub {
+ my ($cgi, $object, $f) = @_;
+ my $columndef = $part_svc->part_svc_column($f->{'field'});
+ my $flag = $columndef->columnflag;
+ if ( $flag eq 'F' ) {
+ $f->{'type'} = length($columndef->columnvalue)
+ ? 'fixed'
+ : 'hidden';
+ $f->{'value'} = $columndef->columnvalue;
+ }
+ },
+
+ 'html_init' => sub {
+ my $cust_main;
+ if ( $pkgnum ) {
+ my $cust_pkg = qsearchs('cust_pkg', {'pkgnum' => $pkgnum});
+ $cust_main = $cust_pkg->cust_main if $cust_pkg;
+ }
+ $cust_main
+ ? include( '/elements/small_custview.html',
+ $cust_main,
+ '',
+ 1,
+ popurl(2). "view/cust_main.cgi"
+ ). '<BR>'
+ : '';
+
+ },
+
+ 'html_table_bottom' => sub {
+ my $svc_x = shift;
+ my $html = '';
+ foreach my $field ($svc_x->virtual_fields) {
+ if ($part_svc->part_svc_column($field)->columnflag ne 'F'){
+ # If the flag is X, it won't even show up
+ # in $svc_acct->virtual_fields.
+ $html .=
+ $svc_x->pvf($field)->widget( 'HTML',
+ 'edit',
+ $svc_x->getfield($field)
+ );
+ }
+ }
+ $html;
+ },
+
+ 'html_bottom' => sub {
+ qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!.
+ qq!<INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart">!;
+ },
+
+ %opt #pass through/override params
+ )
+%>
+<%init>
+
+my %opt = @_;
+
+#my( $svcnum, $pkgnum, $svcpart, $part_svc );
+my( $pkgnum, $svcpart, $part_svc );
+
+#get & untaint pkgnum & svcpart
+if ( ! $cgi->param('error')
+ && $cgi->param('pkgnum') && $cgi->param('svcpart')
+ )
+{
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+ #$cgi->delete_all(); #so edit.html treats this correctly as new??
+}
+
+</%init>
diff --git a/httemplate/edit/inventory_class.html b/httemplate/edit/inventory_class.html
new file mode 100644
index 000000000..3ab47fe28
--- /dev/null
+++ b/httemplate/edit/inventory_class.html
@@ -0,0 +1,16 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Inventory Class',
+ 'table' => 'inventory_class',
+ 'labels' => {
+ 'classnum' => 'Class number',
+ 'classname' => 'Class name',
+ },
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/invoice_logo.html b/httemplate/edit/invoice_logo.html
new file mode 100644
index 000000000..e1c61496f
--- /dev/null
+++ b/httemplate/edit/invoice_logo.html
@@ -0,0 +1,136 @@
+<% include("/elements/header.html", "Edit $type2desc{$type} invoice logo",
+ menubar(
+ 'View all invoice templates' => $p.'browse/invoice_template.html'
+ )
+ )
+%>
+
+% if ( $error ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error %></FONT>
+ <BR><BR>
+% }
+
+% if ( $cgi->param('msg') ) {
+ <FONT SIZE="+1"><B><% $cgi->param('msg') |h %></B></FONT>
+ <BR><BR>
+% }
+
+% if ( $mode eq 'upload' ) {
+ <FORM ACTION="invoice_logo.html" METHOD="POST" ENCTYPE="multipart/form-data">
+ <INPUT TYPE="hidden" NAME="mode" VALUE="preview">
+% } elsif ( $mode eq 'preview' ) {
+ <FORM ACTION="process/invoice_logo.html" METHOD="POST">
+ <INPUT TYPE="hidden" NAME="preview_session" VALUE="<% $session %>">
+% }
+
+<INPUT TYPE="hidden" NAME="type" VALUE="<% $type %>">
+<INPUT TYPE="hidden" NAME="name" VALUE="<% $name %>">
+
+<% include('/elements/table-grid.html') %>
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Current logo</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">New logo preview</TH>
+</TR>
+
+<TR>
+
+ <TD CLASS="grid" BGCOLOR="#ffffff">
+
+% if ( $type eq 'png' ) {
+
+ <IMG SRC="<% $p %>view/logo.cgi?type=png;name=<% $name %>">
+
+% } elsif ( $type eq 'eps' ) {
+
+ <i>EPS preview not yet supported</i>
+
+% }
+
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="#ffffff">
+
+% if ( $mode eq 'upload' ) {
+
+ Upload new logo (.<%uc($type)%> format): <INPUT TYPE="file" NAME="new_logo">
+ <BR><INPUT TYPE="submit" NAME="submit" VALUE="Upload">
+
+% } elsif ( $mode eq 'preview' ) {
+
+ <IMG SRC="<% $p %>view/logo.cgi?type=png;preview_session=<% $session %>">
+
+% }
+
+ </TD>
+
+
+</TR>
+
+</TABLE>
+
+% if ( $mode eq 'preview' ) {
+ <BR>
+ <INPUT TYPE="submit" NAME="submit" VALUE="Change logo">
+% }
+
+</FORM>
+
+<% include("/elements/footer.html") %>
+
+<%once>
+
+my %type2desc = (
+ 'png' => 'online',
+ 'eps' => 'Print/PDF (typeset)',
+);
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+my $type = $cgi->param('type');
+
+$cgi->param('name') =~ /^([^\.\/]*)$/ or die "illegal name";
+my $name = $1;
+
+$cgi->param('mode') =~ /^(\w*)$/ or die "illegal mode";
+my $mode = $1 || 'upload';
+
+my $error = '';
+my $session = '';
+if ( $mode eq 'preview' ) {
+
+ my $fh = $cgi->upload('new_logo');
+
+ if ( defined $fh ) {
+
+ local $/;
+ my $logo_data = <$fh>;
+
+ $session = int(rand(4294967296)); #XXX
+ my $pref = new FS::access_user_pref({
+ 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
+ 'prefname' => "logo_preview$session",
+ 'prefvalue' => encode_base64($logo_data),
+ 'expiration' => time + 3600, #1h? 1m?
+ });
+ my $pref_error = $pref->insert;
+ if ( $pref_error ) {
+ die "FATAL: couldn't set preview cookie: $pref_error\n";
+ }
+
+ } else {
+
+ $mode = 'upload';
+ $error = 'No file uploaded';
+
+ }
+
+}
+
+</%init>
diff --git a/httemplate/edit/invoice_template.html b/httemplate/edit/invoice_template.html
new file mode 100644
index 000000000..9cec62c86
--- /dev/null
+++ b/httemplate/edit/invoice_template.html
@@ -0,0 +1,69 @@
+<% include("/elements/header.html", "Edit $type2desc{$type} invoice template",
+ menubar(
+ 'View all invoice templates' => $p.'browse/invoice_template.html'
+ )
+ )
+%>
+
+<FORM ACTION="process/invoice_template.html" METHOD="POST">
+<INPUT TYPE="hidden" NAME="confname" VALUE="<% $confname %>">
+
+% if ( $type eq 'html' ) {
+
+ <% include('/elements/htmlarea.html',
+ 'field' => 'value',
+ 'curr_value' => $value,
+ 'height' => 800,
+ )
+ %>
+
+% } else {
+
+ <TEXTAREA NAME="value" ROWS=30 COLS=80 WRAP="off"><%$value |h %></TEXTAREA>
+
+% }
+
+<BR><BR>
+<INPUT TYPE="submit" VALUE="Change template">
+
+</FORM>
+
+<% include("/elements/footer.html") %>
+
+<%once>
+
+my %type2desc = (
+ 'html' => 'HTML',
+ 'latex' => 'Print/PDF (typeset)',
+ 'text' => 'Plaintext',
+);
+
+my %type2base = (
+ 'html' => 'invoice_html',
+ 'latex' => 'invoice_latex',
+ 'text' => 'invoice_template',
+);
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $type = $cgi->param('type');
+my $name = $cgi->param('name');
+my $suffix = $cgi->param('suffix');
+
+#XXX type handling, just testing this out for now
+
+my $conf = new FS::Conf;
+
+my $value = length($name)
+ ? join("\n", $conf->config_orbase($type2base{$type}.$suffix, $name) )
+ : join("\n", $conf->config($type2base{$type}.$suffix) );
+
+my $confname = length($name)
+ ? $type2base{$type}.$suffix. '_'. $name
+ : $type2base{$type}.$suffix;
+
+</%init>
diff --git a/httemplate/edit/msgcat.cgi b/httemplate/edit/msgcat.cgi
new file mode 100755
index 000000000..85b300876
--- /dev/null
+++ b/httemplate/edit/msgcat.cgi
@@ -0,0 +1,54 @@
+<% header("Edit Message catalog" ) %>
+<BR>
+
+<% include('/elements/error.html') %>
+
+<% $widget->html %>
+
+ </TABLE>
+ </BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $widget = new HTML::Widgets::SelectLayers(
+ 'selected_layer' => 'en_US',
+ 'options' => { 'en_US'=>'en_US' },
+ 'form_action' => 'process/msgcat.cgi',
+ 'layer_callback' => sub {
+ my $layer = shift;
+ my $html = qq!<INPUT TYPE="hidden" NAME="locale" VALUE="$layer">!.
+ "<BR>Messages for locale $layer<BR>". table().
+ "<TR><TH COLSPAN=2>Code</TH>".
+ "<TH>Message</TH>";
+ $html .= "<TH>en_US Message</TH>" unless $layer eq 'en_US';
+ $html .= '</TR>';
+
+ #foreach my $msgcat ( sort { $a->msgcode cmp $b->msgcode }
+ # qsearch('msgcat', { 'locale' => $layer } ) ) {
+ foreach my $msgcat ( qsearch('msgcat', { 'locale' => $layer } ) ) {
+ $html .=
+ '<TR><TD>'. $msgcat->msgnum. '</TD><TD>'. $msgcat->msgcode. '</TD>'.
+ '<TD><INPUT TYPE="text" SIZE=32 '.
+ qq! NAME="!. $msgcat->msgnum. '" '.
+ qq!VALUE="!. ($cgi->param($msgcat->msgnum)||$msgcat->msg). qq!"></TD>!;
+ unless ( $layer eq 'en_US' ) {
+ my $en_msgcat = qsearchs('msgcat', {
+ 'locale' => 'en_US',
+ 'msgcode' => $msgcat->msgcode,
+ } );
+ $html .= '<TD>'. $en_msgcat->msg. '</TD>';
+ }
+ $html .= '</TR>';
+ }
+
+ $html .= '</TABLE><BR><INPUT TYPE="submit" VALUE="Apply changes">';
+
+ $html;
+ },
+
+);
+
+</%init>
diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi
new file mode 100755
index 000000000..3b5114122
--- /dev/null
+++ b/httemplate/edit/part_bill_event.cgi
@@ -0,0 +1,570 @@
+<% include('/elements/header.html',
+ "$action Invoice Event Definition",
+ menubar(
+ 'View all invoice events' => popurl(2). 'browse/part_bill_event.cgi',
+ )
+ )
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/part_bill_event.cgi" NAME="editEvent" METHOD=POST>
+<INPUT TYPE="hidden" NAME="eventpart" VALUE="<% $part_bill_event->eventpart %>">
+Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
+
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TD ALIGN="right">Event name </TD>
+ <TD><INPUT TYPE="text" NAME="event" VALUE="<% $hashref->{event} %>"></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">For </TD>
+ <TD>
+ <SELECT NAME="payby" <% $hashref->{eventpart} ? '' : 'MULTIPLE SIZE=7'%>>
+% tie my %payby, 'Tie::IxHash', FS::payby->cust_payby2longname;
+% foreach my $payby ( keys %payby ) {
+ <OPTION VALUE="<% $payby %>"<% ($part_bill_event->payby eq $payby) ? ' SELECTED' : '' %>><% $payby{$payby} %></OPTION>
+% }
+ </SELECT> customers
+ </TD>
+ </TR>
+% my $days = $hashref->{seconds}/86400;
+
+
+ <TR>
+ <TD ALIGN="right">After</TD>
+ <TD><INPUT TYPE="text" NAME="days" VALUE="<% $days %>"> days</TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Test event</TD>
+ <TD>
+ <SELECT NAME="freq">
+% tie my %freq, 'Tie::IxHash', '1d' => 'daily', '1m' => 'monthly';
+% foreach my $freq ( keys %freq ) {
+%
+
+
+ <OPTION VALUE="<% $freq %>"<% ($part_bill_event->freq eq $freq) ? ' SELECTED' : '' %>><% $freq{$freq} %></OPTION>
+% }
+
+
+ </SELECT>
+ </TD>
+ </TR>
+
+
+ <TR>
+ <TD ALIGN="right">Disabled</TD>
+ <TD>
+ <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD VALIGN="top" ALIGN="right">Action</TD>
+ <TD>
+%
+%
+%#print ntable();
+%
+%sub select_pkgpart {
+% my $label = shift;
+% my $plandata = shift;
+% my %selected = map { $_=>1 } split(/,\s*/, $plandata->{$label});
+% qq(<SELECT NAME="$label" MULTIPLE>).
+% join("\n", map {
+% '<OPTION VALUE="'. $_->pkgpart. '"'.
+% ( $selected{$_->pkgpart} ? ' SELECTED' : '' ).
+% '>'. $_->pkg. ' - '. $_->comment
+% } qsearch('part_pkg', { 'disabled' => '' } ) ).
+% '</SELECT>';
+%}
+%
+%sub select_agentnum {
+% my $plandata = shift;
+% #my $agentnum = $plandata->{'agentnum'};
+% my %agentnums = map { $_=>1 } split(/,\s*/, $plandata->{'agentnum'});
+% '<SELECT NAME="agentnum" MULTIPLE>'.
+% join("\n", map {
+% '<OPTION VALUE="'. $_->agentnum. '"'.
+% ( $agentnums{$_->agentnum} ? ' SELECTED' : '' ).
+% '>'. $_->agent
+% } qsearch('agent', { 'disabled' => '' } ) ).
+% '</SELECT>';
+%}
+%
+%sub honor_dundate {
+% my $label = shift;
+% my $plandata = shift;
+% '<TABLE>'.
+% '<TR><TD ALIGN="right">Allow delay until dun date? </TD>'.
+% qq(<TD><INPUT TYPE="checkbox" NAME="$label" VALUE="$label => 1," ).
+% ( $plandata->{$label} eq "$label => 1," ? 'CHECKED' : '' ).
+% '>'.
+% '</TD></TR>'.
+% '</TABLE>'
+%}
+%
+%my $conf = new FS::Conf;
+%my $money_char = $conf->config('money_char') || '$';
+%
+%my $late_taxclass = '';
+%my $late_percent_taxclass = '';
+%if ( $conf->exists('enable_taxclasses') ) {
+% $late_taxclass =
+% '<BR>Taxclass '.
+% include('/elements/select-taxclass.html',
+% 'curr_value' => '%%%late_taxclass%%%',
+% 'name' => 'late_taxclass' );
+% $late_percent_taxclass =
+% '<BR>Taxclass '.
+% include('/elements/select-taxclass.html',
+% 'curr_value' => '%%%late_percent_taxclass%%%',
+% 'name' => 'late_percent_taxclass' );
+%}
+%
+%#this is pretty kludgy right here.
+%tie my %events, 'Tie::IxHash',
+%
+% 'fee' => {
+% 'name' => 'Late fee (flat)',
+% 'code' => '$cust_main->charge( %%%charge%%%, \'%%%reason%%%\', \'$%%%charge%%%\', \'%%%late_taxclass%%%\' );',
+% 'html' =>
+% 'Amount <INPUT TYPE="text" SIZE="7" NAME="charge" VALUE="%%%charge%%%">'.
+% '<BR>Reason <INPUT TYPE="text" NAME="reason" VALUE="%%%reason%%%">'.
+% $late_taxclass,
+% 'weight' => 10,
+% },
+% 'fee_percent' => {
+% 'name' => 'Late fee (percentage)',
+% 'code' => '$cust_main->charge( sprintf(\'%.2f\', $cust_bill->owed * %%%percent%%% / 100 ), \'%%%percent_reason%%%\', \'%%%percent%%% percent\', \'%%%late_percent_taxclass%%%\' );',
+% 'html' =>
+% 'Percent <INPUT TYPE="text" SIZE="2" NAME="percent" VALUE="%%%percent%%%">%'.
+% '<BR>Reason <INPUT TYPE="text" NAME="percent_reason" VALUE="%%%percent_reason%%%">'.
+% $late_percent_taxclass,
+% 'weight' => 10,
+% },
+% 'suspend' => {
+% 'name' => 'Suspend',
+% 'code' => '$cust_main->suspend(reason => %%%sreason%%%, %%%honor_dundate%%% );',
+% 'html' => sub { &honor_dundate('honor_dundate', @_) },
+% 'weight' => 10,
+% 'reason' => 'S',
+% },
+% 'suspend-if-balance' => {
+% 'name' => 'Suspend if balance (this invoice and previous) over',
+% 'code' => '$cust_bill->cust_suspend_if_balance_over( %%%balanceover%%%, reason => %%%sreason%%%, %%%balance_honor_dundate%%% );',
+% 'html' => sub { " $money_char ". '<INPUT TYPE="text" SIZE="7" NAME="balanceover" VALUE="%%%balanceover%%%"> '. &honor_dundate('balance_honor_dundate', @_) },
+% 'weight' => 10,
+% 'reason' => 'S',
+% },
+% 'suspend-if-pkgpart' => {
+% 'name' => 'Suspend packages',
+% 'code' => '$cust_main->suspend_if_pkgpart({pkgparts => [%%%if_pkgpart%%%,], reason => %%%sreason%%%, %%%if_pkgpart_honor_dundate%%% });',
+% 'html' => sub { &select_pkgpart('if_pkgpart', @_). &honor_dundate('if_pkgpart_honor_dundate', @_) },
+% 'weight' => 10,
+% 'reason' => 'S',
+% },
+% 'suspend-unless-pkgpart' => {
+% 'name' => 'Suspend packages except',
+% 'code' => '$cust_main->suspend_unless_pkgpart({unless_pkgpart => [%%%unless_pkgpart%%%], reason => %%%sreason%%%, %%%unless_pkgpart_honor_dundate%%% });',
+% 'html' => sub { &select_pkgpart('unless_pkgpart', @_). &honor_dundate('unless_pkgpart_honor_dundate' => @_) },
+% 'weight' => 10,
+% 'reason' => 'S',
+% },
+% 'cancel' => {
+% 'name' => 'Cancel',
+% 'code' => '$cust_main->cancel(reason => %%%creason%%%);',
+% 'weight' => 10,
+% 'reason' => 'C',
+% },
+%
+% 'addpost' => {
+% 'name' => 'Add postal invoicing',
+% 'code' => '$cust_main->invoicing_list_addpost(); "";',
+% 'weight' => 20,
+% },
+%
+% 'comp' => {
+% 'name' => 'Pay invoice with a complimentary "payment"',
+% 'code' => '$cust_bill->comp();',
+% 'weight' => 30,
+% },
+%
+% 'credit' => {
+% 'name' => "Create and apply a credit for the customer's balance (i.e. write off as bad debt)",
+% 'code' => '$cust_main->credit( $cust_main->balance, \'%%%credit_reason%%%\' );',
+% 'html' => '<INPUT TYPE="text" NAME="credit_reason" VALUE="%%%credit_reason%%%">',
+% 'weight' => 30,
+% },
+%
+% 'realtime-card' => {
+% 'name' => 'Run card with a <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> realtime gateway',
+% 'code' => '$cust_bill->realtime_card();',
+% 'weight' => 30,
+% },
+%
+% 'realtime-check' => {
+% 'name' => 'Run check with a <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> realtime gateway',
+% 'code' => '$cust_bill->realtime_ach();',
+% 'weight' => 30,
+% },
+%
+% 'realtime-lec' => {
+% 'name' => 'Run phone bill ("LEC") billing with a <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> realtime gateway',
+% 'code' => '$cust_bill->realtime_lec();',
+% 'weight' => 30,
+% },
+%
+% 'batch-card' => {
+% 'name' => 'Add card or check to a pending batch',
+% 'code' => '$cust_bill->batch_card(%options);',
+% 'weight' => 40,
+% },
+%
+%
+% #'retriable' => {
+% # 'name' => 'Mark batched card event as retriable',
+% # 'code' => '$cust_pay_batch->retriable();',
+% # 'weight' => 60,
+% #},
+%
+% 'send' => {
+% 'name' => 'Send invoice (email/print/fax)',
+% 'code' => '$cust_bill->send();',
+% 'weight' => 50,
+% },
+%
+% 'send_email' => {
+% 'name' => 'Send invoice (email only)',
+% 'code' => '$cust_bill->email();',
+% 'weight' => 50,
+% },
+%
+% 'send_alternate' => {
+% 'name' => 'Send invoice (email/print/fax) with alternate template',
+% 'code' => '$cust_bill->send(\'%%%templatename%%%\');',
+% 'html' =>
+% '<INPUT TYPE="text" NAME="templatename" VALUE="%%%templatename%%%">',
+% 'weight' => 50,
+% },
+%
+% 'send_if_newest' => {
+% 'name' => 'Send invoice (email/print/fax) with alternate template, if it is still the newest invoice (useful for late notices - set to 31 days or later)',
+% 'code' => '$cust_bill->send_if_newest(\'%%%if_newest_templatename%%%\');',
+% 'html' =>
+% '<INPUT TYPE="text" NAME="if_newest_templatename" VALUE="%%%if_newest_templatename%%%">',
+% 'weight' => 50,
+% },
+%
+% 'send_agent' => {
+% 'name' => 'Send invoice (email/print/fax) ',
+% 'code' => '$cust_bill->send( \'%%%agent_templatename%%%\',
+% [ %%%agentnum%%% ],
+% \'%%%agent_invoice_from%%%\',
+% %%%agent_balanceover%%%
+% );',
+% 'html' => sub {
+% '<TABLE BORDER=0>
+% <TR>
+% <TD ALIGN="right">only for agent(s) </TD>
+% <TD>'. &select_agentnum(@_). '</TD>
+% </TR>
+% <TR>
+% <TD ALIGN="right">with template </TD>
+% <TD>
+% <INPUT TYPE="text" NAME="agent_templatename" VALUE="%%%agent_templatename%%%">
+% </TD>
+% </TR>
+% <TR>
+% <TD ALIGN="right">email From: </TD>
+% <TD>
+% <INPUT TYPE="text" NAME="agent_invoice_from" VALUE="%%%agent_invoice_from%%%">
+% </TD>
+% </TR>
+% <TR>
+% <TD ALIGN="right">if balance (this invoice and previous) over
+% </TD>
+% <TD>
+% '. $money_char. '<INPUT TYPE="text" SIZE="7" NAME="agent_balanceover" VALUE="%%%agent_balanceover%%%">
+% </TD>
+% </TR>
+% </TABLE>';
+% },
+% 'weight' => 50,
+% },
+%
+% 'send_csv_ftp' => {
+% 'name' => 'Upload CSV invoice data to an FTP server',
+% 'code' => '$cust_bill->send_csv( protocol => \'ftp\',
+% server => \'%%%ftpserver%%%\',
+% username => \'%%%ftpusername%%%\',
+% password => \'%%%ftppassword%%%\',
+% dir => \'%%%ftpdir%%%\',
+% \'format\' => \'%%%ftpformat%%%\',
+% );',
+% 'html' =>
+% '<TABLE BORDER=0>'.
+% '<TR><TD ALIGN="right">Format ("default" or "billco"): </TD>'.
+% '<TD>'.
+% '<!--'.
+% '<SELECT NAME="ftpformat">'.
+% '<OPTION VALUE="default">Default'.
+% '<OPTION VALUE="billco">Billco'.
+% '</SELECT>'.
+% '-->'.
+% '<INPUT TYPE="text" NAME="ftpformat" VALUE="%%%ftpformat%%%">'.
+% '</TD></TR>'.
+% '<TR><TD ALIGN="right">FTP server: </TD>'.
+% '<TD><INPUT TYPE="text" NAME="ftpserver" VALUE="%%%ftpserver%%%">'.
+% '</TD></TR>'.
+% '<TR><TD ALIGN="right">FTP username: </TD><TD>'.
+% '<INPUT TYPE="text" NAME="ftpusername" VALUE="%%%ftpusername%%%">'.
+% '</TD></TR>'.
+% '<TR><TD ALIGN="right">FTP password: </TD><TD>'.
+% '<INPUT TYPE="text" NAME="ftppassword" VALUE="%%%ftppassword%%%">'.
+% '</TD></TR>'.
+% '<TR><TD ALIGN="right">FTP directory: </TD>'.
+% '<TD><INPUT TYPE="text" NAME="ftpdir" VALUE="%%%ftpdir%%%">'.
+% '</TD></TR>'.
+% '</TABLE>',
+% 'weight' => 50,
+% },
+%
+% 'spool_csv' => {
+% 'name' => 'Spool CSV invoice data',
+% 'code' => '$cust_bill->spool_csv(
+% \'format\' => \'%%%spoolformat%%%\',
+% \'dest\' => \'%%%spooldest%%%\',
+% \'balanceover\' => \'%%%spoolbalanceover%%%\',
+% \'agent_spools\' => \'%%%spoolagent_spools%%%\',
+% );',
+% 'html' => sub {
+% my $plandata = shift;
+%
+% my $html =
+% '<TABLE BORDER=0>'.
+% '<TR><TD ALIGN="right">Format: </TD>'.
+% '<TD>'.
+% '<SELECT NAME="spoolformat">';
+%
+% foreach my $option (qw( default billco )) {
+% $html .= qq(<OPTION VALUE="$option");
+% $html .= ' SELECTED' if $option eq $plandata->{'spoolformat'};
+% $html .= ">\u$option";
+% }
+%
+% $html .=
+% '</SELECT>'.
+% '</TD></TR>'.
+% '<TR><TD ALIGN="right">For destination: </TD>'.
+% '<TD>'.
+% '<SELECT NAME="spooldest">';
+%
+% tie my %dest, 'Tie::IxHash',
+% '' => '(all)',
+% 'POST' => 'Postal Mail',
+% 'EMAIL' => 'Email',
+% 'FAX' => 'Fax',
+% ;
+%
+% foreach my $dest (keys %dest) {
+% $html .= qq(<OPTION VALUE="$dest");
+% $html .= ' SELECTED' if $dest eq $plandata->{'spooldest'};
+% $html .= '>'. $dest{$dest};
+% }
+%
+% $html .=
+% '</SELECT>'.
+% '</TD></TR>'.
+%
+% '<TR>'.
+% '<TD ALIGN="right">if balance (this invoice and previous) over </TD>'.
+% '<TD>'.
+% "$money_char ".
+% '<INPUT TYPE="text" SIZE="7" NAME="spoolbalanceover" VALUE="%%%spoolbalanceover%%%">'.
+% '</TD>'.
+% '<TR><TD ALIGN="right">Individual per-agent spools? </TD>'.
+% '<TD><INPUT TYPE="checkbox" NAME="spoolagent_spools" VALUE="1" '.
+% ( $plandata->{'spoolagent_spools'} ? 'CHECKED' : '' ).
+% '>'.
+% '</TD></TR>'.
+% '</TABLE>';
+%
+% $html;
+% },
+% 'weight' => 50,
+% },
+%
+% 'bill' => {
+% 'name' => 'Generate invoices (normally only used with a <i>Late Fee</i> event)',
+% 'code' => '$cust_main->bill();',
+% 'weight' => 60,
+% },
+%
+% 'apply' => {
+% 'name' => 'Apply unapplied payments and credits',
+% 'code' => '$cust_main->apply_payments_and_credits; "";',
+% 'weight' => 70,
+% },
+%
+%;
+%
+<SCRIPT TYPE="text/javascript">var myreasons = new Array();</SCRIPT>
+%foreach my $event ( keys %events ) {
+% my %plandata = map { /^(\w+) (.*)$/; ($1, $2); }
+% split(/\n/, $part_bill_event->plandata);
+% my $html = $events{$event}{html};
+% if ( ref($html) eq 'CODE' ) {
+% $html = &{$html}(\%plandata);
+% }
+% while ( $html =~ /%%%(\w+)%%%/ ) {
+% my $field = $1;
+% $html =~ s/%%%$field%%%/$plandata{$field}/;
+% }
+%
+<SCRIPT TYPE="text/javascript">myreasons.push('<% $events{$event}{reason} %>');
+</SCRIPT>
+% if ($event eq $part_bill_event->plan){
+% $currentreasonclass=$events{$event}{reason};
+% }
+% print ntable( "#cccccc", 2).
+% qq!<TR><TD><INPUT TYPE="radio" NAME="plan_weight_eventcode" !;
+% print "CHECKED " if $event eq $part_bill_event->plan;
+% print qq!onClick="showhide_table()" !;
+% print qq!VALUE="!. $event. ":". $events{$event}{weight}. ":".
+% encode_entities($events{$event}{code}).
+% qq!">$events{$event}{name}</TD>!;
+% print '<TD>'. $html. '</TD>' if $html;
+% print qq!</TR>!;
+% print '</TABLE>';
+% print qq!<HR WIDTH="90%">!;
+%}
+%
+% if ($currentreasonclass eq 'C'){
+% if ($cgi->param('creason') =~ /^(-?\d+)$/){
+% $creason = $1;
+% }else{
+% $creason = $part_bill_event->reason;
+% }
+% if ($cgi->param('newcreasonT') =~ /^(\d+)$/){
+% $newcreasonT = $1;
+% }
+% if ($cgi->param('newcreason') =~ /^([\w\s]+)$/){
+% $newcreason = $1;
+% }
+% }elsif ($currentreasonclass eq 'S'){
+% if ($cgi->param('sreason') =~ /^(-?\d+)$/){
+% $sreason = $1;
+% }else{
+% $sreason = $part_bill_event->reason;
+% }
+% if ($cgi->param('newsreasonT') =~ /^(\d+)$/){
+% $newsreasonT = $1;
+% }
+% if ($cgi->param('newsreason') =~ /^([\w\s]+)$/){
+% $newsreason = $1;
+% }
+% }
+%
+
+</TD></TR>
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+ function showhide_table()
+ {
+ for(i=0;i<document.editEvent.plan_weight_eventcode.length;i++){
+ if (document.editEvent.plan_weight_eventcode[i].checked == true){
+ currentevent=i;
+ }
+ }
+ if(myreasons[currentevent] == 'C'){
+ document.getElementById('Ctable').style.display = 'inline';
+ document.getElementById('Stable').style.display = 'none';
+ }else if(myreasons[currentevent] == 'S'){
+ document.getElementById('Ctable').style.display = 'none';
+ document.getElementById('Stable').style.display = 'inline';
+ }else{
+ document.getElementById('Ctable').style.display = 'none';
+ document.getElementById('Stable').style.display = 'none';
+ }
+ }
+</SCRIPT>
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%">
+<TR><TD>
+<TABLE BORDER=0 id="Ctable" style="display:<% $currentreasonclass eq 'C' ? 'inline' : 'none' %>">
+<% include('/elements/tr-select-reason.html',
+ 'field' => 'creason',
+ 'reason_class' => 'C',
+ 'curr_value' => $creason,
+ 'init_type' => $newcreasonT,
+ 'init_newreason' => $newcreason
+ )
+%>
+</TABLE>
+</TR></TD>
+</TABLE>
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%">
+<TR><TD>
+<TABLE BORDER=0 id="Stable" style="display:<% $currentreasonclass eq 'S' ? 'inline' : 'none' %>">
+<% include('/elements/tr-select-reason.html',
+ 'field' => 'sreason',
+ 'reason_class' => 'S',
+ 'curr_value' => $sreason,
+ 'init_type' => $newsreasonT,
+ 'init_newreason' => $newsreason
+ )
+%>
+</TABLE>
+</TR></TD>
+</TABLE>
+
+%
+%print qq!<INPUT TYPE="submit" VALUE="!,
+% $hashref->{eventpart} ? "Apply changes" : "Add invoice event",
+% qq!">!;
+%
+
+
+ </FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+if ( $cgi->param('eventpart') && $cgi->param('eventpart') =~ /^(\d+)$/ ) {
+ $cgi->param('eventpart', $1);
+} else {
+ $cgi->param('eventpart', '');
+}
+
+my ($creason, $newcreasonT, $newcreason);
+my ($sreason, $newsreasonT, $newsreason);
+
+my ($query) = $cgi->keywords;
+my $action = '';
+my $part_bill_event = '';
+my $currentreasonclass = '';
+if ( $cgi->param('error') ) {
+ $part_bill_event = new FS::part_bill_event ( {
+ map { $_, scalar($cgi->param($_)) } fields('part_bill_event')
+ } );
+}
+if ( $query && $query =~ /^(\d+)$/ ) {
+ $part_bill_event ||= qsearchs('part_bill_event',{'eventpart'=>$1});
+} else {
+ $part_bill_event ||= new FS::part_bill_event {};
+}
+$action ||= $part_bill_event->eventpart ? 'Edit' : 'Add';
+my $hashref = $part_bill_event->hashref;
+
+</%init>
diff --git a/httemplate/edit/part_event.html b/httemplate/edit/part_event.html
new file mode 100644
index 000000000..6a532223e
--- /dev/null
+++ b/httemplate/edit/part_event.html
@@ -0,0 +1,679 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Billing event definition',
+ 'table' => 'part_event',
+ 'fields' => [
+ 'event',
+ { field => 'eventtable',
+ type => 'select',
+ options => [ FS::part_event->eventtables ],
+ labels => $eventtable_labels,
+ onchange => 'eventtable_changed',
+ },
+ { field => 'agentnum',
+ type => 'select-agent',
+ disable_empty => $disable_empty_agent,
+ },
+ { field => 'check_freq',
+ type => 'select',
+ options => [ '1d', '1m' ],
+ labels => $check_freq_labels,
+ },
+ { field => 'disabled',
+ type => 'checkbox',
+ value => 'Y',
+ },
+ { type => 'title',
+ value => 'Event Conditions',
+ },
+ { field => 'conditionname',
+ type => 'selectlayers',
+ options => [ keys %all_conditions ],
+ labels => \%condition_labels,
+ onchange => 'condition_changed(what);',
+ layer_fields => \%condition_fields,
+ layer_values_callback => $condition_layer_values,
+ html_between => n_a('action'),
+ m2name_table => 'part_event_condition',
+ m2name_namecol => 'conditionname',
+ m2_label => 'Condition',
+ m2_new_default => \@implicit_condition_objs,
+ m2_error_callback => $condition_error_callback,
+ m2_remove_warnings => \%condition_remove_warnings,
+ m2_new_js => 'condition_repop',
+ m2_remove_js => 'condition_add',
+ },
+ { type => 'title',
+ value => 'Event Action',
+ },
+ { field => 'action',
+ type => 'selectlayers',
+ options => [ keys %all_actions ],
+ labels => \%action_labels,
+ onchange => 'action_changed(what);',
+ layer_fields => \%action_fields,
+ layer_values_callback => $action_layer_values,
+ html_between => n_a('action'),
+ },
+
+ ],
+ 'labels' => {
+ 'eventpart' => 'Event',
+ 'event' => 'Event name',
+ 'eventtable' => 'Type',
+ 'agentnum' => 'Agent',
+ 'check_freq' => 'Check frequency',
+ 'disabled' => 'Disable event',
+
+ 'conditionname' => 'Add&nbsp;new&nbsp;condition',
+ #'weight',
+ 'action' => 'Action',
+ },
+ 'viewall_dir' => 'browse',
+ 'new_callback' => sub { #start empty for new events only
+ my( $cgi, $object, $fields_listref ) = @_;
+ unshift @{ $fields_listref->[1]{'options'} }, '';
+ },
+ 'error_callback' => $error_callback,
+
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Edit global billing events',
+ )
+%>
+<SCRIPT TYPE="text/javascript">
+
+ window.onload = function () { eventtable_changed(document.getElementById('eventtable')) };
+ var notonload = 0;
+
+ function eventtable_changed(what) {
+
+% if ( $JS_DEBUG ) {
+ alert('eventtable_changed called on ' + what );
+% }
+
+ var eventtable = what.options[what.selectedIndex].value;
+% if ( $JS_DEBUG ) {
+ alert ("eventtable: " + eventtable);
+% }
+ var eventdesc = what.options[what.selectedIndex].text;
+
+ //remove the ** Select type **
+ if ( what.options[0].value == '' && notonload++ > 0 ) {
+ what.options[0] = null;
+ }
+
+ ////
+ // XXX gray out conditions that can't apply (in addition to the warning)?
+ ////
+
+ ////
+ // update condition selects
+ ////
+
+ for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) {
+ var cond_id = 'conditionname' + cnum;
+ var cond_select = document.getElementById(cond_id);
+
+% if ( $JS_DEBUG ) {
+ alert('updating ' + cond_id);
+% }
+
+ // save off the current value
+ var conditionname = cond_select.options[cond_select.selectedIndex].value;
+ var cond_desc = cond_select.options[cond_select.selectedIndex].text;
+
+ var seen_condition = condition_repop(cond_select);
+
+ var warning = document.getElementById(cond_id + '_warning');
+% if ( $JS_DEBUG ) {
+ alert('turning off warning; setting style.display of '+ cond_id +
+ '_warning (' + warning + ') to none');
+% }
+ warning.style.display = 'none';
+
+ if ( ! seen_condition && conditionname != '' ) {
+ // add the current (not valid) condition back
+ opt(cond_select, conditionname, cond_desc, true );
+ if ( ! condition_is_implicit(conditionname) ) {
+ cond_select.parentNode.parentNode.style.display = '';
+ cond_select.disabled = '';
+ // turn on a warning and gray out the condition row
+% if ( $JS_DEBUG ) {
+ alert('turning on warning; setting style.display of '+ cond_id +
+ '_warning (' + warning + ') to ""');
+% }
+ warning.innerHTML = 'Not applicable to ' + eventdesc + ' events';
+ warning.style.display = '';
+ } else {
+ if ( ! condition_in_eventtable(conditionname) ) {
+% if ( $JS_DEBUG ) {
+ alert(conditionname + " not in " + eventtable + "; disabling");
+% }
+ cond_select.parentNode.parentNode.style.display = 'none';
+ cond_select.disabled = 'disabled';
+ } else {
+% if ( $JS_DEBUG ) {
+ alert(conditionname + " implicit for " + eventtable + "; enabling");
+% }
+ cond_select.parentNode.parentNode.style.display = '';
+ cond_select.disabled = '';
+ }
+ }
+ }
+
+ }
+
+
+ ////
+ // update action select
+ ////
+
+ // save off the current value first!!
+ var action = what.form.action.options[what.form.action.selectedIndex].value;
+ var a_desc = what.form.action.options[what.form.action.selectedIndex].text;
+ var seen_action = false;
+
+ // blank the current action select
+ for ( var i = what.form.action.length; i >= 0; i-- )
+ what.form.action.options[i] = null;
+
+ if ( action == '' ) {
+ opt(what.form.action, action, a_desc, true );
+ }
+
+ // repopulate it
+% foreach my $eventtable ( FS::part_event->eventtables ) {
+% tie my %actions, 'Tie::IxHash', FS::part_event->actions($eventtable);
+% #use Data::Dumper; warn Dumper(%actions);
+
+ if ( eventtable == '<% $eventtable %>' ) {
+
+% foreach my $action ( keys %actions ) {
+% ( my $description = $actions{$action}->{'description'} ) =~ s/'/\\'/g;
+
+ var sel = false;
+ if ( action == '<% $action %>' ) {
+ seen_action = true;
+ sel = true;
+ }
+ opt( what.form.action, '<% $action %>', '<% $description %>', sel );
+% }
+
+ }
+
+% }
+
+ // by default, turn off warnings and enable the submit button
+ var warning = document.getElementById('action_warning');
+ warning.style.display = 'none';
+ var submit_button = document.getElementById('submit');
+ submit_button.disabled = '';
+
+ if ( ! seen_action && action != '' ) {
+ // add the current (not valid) action back
+ opt( what.form.action, action, a_desc, true );
+ // turn on a warning and disable the submit button
+ //warning.innerHTML = a_desc + ' event not available as a ' +
+ warning.innerHTML = 'Not available as a ' + eventdesc + ' action';
+ warning.style.display = '';
+ submit_button.disabled = 'disabled';
+ }
+
+ }
+
+ function opt(what,value,text,selected) {
+ var optionName = new Option(text, value, false, selected);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function action_changed(what) {
+ // remove '** Select new **'
+ if ( what.options[0].value == '' ) {
+ what.options[0] = null;
+ }
+ // remove the warning, remove the invalid action, enable the submit button
+ var warning = document.getElementById('action_warning');
+ if ( warning.style.display == '' ) {
+ warning.style.display = 'none';
+ what.options[what.length-1] = null;
+ document.getElementById('submit').disabled = '';
+ }
+ }
+
+ function condition_changed(what) {
+ // remove '** Select new **'
+ if ( what.options[0].value == '' ) {
+ what.options[0] = null;
+ }
+
+ var previousValue = what.getAttribute('previousValue');
+ var previousText = what.getAttribute('previousText');
+ var value = what.options[what.selectedIndex].value;
+ var text = what.options[what.selectedIndex].text;
+
+% foreach my $value ( keys %condition_remove_warnings ) {
+ if ( previousValue == '<% $value %>' ) {
+ if ( !confirm( <% $condition_remove_warnings{$value} |js_string %> ) ) {
+ for ( var i=0; i < what.length; i++ ) {
+ if ( what.options[i].value == previousValue ) {
+ what.selectedIndex = i;
+ }
+ }
+ return false;
+ }
+ }
+% }
+
+ //alert(previous + ' changed to ' + value);
+
+ var field_regex = /(\d+)$/;
+ var match = field_regex.exec(what.name);
+ if ( !match ) {
+ alert(what.name + " didn't match?!");
+ return;
+ }
+
+ //add the previous condition *back* to all the other selects...
+ condition_add(previousValue, previousText, match[1]);
+
+ what.setAttribute('previousValue', value);
+ what.setAttribute('previousText', text);
+
+ // remove the new condition from all other selects
+ condition_remove(value, match[1]);
+
+ }
+
+ function condition_avail(check_cond, curnum) {
+ for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) {
+ if ( cnum == curnum ) continue;
+
+ var cond_id = 'conditionname' + cnum;
+ var cond_select = document.getElementById(cond_id);
+
+ //alert("checking " + cond_id + " (" + cond_select.disabled + ")");
+
+ if ( cond_select.disabled ) continue;
+
+ // the current value
+ var conditionname = cond_select.options[cond_select.selectedIndex].value;
+
+ if ( check_cond == conditionname ) return false;
+
+ }
+
+ return true;
+
+ }
+
+ function condition_remove(remove_cond, curnum) {
+
+ if ( remove_cond.length == 0 ) return;
+
+ for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) {
+ if ( cnum == curnum ) continue;
+
+ var cond_id = 'conditionname' + cnum;
+ var cond_select = document.getElementById(cond_id);
+
+ //for ( var i = cond_select.length; i >= 0; i-- ) {
+ for ( var i=0; i < cond_select.length; i++ ) {
+ if ( cond_select.options[i].value == remove_cond ) {
+ cond_select.options[i] = null;
+ }
+ }
+
+ }
+
+ }
+
+ function condition_add(add_condname, add_conddesc, curnum) {
+
+ if ( add_condname.length == 0 ) return;
+
+ var in_eventtable = condition_in_eventtable(add_condname);
+
+ if ( ! in_eventtable ) return;
+
+ for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) {
+ if ( cnum == curnum ) continue;
+
+ var cond_id = 'conditionname' + cnum;
+ var cond_select = document.getElementById(cond_id);
+
+ if ( cond_select.disabled ) continue;
+
+ //alert("adding " + add_condname + " to " + cond_id);
+
+ opt(cond_select, add_condname, add_conddesc, false );
+
+ cond_select.parentNode.parentNode.style.display = '';
+
+ }
+
+ }
+
+ function condition_in_eventtable(condname) {
+
+ var eventtable_el = document.getElementById('eventtable');
+ var eventtable = eventtable_el.options[eventtable_el.selectedIndex].value;
+
+ var in_eventtable = false;
+
+% foreach my $eventtable ( FS::part_event->eventtables ) {
+% tie my %conditions, 'Tie::IxHash',
+% FS::part_event_condition->conditions($eventtable);
+
+ if ( eventtable == '<% $eventtable %>' ) {
+
+% foreach my $conditionname ( keys %conditions ) {
+
+ if ( condname == '<% $conditionname %>' ) {
+ in_eventtable = true;
+ }
+
+% }
+
+ }
+
+% }
+
+ return in_eventtable;
+
+ }
+
+ function condition_is_implicit(condname) {
+
+ if ( true <% @implicit_conditions
+ ? ( ' && '. join(' && ', map { "condname != '$_'" }
+ @implicit_conditions
+ )
+ )
+ : ''
+ %> ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ function condition_repop(cond_select) {
+
+ var eventtable_el = document.getElementById('eventtable');
+ var eventtable = eventtable_el.options[eventtable_el.selectedIndex].value;
+
+ // save off the current value
+ var conditionname = cond_select.options[cond_select.selectedIndex].value;
+ var cond_desc = cond_select.options[cond_select.selectedIndex].text;
+ var seen_condition = false;
+
+ //skip deleted conditions
+ if ( cond_select.disabled && conditionname != '' && ! condition_is_implicit(conditionname) ) {
+ return false;
+ }
+
+ var field_regex = /(\d+)$/;
+ var match = field_regex.exec(cond_select.name);
+ if ( !match ) {
+ alert(what.name + " didn't match?!");
+ return;
+ }
+ var cnum = match[1];
+
+ // blank the current condition select
+ for ( var i = cond_select.length; i >= 0; i-- )
+ cond_select.options[i] = null;
+
+ if ( conditionname == '' ) {
+ opt(cond_select, conditionname, cond_desc, true );
+ }
+
+ // repopulate it
+% foreach my $eventtable ( FS::part_event->eventtables ) {
+% tie my %conditions, 'Tie::IxHash',
+% FS::part_event_condition->conditions($eventtable);
+
+ if ( eventtable == '<% $eventtable %>' ) {
+
+% foreach my $conditionname ( keys %conditions ) {
+% my $description = $conditions{$conditionname}->{'description'};
+% $description =~ s/'/\\'/g;
+
+ var sel = false;
+ if ( conditionname == '<% $conditionname %>' ) {
+ seen_condition = true;
+ sel = true;
+ }
+
+ if ( condition_avail("<% $conditionname %>", cnum) ) {
+ opt(cond_select, '<% $conditionname %>', '<% $description %>', sel);
+ }
+
+% }
+
+ }
+
+% }
+
+ if ( cond_select.length > 1 || cond_select.length == 1 && cond_select.options[0].value.length > 0 ) {
+
+ cond_select.parentNode.parentNode.style.display = '';
+ cond_select.disabled = '';
+
+ } else {
+ cond_select.parentNode.parentNode.style.display = 'none';
+ cond_select.disabled = 'disabled';
+ }
+
+ return seen_condition;
+
+ }
+
+</SCRIPT>
+<%once>
+
+#misc (eventtable, check_freq)
+
+my $eventtable_labels = FS::part_event->eventtable_labels;
+$eventtable_labels->{''} = '** Select type **';
+
+my $check_freq_labels = FS::part_event->check_freq_labels;
+
+#conditions
+
+tie my %all_conditions, 'Tie::IxHash',
+ '' => { 'description' => '*** Select new condition ***', },
+ FS::part_event_condition->conditions();
+
+my %condition_labels = map { $_ => $all_conditions{$_}->{'description'} }
+ keys %all_conditions;
+
+#my %condition_fields = map { $_ => $all_conditions{$_}->{option_fields} }
+# keys %all_conditions;
+my %condition_fields = map { my $c = $_;
+ tie my %opts, 'Tie::IxHash',
+ @{ $all_conditions{$c}->{'option_fields'} || []};
+ %opts = ( map { ( "$c.$_" => $opts{$_} ); }
+ keys %opts
+ );
+ ( $c => [ %opts ] );
+ }
+ keys %all_conditions;
+
+my @implicit_conditions = sort { $all_conditions{$a}->{'implicit_flag'} <=>
+ $all_conditions{$b}->{'implicit_flag'}
+ }
+ grep { $all_conditions{$_}->{'implicit_flag'} }
+ keys %all_conditions;
+
+my @implicit_condition_objs = map {
+ new FS::part_event_condition {
+ 'conditionname' => $_,
+ };
+ }
+ @implicit_conditions;
+
+my %condition_remove_warnings =
+ map { ( $_ => $all_conditions{$_}->{'remove_warning'} ); }
+ grep { $all_conditions{$_}->{'remove_warning'} }
+ keys %all_conditions;
+
+#actions
+
+tie my %all_actions, 'Tie::IxHash',
+ '' => { 'description' => '*** Select event action ***', },
+ FS::part_event->actions();
+
+my %action_labels = map { $_ => $all_actions{$_}->{'description'} }
+ keys %all_actions;
+
+#my %action_fields = map { $_ => $all_actions{$_}->{option_fields} }
+# keys %all_actions;
+my %action_fields = map { my $action = $_;
+ tie my %opts, 'Tie::IxHash',
+ @{ $all_actions{$action}->{option_fields} || [] };
+ %opts = ( map { ( "$action.$_" => $opts{$_} ); }
+ keys %opts
+ );
+ ( $action => [ %opts ] );
+ }
+ keys %all_actions;
+
+#subs
+
+sub n_a {
+ my $t = shift;
+
+ return sub {
+ my $field = shift;
+ qq( <FONT ID="${field}_warning" STYLE="display:none" COLOR="#FF0000">).
+ "Party Party Join us Join us".
+ '</FONT>';
+ };
+}
+
+my $action_layer_values = sub {
+ my( $cgi, $part_event ) = @_;
+ my $action = $cgi->param('action') || $part_event->action;
+ return {} unless $action;
+ scalar( #force hashref
+ {
+ #map { $_ => { $part_event->options } }
+ # keys %action_fields
+ map { my $action = $_;
+ my %fields = @{ $action_fields{$action} };
+ my %obj_opts = $part_event->options;
+ %obj_opts = map { ( "$action.$_" => $obj_opts{$_} ); }
+ keys %obj_opts;
+ my %opts =
+ map { #false laziness w/process/part_event.html
+ my $option = $_;
+ my $value = scalar($cgi->param($_)) || $obj_opts{$_};
+
+ if ( $option =~ /^(.*)\.reasonnum$/ && $value == -1 ) {
+ $value = {
+ 'typenum' => scalar( $cgi->param( "new${option}T" ) ),
+ 'reason' => scalar( $cgi->param( "new${option}" ) ),
+ };
+ }
+
+ ( $option => $value );
+
+ }
+ keys %fields;
+ ( $action => \%opts );
+ }
+ keys %action_fields
+ }
+ );
+};
+
+tie my %cgi_conditions, 'Tie::IxHash';
+
+my $error_callback = sub {
+ my( $cgi, $object, $fields_listref ) = @_;
+
+ my @cond_params = grep /^conditionname\d+$/, $cgi->param;
+
+ %cgi_conditions = map {
+ my $param = $_;
+ my $conditionname = $cgi->param($param);
+ $conditionname => {
+ map {
+
+ my $cgi_key = $_;
+ $cgi_key =~ /^$param\.$conditionname\.(.*)$/ or die 'wtf!';
+ my $key = $1;
+ #my $value = $cgi->param($_);
+
+ #my $info = $all_conditions->{$conditionname}
+ my %cond_opts =
+ @{ $all_conditions{$conditionname}->{'option_fields'} || []};
+ my $info = $cond_opts{$key};
+
+ my $value;
+ #false laziness w/process/part_event.html
+ if ( $info->{'type'} =~ /^(select|checkbox)-?multiple$/
+ or $info->{'type'} =~ /^select/ && $info->{'multiple'} ) {
+ $value = { map { $_ => 1 } $cgi->param($cgi_key) };
+ } elsif ( $info->{'type'} eq 'freq' ) {
+ $value = $cgi->param($cgi_key). $cgi->param($cgi_key.'_units');
+ } else {
+ $value = $cgi->param($cgi_key);
+ }
+
+ $key => $value;
+
+ } grep /^$param\.$conditionname\./, $cgi->param
+ };
+ } grep $cgi->param($_), grep /^conditionname\d+$/, $cgi->param;
+
+};
+
+my $condition_error_callback = sub {
+ map {
+ new FS::part_event_condition { 'conditionname' => $_, };
+ } keys %cgi_conditions;
+};
+
+my $condition_layer_values = sub {
+ #m2_table option causes this to be
+ # part_event_condition instead of part_event
+ my ( $cgi, $part_event_condition, $switches ) = @_;
+ scalar( #force hashref
+ {
+ #map { $_ => { $part_event_condition->options } }
+ # keys %condition_fields
+ map { my $conditionname = $_;
+ my %opts = $switches->{'mode'} eq 'error'
+ ? %{ $cgi_conditions{$conditionname} || {} }
+ : $part_event_condition->options;
+ %opts = (
+ map { ( "$conditionname.$_" => $opts{$_} ); }
+ keys %opts
+ );
+ ( $conditionname => \%opts );
+ }
+ keys %condition_fields
+ }
+ );
+};
+
+
+</%once>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Edit billing events')
+ || $curuser->access_right('Edit global billing events');
+
+my $disable_empty_agent= ! $curuser->access_right('Edit global billing events');
+
+%cgi_conditions = ();
+my $use_cgi_conditions = 0;
+
+my $JS_DEBUG = 0;
+
+</%init>
diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi
new file mode 100644
index 000000000..d57979751
--- /dev/null
+++ b/httemplate/edit/part_export.cgi
@@ -0,0 +1,123 @@
+<% include('/elements/header.html', "$action Export", '', ' onLoad="visualize()"') %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="dummy">
+<INPUT TYPE="hidden" NAME="exportnum" VALUE="<% $part_export->exportnum %>">
+
+<% ntable("#cccccc",2) %>
+<TR>
+ <TD ALIGN="right">Export host</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="machine" VALUE="<% $part_export->machine %>">
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Export</TD>
+ <TD><% $widget->html %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#if ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {
+# $cgi->param('clone', $1);
+#} else {
+# $cgi->param('clone', '');
+#}
+
+my($query) = $cgi->keywords;
+my $action = '';
+my $part_export = '';
+if ( $cgi->param('error') ) {
+ $part_export = new FS::part_export ( {
+ map { $_, scalar($cgi->param($_)) } fields('part_export')
+ } );
+} elsif ( $query =~ /^(\d+)$/ ) {
+ $part_export = qsearchs('part_export', { 'exportnum' => $1 } );
+} else {
+ $part_export = new FS::part_export;
+}
+$action ||= $part_export->exportnum ? 'Edit' : 'Add';
+
+#my $exports = FS::part_export::export_info($svcdb);
+my $exports = FS::part_export::export_info();
+
+my %layers = map { $_ => "$_ - ". $exports->{$_}{desc} } keys %$exports;
+$layers{''}='';
+
+my $widget = new HTML::Widgets::SelectLayers(
+ 'selected_layer' => $part_export->exporttype,
+ 'options' => \%layers,
+ 'form_name' => 'dummy',
+ 'form_action' => 'process/part_export.cgi',
+ 'form_text' => [qw( exportnum machine )],
+# 'form_checkbox' => [qw()],
+ 'html_between' => "</TD></TR></TABLE>\n",
+ 'layer_callback' => sub {
+ my $layer = shift;
+ my $html = qq!<INPUT TYPE="hidden" NAME="exporttype" VALUE="$layer">!.
+ ntable("#cccccc",2);
+
+ $html .= '<TR><TD ALIGN="right">Description</TD><TD BGCOLOR=#ffffff>'.
+ $exports->{$layer}{notes}. '</TD></TR>'
+ if $layer;
+
+ foreach my $option ( keys %{$exports->{$layer}{options}} ) {
+ my $optinfo = $exports->{$layer}{options}{$option};
+ die "Retreived non-ref export info option from $layer export: $optinfo"
+ unless ref($optinfo);
+ my $label = $optinfo->{label};
+ my $type = defined($optinfo->{type}) ? $optinfo->{type} : 'text';
+ my $value = $cgi->param($option)
+ || ( $part_export->exportnum && $part_export->option($option) )
+ || ( (exists $optinfo->{default} && !$part_export->exportnum)
+ ? $optinfo->{default}
+ : ''
+ );
+ $html .= qq!<TR><TD ALIGN="right">$label</TD><TD>!;
+ if ( $type eq 'select' ) {
+ $html .= qq!<SELECT NAME="$option">!;
+ foreach my $select_option ( @{$optinfo->{options}} ) {
+ #if ( ref($select_option) ) {
+ #} else {
+ my $selected = $select_option eq $value ? ' SELECTED' : '';
+ $html .= qq!<OPTION VALUE="$select_option"$selected>!.
+ qq!$select_option</OPTION>!;
+ #}
+ }
+ $html .= '</SELECT>';
+ } elsif ( $type eq 'textarea' ) {
+ $html .= qq!<TEXTAREA NAME="$option" COLS=80 ROWS=8 WRAP="virtual">!.
+ encode_entities($value). '</TEXTAREA>';
+ } elsif ( $type eq 'text' ) {
+ $html .= qq!<INPUT TYPE="text" NAME="$option" VALUE="!.
+ encode_entities($value). '" SIZE=64>';
+ } elsif ( $type eq 'checkbox' ) {
+ $html .= qq!<INPUT TYPE="checkbox" NAME="$option" VALUE="1"!;
+ $html .= ' CHECKED' if $value;
+ $html .= '>';
+ } else {
+ $html .= "unknown type $type";
+ }
+ $html .= '</TD></TR>';
+ }
+ $html .= '</TABLE>';
+
+ $html .= '<INPUT TYPE="hidden" NAME="options" VALUE="'.
+ join(',', keys %{$exports->{$layer}{options}} ). '">';
+
+ $html .= '<INPUT TYPE="hidden" NAME="nodomain" VALUE="'.
+ $exports->{$layer}{nodomain}. '">';
+
+ $html .= '<INPUT TYPE="submit" VALUE="'.
+ ( $part_export->exportnum ? "Apply changes" : "Add export" ).
+ '">';
+
+ $html;
+ },
+);
+
+</%init>
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
new file mode 100755
index 000000000..f40469937
--- /dev/null
+++ b/httemplate/edit/part_pkg.cgi
@@ -0,0 +1,637 @@
+<% include( 'elements/edit.html',
+ 'post_url' => popurl(1).'process/part_pkg.cgi',
+ 'name' => "Package definition",
+ 'table' => 'part_pkg',
+
+ 'agent_virt' => 1,
+ 'agent_null_right' => $edit_global,
+ 'agent_clone_extra_sql' => $agent_clone_extra_sql,
+ #'viewall_dir' => 'browse',
+ 'viewall_url' => $p.'browse/part_pkg.cgi',
+ 'html_init' => include('/elements/init_overlib.html').
+ $javascript,
+ 'html_bottom' => $html_bottom,
+ 'body_etc' =>
+ 'onLoad="agent_changed(document.edit_topform.agentnum)"',
+
+ 'begin_callback' => $begin_callback,
+ 'end_callback' => $end_callback,
+ 'new_hashref_callback' => $new_hashref_callback,
+ 'new_object_callback' => $new_object_callback,
+ 'new_callback' => $new_callback,
+ 'clone_callback' => $clone_callback,
+ 'edit_callback' => $edit_callback,
+ 'error_callback' => $error_callback,
+ 'field_callback' => $field_callback,
+
+ 'labels' => {
+ 'pkgpart' => 'Package Definition',
+ 'pkg' => 'Package (customer-visible)',
+ 'comment' => 'Comment (customer-hidden)',
+ 'classnum' => 'Package class',
+ 'promo_code' => 'Promotional code',
+ 'freq' => 'Recurring fee frequency',
+ 'setuptax' => 'Setup fee tax exempt',
+ 'recurtax' => 'Recurring fee tax exempt',
+ 'taxclass' => 'Tax class',
+ 'taxproduct_select'=> 'Tax products',
+ 'plan' => 'Price plan',
+ 'disabled' => 'Disable new orders',
+ 'pay_weight' => 'Payment weight',
+ 'credit_weight' => 'Credit weight',
+ 'agentnum' => 'Agent',
+ 'setup_fee' => 'Setup fee',
+ 'recur_fee' => 'Recurring fee',
+ 'bill_dst_pkgpart' => 'Include line item(s) from package',
+ 'svc_dst_pkgpart' => 'Include services of package',
+ },
+
+ 'fields' => [
+ { field=>'clone', type=>'hidden',
+ curr_value_callback =>
+ sub { shift->param('clone') },
+ },
+ { field=>'pkgnum', type=>'hidden',
+ curr_value_callback =>
+ sub { shift->param('pkgnum') },
+ },
+
+ { type => 'columnstart' },
+
+ { field => 'pkg',
+ type => 'text',
+ size => 40, #32
+ maxlength => 50,
+ },
+ {field=>'comment', type=>'text', size=>40 }, #32
+ { field => 'agentnum',
+ type => 'select-agent',
+ disable_empty => ! $acl_edit_global,
+ empty_label => '(global)',
+ onchange => 'agent_changed',
+ },
+ {field=>'classnum', type=>'select-pkg_class' },
+ {field=>'disabled', type=>$disabled_type, value=>'Y'},
+
+ { type => 'tablebreak-tr-title',
+ value => 'Pricing', #better name?
+ },
+ { field => 'plan',
+ type => 'selectlayers-select',
+ options => [ keys %plan_labels ],
+ labels => \%plan_labels,
+ },
+ { field => 'setup_fee',
+ type => 'money',
+ },
+ { field => 'freq',
+ type => 'part_pkg_freq',
+ onchange => 'freq_changed',
+ },
+ { field => 'recur_fee',
+ type => 'money',
+ disabled => sub { $recur_disabled },
+ },
+
+ #price plan
+ #setup fee
+ #recurring frequency
+ #recurring fee (auto-disable)
+
+ { type => 'columnnext' },
+
+ {type=>'justtitle', value=>'Taxation' },
+ {field=>'setuptax', type=>'checkbox', value=>'Y'},
+ {field=>'recurtax', type=>'checkbox', value=>'Y'},
+ {field=>'taxclass', type=>'select-taxclass' },
+ { field => 'taxproductnums',
+ type => 'hidden',
+ value => join(',', @taxproductnums),
+ },
+ { field => 'taxproduct_select',
+ type => 'selectlayers',
+ options => [ '(default)', @taxproductnums ],
+ curr_value => '(default)',
+ labels => { ( '(default)' => '(default)' ),
+ map {($_=>$usage_class{$_})}
+ @taxproductnums
+ },
+ layer_fields => \%taxproduct_fields,
+ layer_values_callback => $taxproduct_values,
+ layers_only => !$taxproducts,
+ cell_style => ( !$taxproducts
+ ? 'display:none'
+ : ''
+ ),
+ },
+
+ { type => 'tablebreak-tr-title',
+ value => 'Promotions', #better name?
+ },
+ { field=>'promo_code', type=>'text', size=>15 },
+
+ { type => 'tablebreak-tr-title',
+ value => 'Line-item revenue recogition', #better name?
+ },
+ { field=>'pay_weight', type=>'text', size=>6 },
+ { field=>'credit_weight', type=>'text', size=>6 },
+
+ { type => 'columnnext' },
+
+ { field => 'agent_type',
+ type => 'select-agent_types',
+ disabled => ! $acl_edit_global,
+ curr_value_callback => sub {
+ my($cgi, $object, $field) = @_;
+ #in the other callbacks..? hmm.
+ \@agent_type;
+ },
+ },
+
+ { type => 'columnend' },
+
+ { 'type' => 'tablebreak-tr-title',
+ 'value' => 'Pricing add-ons',
+ },
+ { 'field' => 'bill_dst_pkgpart',
+ 'type' => 'select-part_pkg',
+ 'm2_label' => 'Include line item(s) from package',
+ 'm2m_method' => 'bill_part_pkg_link',
+ 'm2m_dstcol' => 'dst_pkgpart',
+ 'm2_error_callback' =>
+ &{$m2_error_callback_maker}('bill'),
+ },
+
+ { type => 'tablebreak-tr-title',
+ value => 'Services',
+ },
+ { type => 'pkg_svc', },
+
+ { 'field' => 'svc_dst_pkgpart',
+ 'label' => 'Also include services from package: ',
+ 'type' => 'select-part_pkg',
+ 'm2_label' => 'Include services of package: ',
+ 'm2m_method' => 'svc_part_pkg_link',
+ 'm2m_dstcol' => 'dst_pkgpart',
+ 'm2_error_callback' =>
+ &{$m2_error_callback_maker}('svc'),
+ },
+
+ { type => 'tablebreak-tr-title',
+ value => 'Price plan options',
+ },
+
+ ],
+
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $edit_global = 'Edit global package definitions';
+my $acl_edit = $curuser->access_right('Edit package definitions');
+my $acl_edit_global = $curuser->access_right($edit_global);
+
+my $acl_edit_either = $acl_edit || $acl_edit_global;
+
+my $begin_callback = sub {
+ my( $cgi, $fields, $opt ) = @_;
+ die "access denied"
+ unless $acl_edit_either
+ || ( $cgi->param('pkgnum')
+ && $curuser->access_right('Customize customer package')
+ );
+};
+
+my $disabled_type = $acl_edit_either ? 'checkbox' : 'hidden';
+
+my $agent_clone_extra_sql =
+ ' ( '. FS::part_pkg->curuser_pkgs_sql.
+ #kludge to clone custom customer packages you otherwise couldn't see
+ " OR ( part_pkg.disabled = 'Y' AND part_pkg.comment LIKE '(CUSTOM)%' ) ".
+ ' ) ';
+
+my $conf = new FS::Conf;
+my $taxproducts = $conf->exists('enable_taxproducts');
+
+#XXX
+# - tr-part_pkg_freq: month_increments_only (from price plans)
+# - test cloning
+# - test errors cloning
+# - test custom pricing
+# - move the selectlayer divs away from lame layer_callback
+
+#my ($query) = $cgi->keywords;
+#
+#my $part_pkg = '';
+
+my @agent_type = ();
+my %tax_override = ();
+
+my %taxproductnums = map { ($_->classnum => 1) }
+ qsearch('usage_class', { 'disabled' => '' });
+my @taxproductnums = ( qw( setup recur ), sort (keys %taxproductnums) );
+
+my %options = ();
+my $recur_disabled = 1;
+
+my $error_callback = sub {
+ my($cgi, $object, $fields, $opt ) = @_;
+
+ (@agent_type) = $cgi->param('agent_type');
+
+ $opt->{action} = 'Custom' if $cgi->param('pkgnum');
+
+ $recur_disabled = $cgi->param('freq') ? 0 : 1;
+
+ foreach ($cgi->param) {
+ /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
+ }
+ $tax_override{''} = $cgi->param('tax_override');
+ $tax_override{$_} = $cgi->param('tax_override_$_')
+ foreach(grep { /^tax_override_(\w+)$/ } $cgi->param);
+
+ #some false laziness w/process
+ $cgi->param('plan') =~ /^(\w+)$/ or die 'unparsable plan';
+ my $plan = $1;
+ my $options = $cgi->param($plan."__OPTIONS");
+ my @options = split(',', $options);
+ %options =
+ map { my $optionname = $_;
+ my $param = $plan."__$optionname";
+ my $value = join(', ', $cgi->param($param));
+ ( $optionname => $value );
+ }
+ @options;
+
+ #$cgi->param($_, $options{$_}) foreach (qw( setup_fee recur_fee ));
+ $object->set($_ => scalar($cgi->param($_)) )
+ foreach (qw( setup_fee recur_fee ));
+
+};
+
+my $new_hashref_callback = sub { { 'plan' => 'flat' }; };
+
+my $new_object_callback = sub {
+ my( $cgi, $hashref, $fields, $opt ) = @_;
+
+ my $part_pkg = FS::part_pkg->new( $hashref );
+ $part_pkg->set($_ => '0')
+ foreach (qw( setup_fee recur_fee ));
+
+ $part_pkg;
+
+};
+
+my $edit_callback = sub {
+ my( $cgi, $object, $fields, $opt ) = @_;
+
+ $recur_disabled = $object->freq ? 0 : 1;
+
+ (@agent_type) = map {$_->typenum} qsearch('type_pkgs',{'pkgpart'=>$1});
+
+ foreach ($object->options) {
+ /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
+ }
+ foreach ($object->part_pkg_taxoverride) {
+ $taxproductnums{$_->usage_class} = 1
+ if $_->usage_class;
+ }
+
+ %options = $object->options;
+
+ $object->set($_ => $object->option($_))
+ foreach (qw( setup_fee recur_fee ));
+
+};
+
+my $new_callback = sub {
+ my( $cgi, $object, $fields ) = @_;
+
+ my $conf = new FS::Conf;
+ if ( $conf->exists('agent_defaultpkg') ) {
+ #my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
+ @agent_type = map {$_->typenum} qsearch('agent_type',{});
+ }
+
+};
+
+my $clone_callback = sub {
+ my( $cgi, $object, $fields, $opt ) = @_;
+
+ if ( $cgi->param('pkgnum') ) {
+
+ my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cgi->param('pkgnum') } );
+ $object->agentnum( $cust_pkg->cust_main->agentnum );
+
+ $opt->{action} = 'Custom';
+
+ #my $part_pkg = $clone_part_pkg->clone;
+ #this is all clone did anyway
+ $object->comment( '(CUSTOM) '. $object->comment )
+ unless $object->comment =~ /^\(CUSTOM\) /;
+
+ $object->disabled('Y');
+
+ }
+
+ %options = $object->options;
+
+ $object->set($_ => $options{$_})
+ foreach (qw( setup_fee recur_fee ));
+
+ $recur_disabled = $object->freq ? 0 : 1;
+};
+
+my $m2_error_callback_maker = sub {
+ my $link_type = shift; #yay closures
+ return sub {
+ my( $cgi, $object ) = @_;
+ map {
+ new FS::part_pkg_link {
+ 'link_type' => $link_type,
+ 'src_pkgpart' => $object->pkgpart,
+ 'dst_pkgpart' => $_,
+ };
+ }
+ grep $_,
+ map $cgi->param($_),
+ grep /^${link_type}_dst_pkgpart(\d+)$/, $cgi->param;
+ };
+};
+
+my $javascript = <<'END';
+ <SCRIPT TYPE="text/javascript">
+
+ function freq_changed(what) {
+ var freq = what.options[what.selectedIndex].value;
+
+ if ( freq == '0' ) {
+ what.form.recur_fee.disabled = true;
+ what.form.recur_fee.style.backgroundColor = '#dddddd';
+ } else {
+ what.form.recur_fee.disabled = false;
+ what.form.recur_fee.style.backgroundColor = '#ffffff';
+ }
+
+ }
+
+ function agent_changed(what) {
+
+ var agentnum = what.options[what.selectedIndex].value;
+
+ if ( agentnum == 0 ) {
+ what.form.agent_type.disabled = false;
+ //what.form.agent_type.style.backgroundColor = '#ffffff';
+ what.form.agent_type.style.visibility = '';
+ } else {
+ what.form.agent_type.disabled = true;
+ //what.form.agent_type.style.backgroundColor = '#dddddd';
+ what.form.agent_type.style.visibility = 'hidden';
+ }
+
+ }
+
+ </SCRIPT>
+END
+
+tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() };
+
+tie my %plan_labels, 'Tie::IxHash',
+ map { $_ => ( $plans{$_}->{'shortname'} || $plans{$_}->{'name'} ) }
+ keys %plans;
+
+my $html_bottom = sub {
+ my( $object ) = @_;
+
+ #warn join("\n", map { "$_: $options{$_}" } keys %options ). "\n";
+
+ my $layer_callback = sub {
+
+ my $layer = shift;
+ my $html = ntable("#cccccc",2);
+
+ #$html .= '
+ # <TR>
+ # <TD ALIGN="right">Recurring fee frequency </TD>
+ # <TD><SELECT NAME="freq">
+ #';
+ #
+ #my @freq = keys %freq;
+ #@freq = grep { /^\d+$/ } @freq
+ #XXX this bit# # if exists($plans{$layer}->{'freq'}) && $plans{$layer}->{'freq'} eq 'm';
+ #foreach my $freq ( @freq ) {
+ # $html .= qq(<OPTION VALUE="$freq");
+ # $html .= ' SELECTED' if $freq eq $part_pkg->freq;
+ # $html .= ">$freq{$freq}";
+ #}
+ #$html .= '</SELECT></TD></TR>';
+
+ my $href = $plans{$layer}->{'fields'};
+ my @fields = exists($plans{$layer}->{'fieldorder'})
+ ? @{$plans{$layer}->{'fieldorder'}}
+ : keys %{ $href };
+
+ foreach my $field ( grep $_ !~ /^(setup|recur)_fee$/, @fields ) {
+
+ $html .= '<TR><TD ALIGN="right">'. $href->{$field}{'name'}. '</TD><TD>';
+
+ my $format = sub { shift };
+ $format = $href->{$field}{'format'} if exists($href->{$field}{'format'});
+
+ #XXX these should use elements/ fields... (or this whole thing should
+ #just use layer_fields instead of layer_callback)
+
+ if ( ! exists($href->{$field}{'type'}) ) {
+
+ $html .= qq!<INPUT TYPE="text" NAME="${layer}__$field" VALUE="!.
+ ( exists($options{$field})
+ ? &$format($options{$field})
+ : $href->{$field}{'default'} ).
+ qq!">!;
+
+ } elsif ( $href->{$field}{'type'} eq 'checkbox' ) {
+
+ $html .= qq!<INPUT TYPE="checkbox" NAME="${layer}__$field" VALUE=1 !.
+ ( exists($options{$field}) && $options{$field}
+ ? ' CHECKED'
+ : ''
+ ). '>';
+
+ } elsif ( $href->{$field}{'type'} =~ /^select/ ) {
+
+ $html .= '<SELECT';
+ $html .= ' MULTIPLE'
+ if $href->{$field}{'type'} eq 'select_multiple';
+ $html .= qq! NAME="${layer}__$field">!;
+
+ if ( $href->{$field}{'select_table'} ) {
+ foreach my $record (
+ qsearch( $href->{$field}{'select_table'},
+ $href->{$field}{'select_hash'} )
+ ) {
+ my $value = $record->getfield($href->{$field}{'select_key'});
+ $html .= qq!<OPTION VALUE="$value"!.
+ ( $options{$field} =~ /(^|, *)$value *(,|$)/ #?
+ ? ' SELECTED'
+ : ''
+ ).
+ '>'. $record->getfield($href->{$field}{'select_label'});
+ }
+ } elsif ( $href->{$field}{'select_options'} ) {
+ foreach my $key ( keys %{ $href->{$field}{'select_options'} } ) {
+ my $label = $href->{$field}{'select_options'}{$key};
+ $html .= qq!<OPTION VALUE="$key"!.
+ ( $options{$field} =~ /(^|, *)$key *(,|$)/ #?
+ ? ' SELECTED'
+ : ''
+ ).
+ '>'. $label;
+ }
+
+ } else {
+ $html .= '<font color="#ff0000">warning: '.
+ "don't know how to retreive options for $field select field".
+ '</font>';
+ }
+ $html .= '</SELECT>';
+
+ } elsif ( $href->{$field}{'type'} eq 'radio' ) {
+
+ my $radio =
+ qq!<INPUT TYPE="radio" NAME="${layer}__$field"!;
+
+ foreach my $key ( keys %{ $href->{$field}{'options'} } ) {
+ my $label = $href->{$field}{'options'}{$key};
+ $html .= qq!$radio VALUE="$key"!.
+ ( $options{$field} =~ /(^|, *)$key *(,|$)/ #?
+ ? ' CHECKED'
+ : ''
+ ).
+ "> $label<BR>";
+ }
+
+ }
+
+ $html .= '</TD></TR>';
+ }
+ $html .= '</TABLE>';
+
+ $html .= qq(<INPUT TYPE="hidden" NAME="${layer}__OPTIONS" VALUE=").
+ join(',', keys %{ $href } ). '">';
+
+ $html;
+
+ };
+
+ my %selectlayers = (
+ field => 'plan',
+ options => [ keys %plan_labels ],
+ labels => \%plan_labels,
+ curr_value => $object->plan,
+ layer_callback => $layer_callback,
+ );
+
+ my $return =
+ include('/elements/selectlayers.html', %selectlayers, 'layers_only'=>1 ).
+ '<SCRIPT TYPE="text/javascript">'.
+ include('/elements/selectlayers.html', %selectlayers, 'js_only'=>1 );
+
+ $return .=
+ "taxproduct_selectchanged(document.getElementById('taxproduct_select'));\n"
+ if $taxproducts;
+
+ $return .= '</SCRIPT>';
+
+ $return;
+
+};
+
+my %usage_class = map { ($_->classnum => $_->classname) }
+ qsearch('usage_class', {});
+$usage_class{setup} = 'Setup';
+$usage_class{recur} = 'Recurring';
+
+my %taxproduct_fields = ();
+my $end_callback = sub {
+ my( $cgi, $object, $fields, $opt ) = @_;
+
+ @taxproductnums = ( qw( setup recur ), sort (keys %taxproductnums) );
+
+ if ( $object->pkgpart ) {
+ foreach my $usage_class ( '', @taxproductnums ) {
+ $tax_override{$usage_class} =
+ join (",", map $_->taxclassnum,
+ qsearch( 'part_pkg_taxoverride', {
+ 'pkgpart' => $object->pkgpart,
+ 'usage_class' => $usage_class,
+ })
+ );
+ }
+ }
+
+ %taxproduct_fields =
+ map { $_ => [ "taxproductnum_$_",
+ { type => 'select-taxproduct',
+ #label => "$usage_class{$_} tax product",
+ },
+ "tax_override_$_",
+ { type => 'select-taxoverride' }
+ ]
+ }
+ @taxproductnums;
+
+ $taxproduct_fields{'(default)'} =
+ [ 'taxproductnum', { type => 'select-taxproduct',
+ #label => 'Default tax product',
+ },
+ 'tax_override', { type => 'select-taxoverride' },
+ ];
+};
+
+my $taxproduct_values = sub {
+ my ($cgi, $object, $flags) = @_;
+ my $routine =
+ sub { my $layer = shift;
+ my @fields = @{$taxproduct_fields{$layer}};
+ my @values = ();
+ while( @fields ) {
+ my $field = shift @fields;
+ shift @fields;
+ $field =~ /^taxproductnum_\w+$/ &&
+ push @values, ( $field => $options{"usage_$field"} );
+ $field =~ /^tax_override_(\w+)$/ &&
+ push @values, ( $field => $tax_override{$1} );
+ $field =~ /^taxproductnum$/ &&
+ push @values, ( $field => $object->taxproductnum );
+ $field =~ /^tax_override$/ &&
+ push @values, ( $field => $tax_override{''} );
+ }
+ { (@values) };
+ };
+
+ my @result =
+ map { ( $_ => { &{$routine}($_) } ) } ( '(default)', @taxproductnums );
+ return({ @result });
+
+};
+
+my $field_callback = sub {
+ my ($cgi, $object, $fieldref) = @_;
+
+ my $field = $fieldref->{field};
+ if ($field eq 'taxproductnums') {
+ $fieldref->{value} = join(',', @taxproductnums);
+ } elsif ($field eq 'taxproduct_select') {
+ $fieldref->{options} = [ '(default)', @taxproductnums ];
+ $fieldref->{labels} = { ( '(default)' => '(default)' ),
+ map {( $_ => ($usage_class{$_} || $_) )}
+ @taxproductnums
+ };
+ $fieldref->{layer_fields} = \%taxproduct_fields;
+ $fieldref->{layer_values_callback} = $taxproduct_values;
+ }
+};
+
+</%init>
diff --git a/httemplate/edit/part_pkg_taxclass.html b/httemplate/edit/part_pkg_taxclass.html
new file mode 100644
index 000000000..e76705722
--- /dev/null
+++ b/httemplate/edit/part_pkg_taxclass.html
@@ -0,0 +1,32 @@
+<% include('/elements/header.html', "$action taxclass") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/part_pkg_taxclass.html" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="taxclassnum" VALUE="">
+
+Tax class <INPUT TYPE="text" NAME="taxclass" VALUE="<% $taxclass |h %>">
+
+<BR><BR>
+<INPUT TYPE="submit" VALUE="<% $action %> taxclass">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $taxclass = '';
+if ( $cgi->param('error') ) {
+ $taxclass = $cgi->param('taxclass');
+}
+
+my $action = 'Add';
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/part_pkg_taxoverride.html b/httemplate/edit/part_pkg_taxoverride.html
new file mode 100644
index 000000000..61dfa2ac5
--- /dev/null
+++ b/httemplate/edit/part_pkg_taxoverride.html
@@ -0,0 +1,132 @@
+<% include('/elements/header-popup.html', 'Override taxes', '', 'onload="resizeFrames()"') %>
+
+<TABLE WIDTH="100%" HEIGHT="100%">
+ <TR><TD>
+ <iframe name="selected" src="<% $p %>browse/tax_class.html?_type=select;magic=select;maxrecords=15;offset=<% $selected_offset %>;selected=<% $selected %>;" width="100%" frameborder="0" border="0" id="selectorSelected" scrolling="no">
+</iframe>
+ <BR>
+ </TD></TR>
+
+ <TR><TD>
+<FORM="dummy">
+ <CENTER>
+ <INPUT type="submit" value="Finish" onclick="s=fetchSelected(); s.shift(); parent.document.getElementById('<% $element_name || "tax_override" %>').value=s.toString(); parent.<% $onclick %>();">
+ <INPUT type="reset" value="Cancel" onclick="parent.<% $onclick %>();">
+ </CENTER>
+</FORM>
+ </TD></TR>
+
+ <TR><TD>
+ <iframe name="unselected" src="<% $p %>browse/tax_class.html?_type=select;magic=omit;maxrecords=15;offset=<% $unselected_offset %>;omit=<% $selected %>;" width="100%" frameborder="0" border="0" id="selectorUnselected" scrolling="no">
+</iframe>
+ <BR>
+ </TD></TR>
+
+</TABLE>
+<SCRIPT>
+
+ function resizeFrames() {
+ //frames['selected'].style.height =
+ // frames['selected'].contentWindow.document.body.scrollHeight + "px";
+ //frames['unselected'].style.height =
+ // frames['unselected'].contentWindow.document.body.scrollHeight + "px";
+ var f = document.getElementById('selectorSelected');
+ f.style.height = f.contentWindow.document.body.scrollHeight + "px";
+ var f = document.getElementById('selectorUnselected');
+ f.style.height = f.contentWindow.document.body.scrollHeight + "px";
+ }
+
+ function fetchOffset(search) {
+ var value = 0;
+ if (search.length > 1) {
+ var params = search.split(';');
+ for (i=0; i<params.length; i++) {
+ if (params[i].substr(0,7) == 'offset=') {
+ value = params[i].substr(7);
+ }
+ }
+ }
+ return value;
+ }
+
+ function fetchOffsetStrings() {
+ return 'selected_offset=' +
+ fetchOffset(frames['selected'].location.search) + ';' +
+ 'unselected_offset=' +
+ fetchOffset(frames['unselected'].location.search) + ';';
+ }
+
+ function fetchSelected() {
+ var i;
+ var selected = new Array;
+ var replace = '?';
+ if (window.location.search.length > 1) {
+ var search = window.location.search.substr(1).split(';');
+ for (i=0; i<search.length; i++) {
+ if (search[i].substr(0,9) == 'selected=') {
+ selected = search[i].substr(9).split(',')
+ }else if (search[i].substr(0,16) == 'selected_offset=') {
+ }else if (search[i].substr(0,18) == 'unselected_offset=') {
+ }else if (search[i].length) {
+ replace += search[i] + ';';
+ }
+ }
+ }
+ selected.unshift(replace);
+ return selected;
+ }
+ function doUnselect(classnum) {
+ var selected = fetchSelected();
+ var search = selected.shift();
+ //alert("discovered: "+selected.toString());
+ var i=-1, j=-1, k=selected.length;
+ while(++j < k) {
+ if (!(selected[j]==classnum)) {
+ selected[++i]=selected[j];
+ }
+ }
+ selected.length = ++i;
+ //alert("finished: "+selected.toString());
+
+ search += "selected=" + selected.toString() + ';';
+ window.location.search = search + fetchOffsetStrings();
+ }
+ function doSelect(classnum) {
+ var selected = fetchSelected();
+ var search = selected.shift();
+ selected.push(classnum);
+ search += "selected=" + selected.toString() + ';';
+ window.location.search = search + fetchOffsetStrings();
+ }
+</SCRIPT>
+
+<% include('/elements/footer.html') %>
+<%once>
+
+my $conf = new FS::Conf;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+
+my $selected_offset = $1
+ if $cgi->param('selected_offset') =~/^(\d+)$/;
+
+my $unselected_offset = $1
+ if $cgi->param('unselected_offset') =~/^(\d+)$/;
+
+my $selected = $1
+ if $cgi->param('selected') =~/^([,\d]+)$/;
+
+my $element_name = $1
+ if $cgi->param('element_name') =~/^(\w+)$/;
+
+my $onclick = $1
+ if $cgi->param('onclick') =~/^(\w+)$/;
+
+$onclick = 'cClick' unless $onclick;
+
+</%init>
diff --git a/httemplate/edit/part_referral.html b/httemplate/edit/part_referral.html
new file mode 100755
index 000000000..daf8773f0
--- /dev/null
+++ b/httemplate/edit/part_referral.html
@@ -0,0 +1,19 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Advertising source',
+ 'table' => 'part_referral',
+ 'fields' => [ 'referral',
+ { field=>'agentnum', type=>'select-agent', },
+ ],
+ 'labels' => { 'referral' => 'Advertising source',
+ 'agentnum' => 'Agent',
+ },
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit advertising sources')
+ || $FS::CurrentUser::CurrentUser->access_right('Edit global advertising sources');
+
+</%init>
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
new file mode 100755
index 000000000..e0fb615b1
--- /dev/null
+++ b/httemplate/edit/part_svc.cgi
@@ -0,0 +1,361 @@
+<% include('/elements/header.html', "$action Service Definition",
+ menubar('View all service definitions' => "${p}browse/part_svc.cgi"),
+ #" onLoad=\"visualize()\""
+ )
+%>
+
+<FORM NAME="dummy">
+
+ Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>
+<BR><BR>
+Service <INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"><BR>
+Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR>
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $hashref->{svcpart} %>">
+<BR>
+Service definitions are the templates for items you offer to your customers.
+<UL><LI>svc_acct - Accounts - anything with a username (Mailboxes, PPP accounts, shell accounts, RADIUS entries for broadband, etc.)
+ <LI>svc_domain - Domains
+ <LI>svc_forward - mail forwarding
+ <LI>svc_www - Virtual domain website
+ <LI>svc_broadband - Broadband/High-speed Internet service (always-on)
+ <LI>svc_phone - Customer phone numbers
+ <LI>svc_external - Externally-tracked service
+<!-- <LI>svc_charge - One-time charges (Partially unimplemented)
+ <LI>svc_wo - Work orders (Partially unimplemented)
+-->
+</UL>
+For the selected table, you can give fields default or fixed (unchangable)
+values, or select an inventory class to manually or automatically fill in
+that field.
+<BR><BR>
+
+% #YUCK. false laziness w/part_svc.pm. go away virtual fields, please
+% my %vfields;
+% foreach my $svcdb ( FS::part_svc->svc_tables() ) {
+% eval "use FS::$svcdb;";
+% my $self = "FS::$svcdb"->new;
+% $vfields{$svcdb} = {};
+% foreach my $field ($self->virtual_fields) { # svc_Common::virtual_fields with a null svcpart returns all of them
+% my $pvf = $self->pvf($field);
+% $vfields{$svcdb}->{$field} = $pvf;
+% #warn "\$vfields{$svcdb}->{$field} = $pvf";
+% } #next $field
+% } #next $svcdb
+%
+% #code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm
+% # and generalize the subs
+% # condition sub is tested to see whether to disable display of this choice
+% # params: ( $def, $layer, $field ) (see SUB below)
+% my $inv_sub = sub {
+% $_[0]->{disable_inventory}
+% || $_[0]->{'type'} ne 'text'
+% };
+% tie my %flag, 'Tie::IxHash',
+% '' => { 'desc' => 'No default', },
+% 'D' => { 'desc' => 'Default',
+% 'condition' =>
+% sub { $_[0]->{disable_default} },
+% },
+% 'F' => { 'desc' => 'Fixed (unchangeable)',
+% 'condition' =>
+% sub { $_[0]->{disable_fixed} },
+% },
+% 'S' => { 'desc' => 'Selectable Choice',
+% 'condition' =>
+% sub { !ref($_[0]) || $_[0]->{disable_select} },
+% },
+%# need to template-ize httemplate/edit/svc_* first
+%# 'M' => { 'desc' => 'Manual selection from inventory',
+%# 'condition' => $inv_sub,
+%# },
+% 'A' => { 'desc' => 'Automatically fill in from inventory',
+% 'condition' => $inv_sub,
+% },
+% 'X' => { 'desc' => 'Excluded',
+% 'condition' =>
+% sub { ! $vfields{$_[1]}->{$_[2]} },
+%
+% },
+% ;
+%
+% my @dbs = $hashref->{svcdb}
+% ? ( $hashref->{svcdb} )
+% : FS::part_svc->svc_tables();
+%
+% tie my %svcdb, 'Tie::IxHash', map { $_=>$_ } grep dbdef->table($_), @dbs;
+% my $widget = new HTML::Widgets::SelectLayers(
+% #'selected_layer' => $p_svcdb,
+% 'selected_layer' => $hashref->{svcdb} || 'svc_acct',
+% 'options' => \%svcdb,
+% 'form_name' => 'dummy',
+% #'form_action' => 'process/part_svc.cgi',
+% 'form_action' => 'part_svc.cgi', #self
+% 'form_text' => [ qw( svc svcpart ) ],
+% 'form_checkbox' => [ 'disabled' ],
+% 'layer_callback' => sub {
+% my $layer = shift;
+%
+% my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!;
+%
+% my $columns = 3;
+% my $count = 0;
+% my @part_export =
+% map { qsearch( 'part_export', {exporttype => $_ } ) }
+% keys %{FS::part_export::export_info($layer)};
+% $html .= '<BR><BR>'. table().
+% "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>";
+% foreach my $part_export ( @part_export ) {
+% $html .= '<TD><INPUT TYPE="checkbox"'.
+% ' NAME="exportnum'. $part_export->exportnum. '" VALUE="1" ';
+% $html .= 'CHECKED'
+% if ( $clone || $part_svc->svcpart ) #null svcpart search causing error
+% && qsearchs( 'export_svc', {
+% exportnum => $part_export->exportnum,
+% svcpart => $clone || $part_svc->svcpart });
+% $html .= '>'. $part_export->exportnum. ': '. $part_export->exporttype.
+% ' to '. $part_export->machine. '</TD>';
+% $count++;
+% $html .= '</TR><TR>' unless $count % $columns;
+% }
+% $html .= '</TR></TABLE><BR><BR>';
+%
+% $html .= include('/elements/table-grid.html', 'cellpadding' => 4 ).
+% '<TR>'.
+% '<TH CLASS="grid" BGCOLOR="#cccccc">Field</TH>'.
+% '<TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>'.
+% '</TR>';
+%
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% #yucky kludge
+% my @fields = defined( dbdef->table($layer) )
+% ? grep { $_ ne 'svcnum' } fields($layer)
+% : ();
+% push @fields, 'usergroup' if $layer eq 'svc_acct'; #kludge
+% $part_svc->svcpart($clone) if $clone; #haha, undone below
+%
+%
+% foreach my $field (@fields) {
+%
+% #my $def = $defs{$layer}{$field};
+% my $def = FS::part_svc->svc_table_fields($layer)->{$field};
+% my $label = $def->{'def_label'} || $def->{'label'};
+% my $formatter = $def->{'format'} || sub { shift };
+% my $part_svc_column = $part_svc->part_svc_column($field);
+% my $value = &$formatter($part_svc_column->columnvalue);
+% my $flag = $part_svc_column->columnflag;
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% $html .= qq!<TR><TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">!.
+% ( $label || $field ).
+% "</TD>";
+% $flag = '' if $def->{type} eq 'disabled';
+%
+% $html .= qq!<TD CLASS="grid" BGCOLOR="$bgcolor">!;
+%
+% if ( $def->{type} eq 'disabled' ) {
+%
+% $html .= 'No default';
+%
+% } else {
+%
+% $html .= qq!<SELECT NAME="${layer}__${field}_flag"!.
+% qq! onChange="${layer}__${field}_flag_changed(this)">!;
+%
+% foreach my $f ( keys %flag ) {
+%
+% #here is where the SUB from above is called, to skip some choices
+% next if $flag{$f}->{condition}
+% && &{ $flag{$f}->{condition} }( $def, $layer, $field );
+%
+% $html .= qq!<OPTION VALUE="$f"!.
+% ' SELECTED'x($flag eq $f ).
+% '>'. $flag{$f}->{desc};
+%
+% }
+%
+% $html .= '</SELECT>';
+%
+% $html .= join("\n",
+% '<SCRIPT>',
+% " function ${layer}__${field}_flag_changed(what) {",
+% ' var f = what.options[what.selectedIndex].value;',
+% ' if ( f == "" || f == "X" ) { //disable',
+% " what.form.${layer}__${field}.disabled = true;".
+% " what.form.${layer}__${field}.style.backgroundColor = '#dddddd';".
+% " if ( what.form.${layer}__${field}_classnum ) {".
+% " what.form.${layer}__${field}_classnum.disabled = true;".
+% " what.form.${layer}__${field}_classnum.style.backgroundColor = '#dddddd';".
+% " }".
+% ' } else if ( f == "D" || f == "F" || f =="S" ) { //enable, text box',
+% " what.form.${layer}__${field}.disabled = false;".
+% " what.form.${layer}__${field}.style.backgroundColor = '#ffffff';".
+% " if ( f == 'S' || '${field}' == 'usergroup' ) {". # kludge
+% " what.form.${layer}__${field}.multiple = true;".
+% " } else {".
+% " what.form.${layer}__${field}.multiple = false;".
+% " }".
+% " what.form.${layer}__${field}.style.display = '';".
+% " if ( what.form.${layer}__${field}_classnum ) {".
+% " what.form.${layer}__${field}_classnum.disabled = false;".
+% " what.form.${layer}__${field}_classnum.style.backgroundColor = '#ffffff';".
+% " what.form.${layer}__${field}_classnum.style.display = 'none';".
+% " }".
+% ' } else if ( f == "M" || f == "A" ) { //enable, inventory',
+% " what.form.${layer}__${field}.disabled = false;".
+% " what.form.${layer}__${field}.style.backgroundColor = '#ffffff';".
+% " what.form.${layer}__${field}.style.display = 'none';".
+% " if ( what.form.${layer}__${field}_classnum ) {".
+% " what.form.${layer}__${field}_classnum.disabled = false;".
+% " what.form.${layer}__${field}_classnum.style.backgroundColor = '#ffffff';".
+% " what.form.${layer}__${field}_classnum.style.display = '';".
+% " }".
+% ' }',
+% ' }',
+% '</SCRIPT>',
+% );
+%
+% }
+%
+% $html .= qq!</TD><TD CLASS="grid" BGCOLOR="$bgcolor">!;
+%
+% my $disabled = $flag ? ''
+% : 'DISABLED STYLE="background-color: #dddddd"';
+%
+% if ( !$def->{type} || $def->{type} eq 'text' ) {
+%
+% my $nodisplay = ' STYLE="display:none"';
+% my $is_inv = ( $flag =~ /^[MA]$/ );
+%
+% $html .=
+% qq!<INPUT TYPE="text" NAME="${layer}__${field}" VALUE="$value" !.
+% $disabled.
+% ( $is_inv ? $nodisplay : $disabled ).
+% '>';
+%
+% $html .= include('/elements/select-table.html',
+% 'element_name' => "${layer}__${field}_classnum",
+% 'element_etc' => ( $is_inv
+% ? $disabled
+% : $nodisplay
+% ),
+% 'table' => 'inventory_class',
+% 'name_col' => 'classname',
+% 'value' => $value,
+% 'empty_label' => 'Select inventory class',
+% );
+%
+% } elsif ( $def->{type} eq 'select' ) {
+%
+% $html .= qq!<SELECT NAME="${layer}__${field}" $disabled!;
+% $html .= ' MULTIPLE' if $flag eq 'S';
+% $html .= '>';
+% $html .= '<OPTION> </OPTION>' unless $value;
+% if ( $def->{select_table} ) {
+% foreach my $record ( qsearch( $def->{select_table}, {} ) ) {
+% my $rvalue = $record->getfield($def->{select_key});
+% my $select_label = $def->{select_label};
+% $html .= qq!<OPTION VALUE="$rvalue"!.
+% (grep(/^$rvalue$/, split(',',$value)) ? ' SELECTED>' : '>' ).
+% $record->$select_label(). '</OPTION>';
+% } #next $record
+% } else { # select_list
+% foreach my $item ( @{$def->{select_list}} ) {
+% $html .= qq!<OPTION VALUE="$item"!.
+% (grep(/^$item$/, split(',',$value)) ? ' SELECTED>' : '>' ).
+% $item. '</OPTION>';
+% } #next $item
+% } #endif
+% $html .= '</SELECT>';
+%
+% } elsif ( $def->{type} eq 'radius_usergroup_selector' ) {
+%
+% #XXX disable the RADIUS usergroup selector? ugh it sure does need
+% #an overhaul, people have dum group problems because of it
+%
+% $html .= FS::svc_acct::radius_usergroup_selector(
+% [ split(',', $value) ], "${layer}__${field}" );
+%
+% } elsif ( $def->{type} eq 'disabled' ) {
+%
+% $html .=
+% qq!<INPUT TYPE="hidden" NAME="${layer}__${field}" VALUE="">!;
+%
+% } else {
+%
+% $html .= '<font color="#ff0000">unknown type'. $def->{type};
+%
+% }
+%
+% $html .= "</TD></TR>\n";
+%
+% } #foreach my $field (@fields) {
+%
+% $part_svc->svcpart('') if $clone; #undone
+% $html .= "</TABLE>";
+%
+% $html .= include('/elements/progress-init.html',
+% $layer, #form name
+% [ qw(svc svcpart disabled exportnum), @fields ],
+% 'process/part_svc.cgi',
+% $p.'browse/part_svc.cgi',
+% $layer,
+% );
+% $html .= '<BR><INPUT NAME="submit" TYPE="button" VALUE="'.
+% ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '" '.
+% ' onClick="document.'. "$layer.submit.disabled=true; ".
+% "fixup(document.$layer); $layer". 'process();">';
+%
+% #$html .= '<BR><INPUT TYPE="submit" VALUE="'.
+% # ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '">';
+%
+% $html;
+%
+% },
+% );
+%
+%
+
+Table <% $widget->html %>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $part_svc;
+my $clone = '';
+if ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {#clone
+ #$cgi->param('clone') =~ /^(\d+)$/ or die "malformed query: $query";
+ $part_svc = qsearchs('part_svc', { 'svcpart'=>$1 } )
+ or die "unknown svcpart: $1";
+ $clone = $part_svc->svcpart;
+ $part_svc->svcpart('');
+} elsif ( $cgi->keywords ) { #edit
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "malformed query: $query";
+ $part_svc=qsearchs('part_svc', { 'svcpart'=>$1 } )
+ or die "unknown svcpart: $1";
+} else { #adding
+ $part_svc = new FS::part_svc {};
+}
+
+my $action = $part_svc->svcpart ? 'Edit' : 'Add';
+my $hashref = $part_svc->hashref;
+# my $p_svcdb = $part_svc->svcdb || 'svc_acct';
+
+
+
+</%init>
+
+
+
diff --git a/httemplate/edit/part_virtual_field.cgi b/httemplate/edit/part_virtual_field.cgi
new file mode 100644
index 000000000..04ba9b0c0
--- /dev/null
+++ b/httemplate/edit/part_virtual_field.cgi
@@ -0,0 +1,104 @@
+<% include('/elements/header.html', "$action Virtual Field Definition") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/generic.cgi" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="table" VALUE="part_virtual_field">
+<INPUT TYPE="hidden" NAME="redirect_ok"
+ VALUE="<%popurl(2)%>browse/part_virtual_field.cgi">
+<INPUT TYPE="hidden" NAME="vfieldpart" VALUE="<%
+ $vfieldpart%>">
+Field #<B><%$vfieldpart or "(NEW)"%></B><BR><BR>
+
+<%ntable("#cccccc",2)%>
+ <TR>
+ <TD ALIGN="right">Name</TD>
+ <TD><INPUT TYPE="text" NAME="name" MAXLENGTH=32 VALUE="<%
+ $part_virtual_field->name%>"></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Table</TD>
+ <TD>
+% if ($action eq 'Add') {
+
+ <SELECT SIZE=1 NAME="dbtable">
+%
+% my $dbdef = dbdef; # ick
+% #foreach my $dbtable (sort { $a cmp $b } $dbdef->tables) {
+% foreach my $dbtable (qw( svc_broadband router )) {
+% if ($dbtable !~ /^h_/
+% and $dbdef->table($dbtable)->primary_key) {
+
+ <OPTION VALUE="<%$dbtable%>"><%$dbtable%></OPTION>
+%
+% }
+% }
+%
+</SELECT>
+%
+% } else { # Edit
+%
+<%$part_virtual_field->dbtable%>
+ <INPUT TYPE="hidden" NAME="dbtable" VALUE="<%$part_virtual_field->dbtable%>">
+% }
+
+ </TD>
+ <TR>
+ <TD ALIGN="right">Label</TD>
+ <TD><INPUT TYPE="text" NAME="label" MAXLENGTH="80" VALUE="<%
+ $part_virtual_field->label%>"></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Length</TD>
+ <TD><INPUT TYPE="text" NAME="length" MAXLENGTH=4 VALUE="<%
+ $part_virtual_field->length%>"></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Check</TD>
+ <TD><TEXTAREA COLS="20" ROWS="4" NAME="check_block"><%
+ $part_virtual_field->check_block%></TEXTAREA></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">List source</TD>
+ <TD><TEXTAREA COLS="20" ROWS="4" NAME="list_source"><%
+ $part_virtual_field->list_source%></TEXTAREA></TD>
+ </TR>
+</TABLE><BR><INPUT TYPE="submit" VALUE="Submit">
+
+</FORM>
+
+<BR>
+<FONT SIZE=-2>If you don't understand what <I>check_block</I> and
+<I>list_source</I> mean, <B>LEAVE THEM BLANK</B>. We mean it.</FONT>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my ($vfieldpart, $part_virtual_field);
+
+if ( $cgi->param('error') ) {
+ $part_virtual_field = new FS::part_virtual_field ( {
+ map { $_, scalar($cgi->param($_)) } fields('part_virtual_field')});
+ $vfieldpart = $part_virtual_field->vfieldpart;
+} else {
+ my($query) = $cgi->keywords;
+ if ( $query =~ /^(\d+)$/ ) { #editing
+ $vfieldpart=$1;
+ $part_virtual_field=qsearchs('part_virtual_field',
+ {'vfieldpart' => $vfieldpart})
+ or die "Unknown vfieldpart!";
+
+ } else { #adding
+ $part_virtual_field = new FS::part_virtual_field({});
+ }
+}
+my $action = $part_virtual_field->vfieldpart ? 'Edit' : 'Add';
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/payment_gateway.html b/httemplate/edit/payment_gateway.html
new file mode 100644
index 000000000..e3893cf49
--- /dev/null
+++ b/httemplate/edit/payment_gateway.html
@@ -0,0 +1,132 @@
+<% include("/elements/header.html","$action Payment gateway", menubar(
+ 'View all payment gateways' => $p. 'browse/payment_gateway.html',
+)) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%popurl(1)%>process/payment_gateway.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="gatewaynum" VALUE="<% $payment_gateway->gatewaynum %>">
+Gateway #<% $payment_gateway->gatewaynum || "(NEW)" %>
+
+<% ntable('#cccccc', 2, '') %>
+
+<TR>
+ <TH ALIGN="right">Gateway: </TH>
+ <TD>
+% if ( $payment_gateway->gatewaynum ) {
+
+
+ <% $payment_gateway->gateway_module %>
+ <INPUT TYPE="hidden" NAME="gateway_module" VALUE="<% $payment_gateway->gateway_module %>">
+% } else {
+
+
+ <SELECT NAME="gateway_module" SIZE=1>
+% foreach my $module ( qw(
+% 2CheckOut
+% AuthorizeNet
+% BankOfAmerica
+% Beanstream
+% Capstone
+% Cardstream
+% CashCow
+% CyberSource
+% eSec
+% eSelectPlus
+% Exact
+% iAuthorizer
+% IPaymentTPG
+% Jettis
+% LinkPoint
+% MerchantCommerce
+% Network1Financial
+% OCV
+% OpenECHO
+% PayConnect
+% PayflowPro
+% PaymentsGateway
+% PXPost
+% SecureHostingUPG
+% Skipjack
+% StGeorge
+% SurePay
+% TCLink
+% TransactionCentral
+% TransFirsteLink
+% VirtualNet
+% ) ) {
+%
+
+ <OPTION VALUE="<% $module %>"><% $module %>
+% }
+
+ </SELECT>
+% }
+
+
+ </TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right">Username: </TH>
+ <TD><INPUT TYPE="text" NAME="gateway_username" VALUE="<% $payment_gateway->gateway_username %>"></TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right">Password: </TH>
+ <TD><INPUT TYPE="text" NAME="gateway_password" VALUE="<% $payment_gateway->gateway_password %>"></TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right">Action: </TH>
+ <TD>
+ <SELECT NAME="gateway_action" SIZE=1>
+% foreach my $action (
+% 'Normal Authorization',
+% 'Authorization Only',
+% 'Authorization Only, Post Authorization',
+% ) {
+%
+
+ <OPTION VALUE="<% $action %>"<% $action eq $payment_gateway->gateway_action ? ' SELECTED' : '' %>><% $action %>
+% }
+
+ </SELECT>
+ </TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right">Options: (Name/Value pairs, one element per line)</TH>
+ <TD>
+ <TEXTAREA ROWS="5" NAME="gateway_options"><% join("\r", $payment_gateway->options ) %></TEXTAREA>
+ </TD>
+</TR>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="<% $payment_gateway->gatewaynum ? "Apply changes" : "Add gateway" %>">
+ </FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $payment_gateway;
+if ( $cgi->param('error') ) {
+ $payment_gateway = new FS::payment_gateway ( {
+ map { $_, scalar($cgi->param($_)) } fields('payment_gateway')
+ } );
+} elsif ( $cgi->keywords ) {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $payment_gateway = qsearchs( 'payment_gateway', { 'gatewaynum' => $1 } );
+} else { #adding
+ $payment_gateway = new FS::payment_gateway {};
+}
+my $action = $payment_gateway->gatewaynum ? 'Edit' : 'Add';
+#my $hashref = $payment_gateway->hashref;
+
+</%init>
diff --git a/httemplate/edit/pkg_category.html b/httemplate/edit/pkg_category.html
new file mode 100644
index 000000000..fdc8da638
--- /dev/null
+++ b/httemplate/edit/pkg_category.html
@@ -0,0 +1,22 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Package Category',
+ 'table' => 'pkg_category',
+ 'fields' => [
+ 'categoryname',
+ { field=>'disabled', type=>'checkbox', value=>'Y', },
+ ],
+ 'labels' => {
+ 'categorynum' => 'Category number',
+ 'categoryname' => 'Category name',
+ 'disabled' => 'Disable category',
+ },
+ 'viewall_dir' => 'browse',
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/pkg_class.html b/httemplate/edit/pkg_class.html
new file mode 100644
index 000000000..26bc8baa5
--- /dev/null
+++ b/httemplate/edit/pkg_class.html
@@ -0,0 +1,28 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Package Class',
+ 'table' => 'pkg_class',
+ 'fields' => [
+ 'classname',
+ (scalar(@category)
+ ? { field=>'categorynum', type=>'select-table', 'empty_label'=>'(none)', 'table'=>'pkg_category', 'name_col'=>'categoryname' }
+ : { field=>'categorynum', type=>'hidden' }
+ ),
+ { field=>'disabled', type=>'checkbox', value=>'Y', },
+ ],
+ 'labels' => {
+ 'classnum' => 'Class number',
+ 'classname' => 'Class name',
+ 'categorynum' => 'Category',
+ 'disabled' => 'Disable class',
+ },
+ 'viewall_dir' => 'browse',
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @category = qsearch('pkg_category', { 'disabled' => '' });
+</%init>
diff --git a/httemplate/edit/prepay_credit.cgi b/httemplate/edit/prepay_credit.cgi
new file mode 100644
index 000000000..9e1c30ba6
--- /dev/null
+++ b/httemplate/edit/prepay_credit.cgi
@@ -0,0 +1,110 @@
+<% include("/elements/header.html",'Generate prepaid cards'. ($agent ? ' for '. $agent->agent : '') ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%popurl(1)%>process/prepay_credit.cgi" METHOD="POST" NAME="OneTrueForm" onSubmit="document.OneTrueForm.submit.disabled=true">
+
+Generate
+<INPUT TYPE="text" NAME="num" VALUE="<% $cgi->param('num') || '(quantity)' |h %>" SIZE=10 MAXLENGTH=10 onFocus="if ( this.value == '(quantity)' ) { this.value = ''; }">
+
+<SELECT NAME="type">
+% foreach (qw(alpha alphanumeric numeric)) {
+ <OPTION<% $cgi->param('type') eq $_ ? ' SELECTED' : '' %>><% $_ %>
+% }
+</SELECT>
+
+prepaid cards
+
+<BR>for <SELECT NAME="agentnum"><OPTION>(any agent)
+% foreach my $opt_agent ( qsearch('agent', { 'disabled' => '' } ) ) {
+
+ <OPTION VALUE="<% $opt_agent->agentnum %>"<% $opt_agent->agentnum == $agentnum ? ' SELECTED' : '' %>><% $opt_agent->agent %>
+% }
+
+</SELECT>
+
+<TABLE>
+<TR><TD>Value:
+$<INPUT TYPE="text" NAME="amount" SIZE=8 MAXLENGTH=7 VALUE="<% $cgi->param('amount') |h %>">
+</TD>
+<TD>and/or
+<INPUT TYPE="text" NAME="seconds" SIZE=6 MAXLENGTH=5 VALUE="<% $cgi->param('seconds') |h %>">
+<SELECT NAME="multiplier">
+% foreach my $multiplier ( keys %multiplier ) {
+
+ <OPTION VALUE="<% $multiplier %>"<% $cgi->param('multiplier') eq $multiplier ? ' SELECTED' : '' %>><% $multiplier{$multiplier} %>
+% }
+
+</SELECT>
+</TD></TR>
+<TR><TD></TD>
+<TD>and/or
+<INPUT TYPE="text" NAME="upbytes" SIZE=6 MAXLENGTH=5 VALUE="<% $cgi->param('upbytes') |h %>">
+<SELECT NAME="upmultiplier">
+% foreach my $multiplier ( keys %bytemultiplier ) {
+
+ <OPTION VALUE="<% $multiplier %>"<% $cgi->param('upmultiplier') eq $multiplier ? ' SELECTED' : '' %>><% $bytemultiplier{$multiplier} %>
+% }
+
+</SELECT> upload
+</TD></TR>
+<TR><TD></TD>
+<TD>and/or
+<INPUT TYPE="text" NAME="downbytes" SIZE=6 MAXLENGTH=5 VALUE="<% $cgi->param('downbytes') |h %>">
+<SELECT NAME="downmultiplier">
+% foreach my $multiplier ( keys %bytemultiplier ) {
+
+ <OPTION VALUE="<% $multiplier %>"<% $cgi->param('downmultiplier') eq $multiplier ? ' SELECTED' : '' %>><% $bytemultiplier{$multiplier} %>
+% }
+
+</SELECT> download
+</TD></TR>
+<TR><TD></TD>
+<TD>and/or
+<INPUT TYPE="text" NAME="totalbytes" SIZE=6 MAXLENGTH=5 VALUE="<% $cgi->param('totalbytes') |h %>">
+<SELECT NAME="totalmultiplier">
+% foreach my $multiplier ( keys %bytemultiplier ) {
+
+ <OPTION VALUE="<% $multiplier %>"<% $cgi->param('totalmultiplier') eq $multiplier ? ' SELECTED' : '' %>><% $bytemultiplier{$multiplier} %>
+% }
+
+</SELECT> total transfer
+</TD></TR>
+</TABLE>
+<BR><BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Generate" onSubmit="this.disabled = true">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agent = '';
+my $agentnum = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agent = qsearchs('agent', { 'agentnum' => $agentnum=$1 } );
+}
+
+tie my %multiplier, 'Tie::IxHash',
+ 1 => 'seconds',
+ 60 => 'minutes',
+ 3600 => 'hours',
+;
+
+tie my %bytemultiplier, 'Tie::IxHash',
+ 1 => 'bytes',
+ 1000 => 'Kbytes',
+ 1000000 => 'Mbytes',
+ 1000000000 => 'Gbytes',
+;
+
+$cgi->param('multiplier', '60') unless $cgi->param('multiplier');
+$cgi->param('upmultiplier', '1000000') unless $cgi->param('upmultiplier');
+$cgi->param('downmultiplier', '1000000') unless $cgi->param('downmultiplier');
+$cgi->param('totalmultiplier','1000000') unless $cgi->param('totalmultiplier');
+
+</%init>
diff --git a/httemplate/edit/process/REAL_cust_pkg.cgi b/httemplate/edit/process/REAL_cust_pkg.cgi
new file mode 100755
index 000000000..ebcb7e4ba
--- /dev/null
+++ b/httemplate/edit/process/REAL_cust_pkg.cgi
@@ -0,0 +1,36 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "REAL_cust_pkg.cgi?". $cgi->query_string ) %>
+%} else {
+% my $custnum = $new->custnum;
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum#cust_pkg$pkgnum" ) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer package dates');
+
+my $pkgnum = $cgi->param('pkgnum') or die;
+my $old = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+my %hash = $old->hash;
+$hash{'setup'} = $cgi->param('setup') ? str2time($cgi->param('setup')) : '';
+$hash{'bill'} = $cgi->param('bill') ? str2time($cgi->param('bill')) : '';
+$hash{'last_bill'} =
+ $cgi->param('last_bill') ? str2time($cgi->param('last_bill')) : '';
+$hash{'adjourn'} = $cgi->param('adjourn') ? str2time($cgi->param('adjourn')) : '';
+$hash{'expire'} = $cgi->param('expire') ? str2time($cgi->param('expire')) : '';
+
+my $new;
+my $error;
+if ( $hash{'bill'} != $old->bill # if the next bill date was changed
+ && $hash{'bill'} < time # to a date in the past
+ && ! $cgi->param('bill_areyousure') # and it wasn't confirmed
+ )
+{
+ $error = '_bill_areyousure';
+} else {
+ $new = new FS::cust_pkg \%hash;
+ $error = $new->replace($old);
+}
+
+</%init>
diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html
new file mode 100644
index 000000000..ab25cb3a2
--- /dev/null
+++ b/httemplate/edit/process/access_group.html
@@ -0,0 +1,28 @@
+% if ( $conf->exists('disable_acl_changes') ) {
+ ACL changes disabled in public demo.
+% } else {
+<% include( 'elements/process.html',
+ 'table' => 'access_group',
+ 'viewall_dir' => 'browse',
+ 'process_m2m' => { 'link_table' => 'access_groupagent',
+ 'target_table' => 'agent',
+ },
+ 'process_m2name' => {
+ 'link_table' => 'access_right',
+ 'link_static' => { 'righttype' => 'FS::access_group', },
+ 'num_col' => 'rightobjnum',
+ 'name_col' => 'rightname',
+ 'names_list' => [ FS::AccessRight->rights() ],
+ 'param_style' => 'link_table.value checkboxes',
+ },
+ )
+%>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html
new file mode 100644
index 000000000..ca6bb603f
--- /dev/null
+++ b/httemplate/edit/process/access_user.html
@@ -0,0 +1,21 @@
+% if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
+% $cgi->param('error', "The passwords do not match");
+% print $cgi->redirect(popurl(2) . "access_user.html?" . $cgi->query_string);
+% } else {
+<% include( 'elements/process.html',
+ 'table' => 'access_user',
+ 'viewall_dir' => 'browse',
+ 'copy_on_empty' => [ '_password' ],
+ 'clear_on_error' => [ '_password', '_password2' ],
+ 'process_m2m' => { 'link_table' => 'access_usergroup',
+ 'target_table' => 'access_group',
+ },
+ )
+%>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/addr_block/add.cgi b/httemplate/edit/process/addr_block/add.cgi
new file mode 100755
index 000000000..39d6348ce
--- /dev/null
+++ b/httemplate/edit/process/addr_block/add.cgi
@@ -0,0 +1,20 @@
+<% include( '../elements/process.html',
+ 'table' => 'addr_block',
+ 'redirect' => popurl(4). 'browse/addr_block.cgi?dummy=',
+ 'error_redirect' => popurl(4). 'browse/addr_block.cgi?',
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Broadband global configuration',
+
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+$cgi->param('routernum', 0) # in FS::addr_block::check instead?
+ unless $cgi->param('routernum');
+
+</%init>
diff --git a/httemplate/edit/process/addr_block/allocate.cgi b/httemplate/edit/process/addr_block/allocate.cgi
new file mode 100755
index 000000000..40d04b369
--- /dev/null
+++ b/httemplate/edit/process/addr_block/allocate.cgi
@@ -0,0 +1,16 @@
+<% include( '../elements/process.html',
+ 'table' => 'addr_block',
+ 'copy_on_empty' => [ fields 'addr_block' ],
+ 'error_redirect' => popurl(3). 'allocate.html?',
+ 'popup_reload' => 'Block allocated',
+ )
+%>
+<%init>
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+</%init>
diff --git a/httemplate/edit/process/addr_block/deallocate.cgi b/httemplate/edit/process/addr_block/deallocate.cgi
new file mode 100755
index 000000000..128824ec7
--- /dev/null
+++ b/httemplate/edit/process/addr_block/deallocate.cgi
@@ -0,0 +1,20 @@
+<% include( '../elements/process.html',
+ 'table' => 'addr_block',
+ 'copy_on_empty' => [ grep { $_ ne 'routernum' }
+ fields 'addr_block' ],
+ 'redirect' => popurl(4). 'browse/addr_block.cgi?',
+ 'error_redirect' => popurl(4). 'browse/addr_block.cgi?',
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Broadband global configuration',
+ )
+%>
+<%init>
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+$cgi->param('routernum', 0); # just to be explicit about what we are doing
+</%init>
diff --git a/httemplate/edit/process/addr_block/manual_flag.cgi b/httemplate/edit/process/addr_block/manual_flag.cgi
new file mode 100755
index 000000000..dc0cbbbf5
--- /dev/null
+++ b/httemplate/edit/process/addr_block/manual_flag.cgi
@@ -0,0 +1,30 @@
+<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+my $error = '';
+$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum";
+my $blocknum = $1;
+
+my $addr_block = qsearchs({ 'table' => 'addr_block',
+ 'hashref' => { blocknum => $blocknum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql(
+ 'null_right' => 'Broadband global configuration'
+ ),
+ })
+ or $error = "Unknown blocknum: $blocknum";
+
+$addr_block->manual_flag($cgi->param('manual_flag'))
+ unless $error;
+
+$error ||= $addr_block->replace;
+
+$cgi->param('error', $error)
+ if $error;
+
+</%init>
diff --git a/httemplate/edit/process/addr_block/split.cgi b/httemplate/edit/process/addr_block/split.cgi
new file mode 100755
index 000000000..045fd30de
--- /dev/null
+++ b/httemplate/edit/process/addr_block/split.cgi
@@ -0,0 +1,27 @@
+<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+my $error = '';
+$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum";
+my $blocknum = $1;
+
+my $addr_block = qsearchs({ 'table' => 'addr_block',
+ 'hashref' => { blocknum => $blocknum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql(
+ 'null_right' => 'Broadband global configuration'
+ ),
+ })
+ or $error = "Unknown blocknum: $blocknum";
+
+$error ||= $addr_block->split_block;
+
+$cgi->param('error', $error)
+ if $error;
+
+</%init>
diff --git a/httemplate/edit/process/agent.cgi b/httemplate/edit/process/agent.cgi
new file mode 100755
index 000000000..3cdf40c9b
--- /dev/null
+++ b/httemplate/edit/process/agent.cgi
@@ -0,0 +1,16 @@
+<% include( 'elements/process.html',
+ 'table' => 'agent',
+ 'viewall_dir' => 'browse',
+ 'viewall_ext' => 'cgi',
+ 'process_m2m' => { 'link_table' => 'access_groupagent',
+ 'target_table' => 'access_group',
+ },
+ 'edit_ext' => 'cgi',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/agent_payment_gateway.html b/httemplate/edit/process/agent_payment_gateway.html
new file mode 100644
index 000000000..5b5fd948a
--- /dev/null
+++ b/httemplate/edit/process/agent_payment_gateway.html
@@ -0,0 +1,29 @@
+<% $cgi->redirect(popurl(3). "browse/agent.cgi") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('agentnum') =~ /(\d+)$/ or die "illegal agentnum";
+my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+die "agentnum $1 not found" unless $agent;
+
+#my $old
+
+my @new = map {
+ my $cardtype = $_;
+ new FS::agent_payment_gateway {
+ ( map { $_ => scalar($cgi->param($_)) }
+ fields('agent_payment_gateway')
+ ),
+ 'cardtype' => $cardtype,
+ };
+ }
+ $cgi->param('cardtype');
+
+foreach my $new (@new) {
+ my $error = $new->insert;
+ die $error if $error;
+}
+
+</%init>
diff --git a/httemplate/edit/process/agent_type.cgi b/httemplate/edit/process/agent_type.cgi
new file mode 100755
index 000000000..ad5963b31
--- /dev/null
+++ b/httemplate/edit/process/agent_type.cgi
@@ -0,0 +1,35 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/agent_type.cgi") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $typenum = $cgi->param('typenum');
+my $old = qsearchs('agent_type',{'typenum'=>$typenum}) if $typenum;
+
+my $new = new FS::agent_type ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('agent_type')
+} );
+
+my $error;
+if ( $typenum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $typenum = $new->getfield('typenum');
+}
+
+ $error ||= $new->process_m2m(
+ 'link_table' => 'type_pkgs',
+ 'target_table' => 'part_pkg',
+ 'params' => scalar($cgi->Vars)
+ );
+
+</%init>
diff --git a/httemplate/edit/process/bulk-cust_main_county.html b/httemplate/edit/process/bulk-cust_main_county.html
new file mode 100644
index 000000000..e05192e96
--- /dev/null
+++ b/httemplate/edit/process/bulk-cust_main_county.html
@@ -0,0 +1,63 @@
+% if ( $error ) { #better to redirect back to
+%# <% $cgi->redirect("$url?". $cgi->query_string ) %>
+ <% include('/elements/header-popup.html', 'Error adding taxes' ) %>
+
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT>
+ <BR><BR>
+
+ </BODY>
+ </HTML>
+
+% } else {
+ <% include('/elements/header-popup.html', 'Taxes added') %>
+
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY>
+ </HTML>
+% }
+<%init>
+
+$cgi->param('taxnum') =~ /^([\d,]+)$/
+ or die 'Guru Meditation #69'; #??? should have been passed in
+my @taxnum = split(',', $1);
+
+my $error = '';
+foreach my $taxnum ( @taxnum ) {
+
+ my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } )
+ or die "unknown taxnum: $taxnum";
+
+ if ( $cust_main_county->tax == 0 ) { #let's replace
+
+ foreach (qw( taxname tax exempt_amount setuptax recurtax )) {
+ $cust_main_county->set( $_ => scalar($cgi->param($_)) )
+ }
+
+ $error = $cust_main_county->replace and last;
+
+ } else { #let's insert a new record
+
+ my $new =
+ new FS::cust_main_county {
+ ( map { $_ => scalar($cgi->param($_)) }
+ qw( taxname tax exempt_amount setuptax recurtax )
+ ),
+ ( map { $_ => $cust_main_county->get($_) }
+ qw( country state county taxclass )
+ )
+ };
+
+ $error = $new->insert and last;
+
+ }
+
+}
+
+if ( $error ) {
+ $cgi->param('error', $error);
+}
+
+</%init>
diff --git a/httemplate/edit/process/bulk-cust_svc.cgi b/httemplate/edit/process/bulk-cust_svc.cgi
new file mode 100644
index 000000000..313b061ff
--- /dev/null
+++ b/httemplate/edit/process/bulk-cust_svc.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::part_svc::process_bulk_cust_svc', $cgi;
+
+</%init>
diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html
new file mode 100644
index 000000000..7356e6122
--- /dev/null
+++ b/httemplate/edit/process/change-cust_pkg.html
@@ -0,0 +1,46 @@
+% if ($error) {
+% $cgi->param('error', $error);
+% $cgi->redirect(popurl(3). 'misc/change_pkg.cgi?'. $cgi->query_string );
+% } else {
+
+ <% header("Package changed") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+ </HTML>
+
+% }
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Change customer package');
+
+my $cust_pkg = qsearchs({
+ #'select' => 'cust_pkg.*',
+ 'table' => 'cust_pkg',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'pkgnum' => scalar($cgi->param('pkgnum')), },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+die 'unknown pkgnum' unless $cust_pkg;
+
+my %change = map { $_ => scalar($cgi->param($_)) }
+ qw( locationnum pkgpart );
+
+if ( $cgi->param('locationnum') == -1 ) {
+ my $cust_location = new FS::cust_location {
+ 'custnum' => $cust_pkg->custnum,
+ map { $_ => scalar($cgi->param($_)) }
+ qw( address1 address2 city county state zip country )
+ };
+ $change{'cust_location'} = $cust_location;
+}
+
+my $pkg_or_error = $cust_pkg->change( \%change );
+
+my $error = ref($pkg_or_error) ? '' : $pkg_or_error;
+
+</%init>
diff --git a/httemplate/edit/process/cust_bill_pay.cgi b/httemplate/edit/process/cust_bill_pay.cgi
new file mode 100755
index 000000000..2845d3233
--- /dev/null
+++ b/httemplate/edit/process/cust_bill_pay.cgi
@@ -0,0 +1,13 @@
+<% include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_bill_pay.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'link_table' => 'cust_bill_pay',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply payment');
+
+</%init>
diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi
new file mode 100755
index 000000000..8715ad61e
--- /dev/null
+++ b/httemplate/edit/process/cust_credit.cgi
@@ -0,0 +1,63 @@
+%if ( $error ) {
+% $cgi->param('reasonnum', $reasonnum);
+% $cgi->param('error', $error);
+% $dbh->rollback if $oldAutoCommit;
+%
+<% $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ) %>
+%
+%} else {
+%
+% if ( $cgi->param('apply') eq 'yes' ) {
+% my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum })
+% or die "unknown custnum $custnum";
+% $cust_main->apply_credits;
+% }
+% #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum");
+%
+% $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+%
+<% header('Credit sucessful') %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY></HTML>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post credit');
+
+$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!";
+my $custnum = $1;
+
+$cgi->param('reasonnum') =~ /^(-?\d+)$/ or die "Illegal reasonnum";
+my $reasonnum = $1;
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+my $dbh = dbh;
+
+my $error = '';
+if ($reasonnum == -1) {
+
+ $error = 'Enter a new reason (or select an existing one)'
+ unless $cgi->param('newreasonnum') !~ /^\s*$/;
+ my $reason = new FS::reason({ 'reason_type' => $cgi->param('newreasonnumT'),
+ 'reason' => $cgi->param('newreasonnum'),
+ });
+ $error ||= $reason->insert;
+ $cgi->param('reasonnum', $reason->reasonnum)
+ unless $error;
+}
+
+unless ($error) {
+ my $new = new FS::cust_credit ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('cust_credit')
+ } );
+ $error = $new->insert;
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_credit_bill.cgi b/httemplate/edit/process/cust_credit_bill.cgi
new file mode 100755
index 000000000..c0f34ae5b
--- /dev/null
+++ b/httemplate/edit/process/cust_credit_bill.cgi
@@ -0,0 +1,13 @@
+<% include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_credit_bill.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'link_table' => 'cust_credit_bill',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply credit');
+
+</%init>
diff --git a/httemplate/edit/process/cust_credit_refund.cgi b/httemplate/edit/process/cust_credit_refund.cgi
new file mode 100755
index 000000000..88420f8ab
--- /dev/null
+++ b/httemplate/edit/process/cust_credit_refund.cgi
@@ -0,0 +1,13 @@
+<% include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_credit_refund.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'link_table' => 'cust_credit_refund',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply credit');
+
+</%init>
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
new file mode 100755
index 000000000..097d38204
--- /dev/null
+++ b/httemplate/edit/process/cust_main.cgi
@@ -0,0 +1,210 @@
+% if ( $error ) {
+% $cgi->param('error', $error);
+%
+<% $cgi->redirect(popurl(2). "cust_main.cgi?". $cgi->query_string ) %>
+%
+% } else {
+%
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?". $new->custnum) %>
+%
+% }
+<%once>
+
+my $me = '[edit/process/cust_main.cgi]';
+my $DEBUG = 0;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+
+my $error = '';
+
+#unmunge stuff
+
+$cgi->param('tax','') unless defined $cgi->param('tax');
+
+$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] );
+
+#my $payby = $cgi->param('payby');
+my $payby = $cgi->param('select'); # XXX key
+
+my %noauto = (
+ 'CARD' => 'DCRD',
+ 'CHEK' => 'DCHK',
+);
+$payby = $noauto{$payby}
+ if ! $cgi->param('payauto') && exists $noauto{$payby};
+
+$cgi->param('payby', $payby);
+
+if ( $payby ) {
+ if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
+ $cgi->param('payinfo',
+ $cgi->param('payinfo1'). '@'. $cgi->param('payinfo2') );
+ }
+ $cgi->param('paydate',
+ $cgi->param( 'exp_month' ). '-'. $cgi->param( 'exp_year' ) );
+}
+
+my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );
+push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST');
+push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');
+$cgi->param('invoicing_list', join(',', @invoicing_list) );
+
+
+#create new record object
+
+my $new = new FS::cust_main ( {
+ map {
+ $_, scalar($cgi->param($_))
+# } qw(custnum agentnum last first ss company address1 address2 city county
+# state zip daytime night fax payby payinfo paydate payname tax
+# otaker refnum)
+ } fields('cust_main')
+} );
+
+if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) {
+ $new->setfield("ship_$_", '') foreach qw(
+ last first company address1 address2 city county state zip
+ country daytime night fax
+ );
+}
+
+if ( $cgi->param('birthdate') && $cgi->param('birthdate') =~ /^([ 0-9\-\/]{0,10})$/) {
+ my $conf = new FS::Conf;
+ my $format = $conf->config('date_format') || "%m/%d/%Y";
+ my $parser = DateTime::Format::Strptime->new(pattern => $format,
+ time_zone => 'floating',
+ );
+ my $dt = $parser->parse_datetime($1);
+ if ($dt) {
+ $new->setfield('birthdate', $dt->epoch);
+ $cgi->param('birthdate', $dt->epoch);
+ } else {
+# $error ||= $cgi->param('birthdate') . " is an invalid birthdate:" . $parser->errmsg;
+ $error ||= "Invalid birthdate: " . $cgi->param('birthdate') . ".";
+ $cgi->param('birthdate', '');
+ }
+}
+
+$new->setfield('paid', $cgi->param('paid') )
+ if $cgi->param('paid');
+
+#perhaps this stuff should go to cust_main.pm
+my $cust_pkg = '';
+my $svc_acct = '';
+if ( $new->custnum eq '' ) {
+
+ if ( $cgi->param('pkgpart_svcpart') ) {
+ my $x = $cgi->param('pkgpart_svcpart');
+ $x =~ /^(\d+)_(\d+)$/ or die "illegal pkgpart_svcpart $x\n";
+ my($pkgpart, $svcpart) = ($1, $2);
+ #false laziness: copied from FS::cust_pkg::order (which should become a
+ #FS::cust_main method)
+ my(%part_pkg);
+ # generate %part_pkg
+ # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart
+ my $agent = qsearchs('agent',{'agentnum'=> $new->agentnum });
+ #my($type_pkgs);
+ #foreach $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {
+ # my($pkgpart)=$type_pkgs->pkgpart;
+ # $part_pkg{$pkgpart}++;
+ #}
+ # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart
+ my $pkgpart_href = $agent->pkgpart_hashref;
+ #eslaf
+
+ # this should wind up in FS::cust_pkg!
+ $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum. ") can't ".
+ "purchase pkgpart ". $pkgpart
+ #unless $part_pkg{ $pkgpart };
+ unless $pkgpart_href->{ $pkgpart };
+
+ $cust_pkg = new FS::cust_pkg ( {
+ #later 'custnum' => $custnum,
+ 'pkgpart' => $pkgpart,
+ } );
+ #$error ||= $cust_pkg->check;
+
+ #$cust_svc = new FS::cust_svc ( { 'svcpart' => $svcpart } );
+
+ #$error ||= $cust_svc->check;
+
+ my %svc_acct = (
+ 'svcpart' => $svcpart,
+ 'username' => $cgi->param('username'),
+ '_password' => $cgi->param('_password'),
+ 'popnum' => $cgi->param('popnum'),
+ );
+ $svc_acct{'domsvc'} = $cgi->param('domsvc')
+ if $cgi->param('domsvc');
+
+ $svc_acct = new FS::svc_acct \%svc_acct;
+
+ #and just in case you were silly
+ $svc_acct->svcpart($svcpart);
+ $svc_acct->username($cgi->param('username'));
+ $svc_acct->_password($cgi->param('_password'));
+ $svc_acct->popnum($cgi->param('popnum'));
+
+ #$error ||= $svc_acct->check;
+
+ } elsif ( $cgi->param('username') ) { #good thing to catch
+ $error = "Can't assign username without a package!";
+ }
+
+ use Tie::RefHash;
+ tie my %hash, 'Tie::RefHash';
+ %hash = ( $cust_pkg => [ $svc_acct ] ) if $cust_pkg;
+ $error ||= $new->insert( \%hash, \@invoicing_list );
+
+ my $conf = new FS::Conf;
+ if ( $conf->exists('backend-realtime') && ! $error ) {
+
+ my $berror = $new->bill
+ || $new->apply_payments_and_credits
+ || $new->collect( 'realtime' => 1 );
+ warn "Warning, error billing during backend-realtime: $berror" if $berror;
+
+ }
+
+} else { #create old record object
+
+ my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } );
+ $error ||= "Old record not found!" unless $old;
+ if ( length($old->paycvv) && $new->paycvv =~ /^\s*\*+\s*$/ ) {
+ $new->paycvv($old->paycvv);
+ }
+ if ($new->ss =~ /xx/) {
+ $new->ss($old->ss);
+ }
+ if ($new->stateid =~ /^xxx/) {
+ $new->stateid($old->stateid);
+ }
+ if ($new->payby =~ /^(CARD|DCRD)$/ && $new->payinfo =~ /xx/) {
+ $new->payinfo($old->payinfo);
+ } elsif ($new->payby =~ /^(CHEK|DCHK)$/ && $new->payinfo =~ /xx/) {
+ #fix for #3085 "edit of customer's routing code only surprisingly causes
+ #nothing to happen...
+ # this probably won't do the right thing when we don't have the
+ # public key (can't actually get the real $old->payinfo)
+ my($new_account, $new_aba) = split('@', $new->payinfo);
+ my($old_account, $old_aba) = split('@', $old->payinfo);
+ $new_account = $old_account if $new_account =~ /xx/;
+ $new_aba = $old_aba if $new_aba =~ /xx/;
+ $new->payinfo($new_account.'@'.$new_aba);
+ }
+
+ warn "$me calling $new -> replace( $old, \ @invoicing_list )" if $DEBUG;
+ local($FS::cust_main::DEBUG) = $DEBUG if $DEBUG;
+ local($FS::Record::DEBUG) = $DEBUG if $DEBUG;
+
+ $error ||= $new->replace($old, \@invoicing_list);
+
+ warn "$me returned from replace" if $DEBUG;
+
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_main_county-collapse.cgi b/httemplate/edit/process/cust_main_county-collapse.cgi
new file mode 100755
index 000000000..a917825ce
--- /dev/null
+++ b/httemplate/edit/process/cust_main_county-collapse.cgi
@@ -0,0 +1,44 @@
+%
+%
+%my($query) = $cgi->keywords;
+%$query =~ /^(\d+)$/ or die "Illegal taxnum!";
+%my $taxnum = $1;
+%my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } )
+% or die "Unknown taxnum $taxnum";
+%
+%#really should do this in a .pm & start transaction
+%
+%foreach my $delete ( qsearch('cust_main_county', {
+% 'country' => $cust_main_county->country,
+% 'state' => $cust_main_county->state
+% } ) ) {
+%# unless ( qsearch('cust_main',{
+%# 'state' => $cust_main_county->getfield('state'),
+%# 'county' => $cust_main_county->getfield('county'),
+%# 'country' => $cust_main_county->getfield('country'),
+%# } ) ) {
+% my $error = $delete->delete;
+% die $error if $error;
+%# } else {
+% #should really fix the $cust_main record
+%# }
+%
+%}
+%
+%$cust_main_county->taxnum('');
+%$cust_main_county->county('');
+%my $error = $cust_main_county->insert;
+%die $error if $error;
+%
+%print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi");
+%
+%
+<%init>
+
+#this isn't actually linked from anywhere just now, but it will be again soon
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+
+</%init>
diff --git a/httemplate/edit/process/cust_main_county-expand.cgi b/httemplate/edit/process/cust_main_county-expand.cgi
new file mode 100755
index 000000000..04533a539
--- /dev/null
+++ b/httemplate/edit/process/cust_main_county-expand.cgi
@@ -0,0 +1,78 @@
+<% include('/elements/header-popup.html', 'Addition successful' ) %>
+
+<SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+</SCRIPT>
+
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('taxnum') =~ /^(\d+)$/ or die "Illegal taxnum!";
+my $taxnum = $1;
+my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum})
+ or die ("Unknown taxnum!");
+
+my @expansion;
+if ( $cgi->param('taxclass') ) {
+ my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ @expansion = map $_->[0], @{$sth->fetchall_arrayref};
+ die "no taxclasses - add one first" unless @expansion;#XXX better err handling
+} else {
+ @expansion = split /[\n\r]{1,2}/, $cgi->param('expansion');
+
+ #warn scalar(@expansion);
+ #warn "$_: $expansion[$_]\n" foreach (0..$#expansion);
+
+ @expansion=map {
+ unless ( /^\s*([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]+)\s*$/ ) {
+ $cgi->param('error', "Illegal item in expansion: $_");
+ print $cgi->redirect(popurl(2). "cust_main_county-expand.cgi?". $cgi->query_string );
+ myexit();
+ }
+ $1;
+ } @expansion;
+
+}
+
+foreach ( @expansion) {
+ my(%hash)=$cust_main_county->hash;
+ my($new)=new FS::cust_main_county \%hash;
+ $new->setfield('taxnum','');
+ if ( $cgi->param('taxclass') ) {
+ $new->setfield('taxclass', $_);
+ } elsif ( ! $cust_main_county->state ) {
+ $new->setfield('state',$_);
+ } else {
+ $new->setfield('county',$_);
+ }
+ my $error = $new->insert;
+ die $error if $error;
+}
+
+unless ( qsearch( 'cust_main', {
+ 'state' => $cust_main_county->state,
+ 'county' => $cust_main_county->county,
+ 'country' => $cust_main_county->country,
+ } )
+ || ! @expansion
+) {
+ my $error = $cust_main_county->delete;
+ die $error if $error;
+}
+
+if ( $cgi->param('taxclass') ) {
+ print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi?".
+ 'state='. uri_escape($cust_main_county->state ).';'.
+ 'county='. uri_escape($cust_main_county->county ).';'.
+ 'country='. uri_escape($cust_main_county->country)
+ );
+ myexit;
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_main_county.html b/httemplate/edit/process/cust_main_county.html
new file mode 100644
index 000000000..cb56166c8
--- /dev/null
+++ b/httemplate/edit/process/cust_main_county.html
@@ -0,0 +1,13 @@
+<% include( 'elements/process.html',
+ 'table' => 'cust_main_county',
+ 'popup_reload' => 'Tax changed', #a popup "parent reload" for now
+ #someday change the individual element and go away instead
+ )
+%>
+<%init>
+
+my $conf = new FS::Conf;
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/cust_main_note.cgi b/httemplate/edit/process/cust_main_note.cgi
new file mode 100755
index 000000000..5127c72d1
--- /dev/null
+++ b/httemplate/edit/process/cust_main_note.cgi
@@ -0,0 +1,54 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). 'cust_main_note.cgi?'. $cgi->query_string ) %>
+%} else {
+<% header('Note ' . ($notenum ? 'updated' : 'added') ) %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die "Illegal custnum: ". $cgi->param('custnum');
+my $custnum = $1;
+
+$cgi->param('notenum') =~ /^(\d*)$/
+ or die "Illegal notenum: ". $cgi->param('notenum');
+my $notenum = $1;
+
+my $otaker = $FS::CurrentUser::CurrentUser->name;
+$otaker = $FS::CurrentUser::CurrentUser->username
+ if ($otaker eq "User, Legacy");
+
+my $new = new FS::cust_main_note ( {
+ notenum => $notenum,
+ custnum => $custnum,
+ _date => time,
+ otaker => $otaker,
+ comments => $cgi->param('comment'),
+} );
+
+my $error;
+if ($notenum) {
+
+ die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer note');
+
+ my $old = qsearchs('cust_main_note', { 'notenum' => $notenum });
+ $error = "No such note: $notenum" unless $old;
+ unless ($error) {
+ map { $new->$_($old->$_) } ('_date', 'otaker');
+ $error = $new->replace($old);
+ }
+
+} else {
+
+ die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Add customer note');
+
+ $error = $new->insert;
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi
new file mode 100755
index 000000000..647f6fc6c
--- /dev/null
+++ b/httemplate/edit/process/cust_pay.cgi
@@ -0,0 +1,55 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). 'cust_pay.cgi?'. $cgi->query_string ) %>
+%} elsif ( $field eq 'invnum' ) {
+<% $cgi->redirect(popurl(3). "view/cust_bill.cgi?$linknum") %>
+%} elsif ( $field eq 'custnum' ) {
+% if ( $cgi->param('apply') eq 'yes' ) {
+% my $cust_main = qsearchs('cust_main', { 'custnum' => $linknum })
+% or die "unknown custnum $linknum";
+% $cust_main->apply_payments;
+% }
+% if ( $link eq 'popup' ) {
+%
+<% header('Payment entered') %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY></HTML>
+%
+% } elsif ( $link eq 'custnum' ) {
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$linknum") %>
+% } else {
+% die "unknown link $link";
+% }
+%
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post payment');
+
+$cgi->param('linknum') =~ /^(\d+)$/
+ or die "Illegal linknum: ". $cgi->param('linknum');
+my $linknum = $1;
+
+$cgi->param('link') =~ /^(custnum|invnum|popup)$/
+ or die "Illegal link: ". $cgi->param('link');
+my $field = my $link = $1;
+$field = 'custnum' if $field eq 'popup';
+
+my $_date = str2time($cgi->param('_date'));
+
+my $new = new FS::cust_pay ( {
+ $field => $linknum,
+ _date => $_date,
+ map {
+ $_, scalar($cgi->param($_));
+ } qw(paid payby payinfo paybatch)
+ #} fields('cust_pay')
+} );
+
+my $error = $new->insert( 'manual' => 1 );
+
+</%init>
diff --git a/httemplate/edit/process/cust_pay_pending.html b/httemplate/edit/process/cust_pay_pending.html
new file mode 100644
index 000000000..1bad6cffe
--- /dev/null
+++ b/httemplate/edit/process/cust_pay_pending.html
@@ -0,0 +1,68 @@
+<% include('/elements/header-popup.html', $title ) %>
+% if ( $error ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT>
+% } else {
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+% }
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Edit customer pending payments');
+
+$cgi->param('action') =~ /^(\w+)$/ or die 'illegal action';
+my $action = $1;
+
+$cgi->param('paypendingnum') =~ /^(\d+)$/ or die 'illegal paypendingnum';
+my $paypendingnum = $1;
+my $cust_pay_pending =
+ qsearchs({
+ 'select' => 'cust_pay_pending.*',
+ 'table' => 'cust_pay_pending',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'paypendingnum' => $paypendingnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ })
+ or die 'unknown paypendingnum';
+
+my $error;
+my $title;
+if ( $action eq 'delete' ) {
+
+ $error = $cust_pay_pending->delete;
+ if ( $error ) {
+ $title = 'Error deleting pending payment';
+ } else {
+ $title = 'Pending payment deletion sucessful';
+ }
+
+} elsif ( $action eq 'insert_cust_pay' ) {
+
+ $error = $cust_pay_pending->insert_cust_pay;
+ if ( $error ) {
+ $title = 'Error completing pending payment';
+ } else {
+ $title = 'Pending payment completed';
+ }
+
+} elsif ( $action eq 'decline' ) {
+
+ $error = $cust_pay_pending->decline;
+ if ( $error ) {
+ $title = 'Error declining pending payment';
+ } else {
+ $title = 'Pending payment completed (decline)';
+ }
+
+} else {
+
+ die "unknown action $action";
+
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_pay_refund.cgi b/httemplate/edit/process/cust_pay_refund.cgi
new file mode 100755
index 000000000..2616cad8c
--- /dev/null
+++ b/httemplate/edit/process/cust_pay_refund.cgi
@@ -0,0 +1,13 @@
+<% include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_pay_refund.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'link_table' => 'cust_pay_refund',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Apply payment');
+
+</%init>
diff --git a/httemplate/edit/process/cust_pkg.cgi b/httemplate/edit/process/cust_pkg.cgi
new file mode 100755
index 000000000..c564c417e
--- /dev/null
+++ b/httemplate/edit/process/cust_pkg.cgi
@@ -0,0 +1,42 @@
+% if ($error) {
+% $cgi->param('error', $error);
+% $cgi->redirect(popurl(3). 'edit/cust_pkg.cgi?'. $cgi->query_string );
+% } else {
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum") %>
+% }
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Bulk change customer packages');
+
+my $error = '';
+
+#untaint custnum
+$cgi->param('custnum') =~ /^(\d+)$/;
+my $custnum = $1;
+
+my @remove_pkgnums = map {
+ /^(\d+)$/ or die "Illegal remove_pkg value!";
+ $1;
+} $cgi->param('remove_pkg');
+
+my( $action, $error_redirect ) = ( '', '' );
+my @pkgparts = ();
+
+foreach my $pkgpart ( map /^pkg(\d+)$/ ? $1 : (), $cgi->param ) {
+ if ( $cgi->param("pkg$pkgpart") =~ /^(\d+)$/ ) {
+ my $num_pkgs = $1;
+ while ( $num_pkgs-- ) {
+ push @pkgparts,$pkgpart;
+ }
+ } else {
+ $error = "Illegal quantity";
+ last;
+ }
+}
+
+$error ||= FS::cust_pkg::order($custnum,\@pkgparts,\@remove_pkgnums);
+
+</%init>
diff --git a/httemplate/edit/process/cust_pkg_detail.html b/httemplate/edit/process/cust_pkg_detail.html
new file mode 100644
index 000000000..132ff63c5
--- /dev/null
+++ b/httemplate/edit/process/cust_pkg_detail.html
@@ -0,0 +1,59 @@
+% if ( $error ) {
+<% header('Error') %>
+<FONT COLOR="#ff0000"><B><% $error |h %></B></FONT><BR><BR>
+<CENTER><INPUT TYPE="BUTTON" VALUE="OK" onClick="parent.cClick()"></CENTER>
+</BODY></HTML>
+% } else {
+<% header($action) %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+my %access_right = (
+ 'I' => 'Edit customer package invoice details',
+ 'C' => 'Edit customer package comments',
+);
+
+my %name = (
+ 'I' => 'invoice details',
+ 'C' => 'package comments',
+);
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+$cgi->param('detailtype') =~ /^(\w)$/ or die 'illegal detailtype';
+my $detailtype = $1;
+
+my $right = $access_right{$detailtype};
+die "access denied"
+ unless $curuser->access_right($right);
+
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'illegal pkgnum';
+my $pkgnum = $1;
+
+my $cust_pkg = qsearchs({
+ 'table' => 'cust_pkg',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'pkgnum' => $pkgnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+
+
+my @orig_details = $cust_pkg->cust_pkg_detail($detailtype);
+
+my $action = ucfirst($name{$detailtype}).
+ ( scalar(@orig_details) ? ' changed ' : ' added ' );
+
+my $param = $cgi->Vars;
+my @details = ();
+for ( my $row = 0; exists($param->{"detail$row"}); $row++ ) {
+ push @details, $param->{"detail$row"}
+ if $param->{"detail$row"} =~ /\S/;
+}
+
+my $error = $cust_pkg->set_cust_pkg_detail($detailtype, @details);
+
+</%init>
diff --git a/httemplate/edit/process/cust_refund.cgi b/httemplate/edit/process/cust_refund.cgi
new file mode 100755
index 000000000..5749e5346
--- /dev/null
+++ b/httemplate/edit/process/cust_refund.cgi
@@ -0,0 +1,56 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "cust_refund.cgi?". $cgi->query_string ) %>
+%} else {
+%
+% if ( $link eq 'popup' ) {
+%
+<% header('Refund entered') %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY></HTML>
+% } else {
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum") %>
+% }
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Refund payment')
+ || $FS::CurrentUser::CurrentUser->access_right('Post refund');
+
+$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!";
+my $custnum = $1;
+my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or die "unknown custnum $custnum";
+
+my $link = $cgi->param('popup') ? 'popup' : '';
+
+my $error = '';
+if ( $cgi->param('payby') =~ /^(CARD|CHEK)$/ ) {
+ my %options = ();
+ my $bop = $FS::payby::payby2bop{$1};
+ $cgi->param('refund') =~ /^(\d*)(\.\d{2})?$/
+ or die "illegal refund amount ". $cgi->param('refund');
+ my $refund = "$1$2";
+ $cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!";
+ my $paynum = $1;
+ my $reason = $cgi->param('reason');
+ my $paydate = $cgi->param('exp_year'). '-'. $cgi->param('exp_month'). '-01';
+ $options{'paydate'} = $paydate if $paydate =~ /^\d{2,4}-\d{1,2}-01$/;
+ $error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund,
+ 'paynum' => $paynum,
+ 'reason' => $reason,
+ %options );
+} else {
+ my $new = new FS::cust_refund ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('cust_refund') #huh? , 'paynum' )
+ } );
+ $error = $new->insert;
+}
+
+</%init>
diff --git a/httemplate/edit/process/cust_svc.cgi b/httemplate/edit/process/cust_svc.cgi
new file mode 100644
index 000000000..e22cbb201
--- /dev/null
+++ b/httemplate/edit/process/cust_svc.cgi
@@ -0,0 +1,30 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+% my $svcdb = $new->part_svc->svcdb;
+<% $cgi->redirect(popurl(3). "view/$svcdb.cgi?$svcnum") %>
+%}
+<%init>
+
+die 'access deined'
+ unless $FS::CurrentUser::CurrentUser->access_right('Change customer service');
+
+my $svcnum = $cgi->param('svcnum');
+
+my $old = qsearchs('cust_svc',{'svcnum'=>$svcnum}) if $svcnum;
+
+my $new = new FS::cust_svc ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('cust_svc')
+} );
+
+my $error;
+if ( $svcnum ) {
+ $error=$new->replace($old);
+} else {
+ $error=$new->insert;
+ $svcnum=$new->getfield('svcnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/domain_record.cgi b/httemplate/edit/process/domain_record.cgi
new file mode 100755
index 000000000..2e427e4fb
--- /dev/null
+++ b/httemplate/edit/process/domain_record.cgi
@@ -0,0 +1,30 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+% my $svcnum = $new->svcnum;
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice');
+
+my $recnum = $cgi->param('recnum');
+
+my $old = qsearchs('agent',{'recnum'=>$recnum}) if $recnum;
+
+my $new = new FS::domain_record ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('domain_record')
+} );
+
+my $error;
+if ( $recnum ) {
+ $error=$new->replace($old);
+} else {
+ $error=$new->insert;
+ $recnum=$new->getfield('recnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/elements/ApplicationCommon.html b/httemplate/edit/process/elements/ApplicationCommon.html
new file mode 100644
index 000000000..2782dc231
--- /dev/null
+++ b/httemplate/edit/process/elements/ApplicationCommon.html
@@ -0,0 +1,77 @@
+<%doc>
+
+Examples:
+
+ #cust_bill_pay
+ include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_bill_pay.cgi',
+ 'src_table' => 'cust_pay',
+ 'src_thing' => 'payment',
+ 'link_table' => 'cust_bill_pay',
+ )
+
+ #cust_credit_bill
+ include('elements/ApplicationCommon.html',
+ 'error_redirect' => 'cust_credit_bill.cgi',
+ 'src_table' => 'cust_credit',
+ 'src_thing' => 'credit',
+ 'link_table' => 'cust_credit_bill',
+ )
+
+</%doc>
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). $opt{error_redirect}. '?'. $cgi->query_string ) %>
+%} else {
+<% header("$src_thing application$to sucessful") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+ </HTML>
+% }
+<%init>
+
+my %opt = @_;
+
+my $src_thing = ucfirst($opt{'src_thing'});
+my $src_table = $opt{'src_table'};
+my $src_pkey = dbdef->table($src_table)->primary_key;
+
+my $to = $opt{'link_table'} =~ /refund/ ? ' to Refund' : '';
+
+$cgi->param($src_pkey) =~ /^(\d+)$/ or die "Illegal $src_pkey!";
+my $src_pkeyvalue = $1;
+
+my $src = qsearchs($src_table, { $src_pkey => $src_pkeyvalue } )
+ or die "No such $src_pkey: $src_pkeyvalue";
+
+my $cust_main = qsearchs('cust_main', { 'custnum' => $src->custnum } )
+ or die "Bogus $src_thing: not attached to customer";
+
+my $custnum = $cust_main->custnum;
+
+my $new;
+# $new = new FS::cust_refund ( {
+# 'reason' => 'Refunding payment', #enter reason in UI
+# 'refund' => $cgi->param('amount'),
+# 'payby' => 'BILL',
+# #'_date' => $cgi->param('_date'),
+# 'payinfo' => 'Cash', #enter payinfo in UI
+# 'paynum' => $paynum,
+# } );
+#} else {
+
+ my $class = 'FS::'. $opt{link_table};
+
+ $new = $class->new( {
+ map {
+ $_ => scalar($cgi->param($_));
+ } fields($opt{link_table})
+ } );
+
+#}
+
+my $error = $new->insert;
+
+</%init>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
new file mode 100644
index 000000000..5befdd337
--- /dev/null
+++ b/httemplate/edit/process/elements/process.html
@@ -0,0 +1,268 @@
+<%doc>
+
+Example:
+
+ include( 'elements/process.html',
+
+ ###
+ # required
+ ###
+
+ 'table' => 'tablename',
+
+ #? 'primary_key' => #required when the dbdef doesn't know...???
+ #? 'fields' => [] #""
+
+ ###
+ # optional
+ ###
+
+ 'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
+ 'viewall_ext' => 'html', #'cgi' or 'html', defaults to 'html'
+ OR
+ 'redirect' => 'view/table.cgi?', # value of primary key is appended
+ # (string or coderef returning a string)
+ OR
+ 'popup_reload' => 'Momentary success message', #will reload parent window
+
+ 'error_redirect' => popurl(2).'edit/table.cgi?', #query string appended
+
+ 'edit_ext' => 'html', #defaults to 'html', you might want 'cgi' while the
+ #naming is still inconsistent
+
+ 'copy_on_empty' => [ 'old_field_name', 'another_old_field', ... ],
+
+ 'clear_on_error' => [ 'form_field1', 'form_field2', ... ],
+
+ #pass an arrayref of hashrefs for multiple m2ms or m2names
+ #be certain you incorporate m2m_Common if you see error: param
+
+ 'process_m2m' => { 'link_table' => 'link_table_name',
+ 'target_table' => 'target_table_name',
+ #optional (see m2m_Common::process_m2m), if not specified
+ # all CGI params will be passed)
+ 'params' =>
+ },
+ 'process_m2name' => { 'link_table' => 'link_table_name',
+ 'link_static' => { 'column' => 'value' },
+ 'num_col' => 'column', #if column name is different in
+ #link_table than source_table
+ 'name_col' => 'name_column',
+ 'names_list' => [ 'list', 'names' ],
+
+ 'param_style' => 'link_table.value checkboxes',
+ #or#
+ 'param_style' => 'name_colN values',
+
+
+ },
+
+ #checks CGI params and whatever else before much else runs
+ #return an error string or empty for no error
+ 'precheck_callback' => sub { my( $cgi ) = @_; },
+
+ #supplies arguments to insert() and replace()
+ # for use with tables that are FS::option_Common
+ 'args_callback' => sub { my( $cgi, $object ) = @_; },
+
+ 'debug' => 1, #turns on debugging output
+
+ #agent virtualization
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Access Right Name',
+
+ )
+
+</%doc>
+%if ( $error ) {
+%
+% my $edit_ext = $opt{'edit_ext'} || 'html';
+% my $url = $opt{'error_redirect'} || popurl(2)."$table.$edit_ext";
+% if ( length($cgi->query_string) > 1920 ) { #stupid IE 2083 URL limit
+%
+% my $session = int(rand(4294967296)); #XXX
+% my $pref = new FS::access_user_pref({
+% 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
+% 'prefname' => "redirect$session",
+% 'prefvalue' => $cgi->query_string,
+% 'expiration' => time + 3600, #1h? 1m?
+% });
+% my $pref_error = $pref->insert;
+% if ( $pref_error ) {
+% die "FATAL: couldn't even set redirect cookie: $pref_error".
+% " attempting to set redirect$session to ". $cgi->query_string."\n";
+% }
+%
+<% $cgi->redirect("$url?redirect=$session") %>
+%
+% } else {
+%
+<% $cgi->redirect("$url?". $cgi->query_string ) %>
+%
+% }
+%
+% #different ways of handling success
+%
+%} elsif ( $opt{'popup_reload'} ) {
+
+ <% include('/elements/header-popup.html', $opt{'popup_reload'} ) %>
+
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY>
+ </HTML>
+
+%} else {
+%
+% $opt{'redirect'} = &{$opt{'redirect'}}($cgi, $new)
+% if ref($opt{'redirect'}) eq 'CODE';
+%
+% if ( $opt{'redirect'} ) {
+%
+<% $cgi->redirect( $opt{'redirect'}. $pkeyvalue ) %>
+%
+% } else {
+%
+% my $ext = $opt{'viewall_ext'} || 'html';
+%
+<% $cgi->redirect( popurl(3). ($opt{viewall_dir}||'search'). "/$table.$ext" ) %>
+%
+% }
+%
+%}
+%
+<%init>
+
+my $me = 'process.html:';
+
+my(%opt) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $error = '';
+if ( $opt{'precheck_callback'} ) {
+ $error = &{ $opt{'precheck_callback'} }( $cgi );
+}
+
+#false laziness w/edit.html
+my $table = $opt{'table'};
+my $class = "FS::$table";
+my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} ||
+my $fields = $opt{'fields'}
+ #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ];
+ || [ fields($table) ];
+
+my $pkeyvalue = $cgi->param($pkey);
+
+my $old = '';
+if ( $pkeyvalue ) {
+ $old = qsearchs({
+ 'table' => $table,
+ 'hashref' => { $pkey => $pkeyvalue },
+ 'extra_sql' => ( $opt{'agent_virt'}
+ ? ' AND '. $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ )
+ : ''
+ ),
+ });
+}
+
+my %hash =
+ map { my @entry = ( $_ => scalar($cgi->param($_)) );
+ $opt{'value_callback'} ? ( $_ => &{ $opt{'value_callback'} }( @entry ))
+ : ( @entry )
+ } @$fields;
+
+my $new = $class->new( \%hash );
+
+if ($old && exists($opt{'copy_on_empty'})) {
+ foreach my $field (@{$opt{'copy_on_empty'}}) {
+ $new->set($field, $old->get($field))
+ unless scalar($cgi->param($field));
+ }
+}
+
+if ( $opt{'agent_virt'} ) {
+ die "illegal agentnum"
+ unless $curuser->agentnums_href->{$new->agentnum}
+ or $opt{'agent_null_right'}
+ && ! $new->agentnum
+ && $curuser->access_right($opt{'agent_null_right'});
+}
+
+$error ||= $new->check;
+
+my @args = ();
+if ( !$error && $opt{'args_callback'} ) {
+ @args = &{ $opt{'args_callback'} }( $cgi, $new );
+}
+
+if ( !$error && $opt{'debug'} ) {
+ warn "$me updating record in $table table using $class class\n";
+ warn Dumper(\%hash);
+ warn "with args: \n". Dumper(\@args) if @args;
+}
+
+if ( !$error ) {
+ if ( $pkeyvalue ) {
+ $error = $new->replace($old, @args);
+ } else {
+ $error = $new->insert(@args);
+ $pkeyvalue = $new->getfield($pkey);
+ }
+}
+
+if ( !$error && $opt{'process_m2m'} ) {
+
+ my @process_m2m = ref($opt{'process_m2m'}) eq 'ARRAY'
+ ? @{ $opt{'process_m2m'} }
+ : ( $opt{'process_m2m'} );
+
+ foreach my $process_m2m (@process_m2m) {
+
+ $process_m2m->{'params'} ||= scalar($cgi->Vars);
+
+ warn "$me processing m2m:\n". Dumper( %$process_m2m )
+ if $opt{'debug'};
+
+ $error = $new->process_m2m( %$process_m2m );
+ }
+
+}
+
+if ( !$error && $opt{'process_m2name'} ) {
+
+ my @process_m2name = ref($opt{'process_m2name'}) eq 'ARRAY'
+ ? @{ $opt{'process_m2name'} }
+ : ( $opt{'process_m2name'} );
+
+
+ foreach my $process_m2name (@process_m2name) {
+
+ if ( $opt{'debug'} ) {
+ warn "$me processing m2name:\n". Dumper( %{ $process_m2name },
+ 'params' => scalar($cgi->Vars),
+ );
+ }
+
+ $error = $new->process_m2name( %{ $process_m2name },
+ 'params' => scalar($cgi->Vars),
+ );
+ }
+
+}
+
+
+if ( $error ) {
+ $cgi->param('error', $error);
+ if ( $opt{'clear_on_error'} && scalar(@{$opt{'clear_on_error'}}) ) {
+ foreach my $field (@{$opt{'clear_on_error'}}) {
+ $cgi->param($field, '')
+ }
+ }
+}
+
+</%init>
diff --git a/httemplate/edit/process/elements/svc_Common.html b/httemplate/edit/process/elements/svc_Common.html
new file mode 100644
index 000000000..8e8c99a42
--- /dev/null
+++ b/httemplate/edit/process/elements/svc_Common.html
@@ -0,0 +1,15 @@
+%
+%
+% my %opt = @_;
+% my $table = $opt{'table'};
+% $opt{'fields'} ||= [ fields($table) ];
+% push @{ $opt{'fields'} }, qw( pkgnum svcpart );
+%
+%
+<% include( 'process.html',
+ 'edit_ext' => 'cgi',
+ 'redirect' => popurl(3)."view/$table.cgi?",
+ %opt,
+ )
+%>
+
diff --git a/httemplate/edit/process/generic.cgi b/httemplate/edit/process/generic.cgi
new file mode 100644
index 000000000..642876386
--- /dev/null
+++ b/httemplate/edit/process/generic.cgi
@@ -0,0 +1,77 @@
+%if($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect($redirect_error . '?' . $cgi->query_string) %>
+%} else {
+<% $cgi->redirect($redirect_ok) %>
+%}
+<%doc>
+
+See elements/process.html, newer and somewhat along the same lines,
+though it still makes you setup a process file for the table.
+Perhaps safer, perhaps more of a pain in the ass.
+
+In any case, this is probably pretty deprecated; it is only used by
+part_virtual_field.cgi, and so its ACL is hardcoded to 'Configuration'.
+
+Welcome to generic.cgi.
+
+This script provides a generic edit/process/ backend for simple table
+editing. All it knows how to do is take the values entered into
+the script and insert them into the table specified by $cgi->param('table').
+If there's an existing record with the same primary key, it will be
+replaced. (Deletion will be added in the future.)
+
+Special cgi params for this script:
+table: the name of the table to be edited. The script will die horribly
+ if it can't find the table.
+redirect_ok: URL to be displayed after a successful edit. The value of
+ the record's primary key will be passed as a keyword.
+ Defaults to (freeside root)/view/$table.cgi.
+redirect_error: URL to be displayed if there's an error. The original
+ query string, plus the error message, will be passed.
+ Defaults to $cgi->referer() (i.e. go back where you
+ came from).
+
+</%doc>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $error;
+my $p2 = popurl(2);
+my $p3 = popurl(3);
+my $table = $cgi->param('table');
+my $dbdef = dbdef or die "Cannot fetch dbdef!";
+
+my $dbdef_table = $dbdef->table($table) or die "Cannot fetch schema for $table";
+
+my $pkey = $dbdef_table->primary_key or die "Cannot fetch pkey for $table";
+my $pkey_val = $cgi->param($pkey);
+
+
+#warn "new FS::Record ( $table, (hashref) )";
+my $new = FS::Record::new ( "FS::$table", {
+ map { $_, scalar($cgi->param($_)) } fields($table)
+} );
+
+#warn 'created $new of class '.ref($new);
+
+if($pkey_val and (my $old = qsearchs($table, { $pkey, $pkey_val} ))) {
+ # edit
+ $error = $new->replace($old);
+} else {
+ #add
+ $error = $new->insert;
+ $pkey_val = $new->getfield($pkey);
+ # New records usually don't have their primary keys set until after
+ # they've been checked/inserted, so grab the new $pkey_val so we can
+ # redirect to it.
+}
+
+my $redirect_ok = (($cgi->param('redirect_ok')) ?
+ $cgi->param('redirect_ok') : $p3."browse/generic.cgi?$table");
+my $redirect_error = (($cgi->param('redirect_error')) ?
+ $cgi->param('redirect_error') : $cgi->referer());
+
+</%init>
diff --git a/httemplate/edit/process/inventory_class.html b/httemplate/edit/process/inventory_class.html
new file mode 100644
index 000000000..dbf978e72
--- /dev/null
+++ b/httemplate/edit/process/inventory_class.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'inventory_class',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/invoice_logo.html b/httemplate/edit/process/invoice_logo.html
new file mode 100644
index 000000000..524d32542
--- /dev/null
+++ b/httemplate/edit/process/invoice_logo.html
@@ -0,0 +1,25 @@
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+$cgi->param('type') =~ /^(png|eps)$/ or die "illegal type";
+my $type = $1;
+
+$cgi->param('name') =~ /^([^\.\/]*)$/ or die "illegal name";
+my $tname = my $name = $1;
+$tname = "_$tname" if length($tname);
+
+$cgi->param('preview_session') =~ /^(\w*)$/ or die "illegal preview_session";
+my $session = $1;
+my $data = decode_base64( $curuser->option("logo_preview$session") );
+
+$conf->set_binary("logo$name.$type", $data);
+
+$cgi->redirect(popurl(3). "edit/invoice_logo.html?type=$type;name=$name;msg=Logo%20changed");
+
+</%init>
diff --git a/httemplate/edit/process/invoice_template.html b/httemplate/edit/process/invoice_template.html
new file mode 100644
index 000000000..6c9371ad1
--- /dev/null
+++ b/httemplate/edit/process/invoice_template.html
@@ -0,0 +1,15 @@
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+my $confname = $cgi->param('confname');
+my $value = $cgi->param('value');
+
+$conf->set($confname, $value);
+
+$cgi->redirect(popurl(3). 'browse/invoice_template.html');
+
+</%init>
diff --git a/httemplate/edit/process/msgcat.cgi b/httemplate/edit/process/msgcat.cgi
new file mode 100644
index 000000000..7175fa2b3
--- /dev/null
+++ b/httemplate/edit/process/msgcat.cgi
@@ -0,0 +1,22 @@
+%if ( $error ) {
+% $cgi->param('error',$error);
+<% $cgi->redirect($p. "msgcat.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/msgcat.cgi") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $error;
+foreach my $param ( grep { /^\d+$/ } $cgi->param ) {
+ my $old = qsearchs('msgcat', { msgnum=>$param } );
+ next if $old->msg eq $cgi->param($param); #no need to update identical records
+ my $new = new FS::msgcat { $old->hash };
+ $new->msg($cgi->param($param));
+ $error = $new->replace($old);
+ last if $error;
+}
+
+</%init>
diff --git a/httemplate/edit/process/part_bill_event.cgi b/httemplate/edit/process/part_bill_event.cgi
new file mode 100755
index 000000000..eb0529bb8
--- /dev/null
+++ b/httemplate/edit/process/part_bill_event.cgi
@@ -0,0 +1,106 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "part_bill_event.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3)."browse/part_bill_event.cgi") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $eventpart = $cgi->param('eventpart');
+
+my $old = qsearchs('part_bill_event',{'eventpart'=>$eventpart}) if $eventpart;
+
+#s/days/seconds/
+$cgi->param('seconds', int( $cgi->param('days') * 86400 ) );
+
+my $error;
+if ( ! $cgi->param('plan_weight_eventcode') ) {
+ $error = "Must select an action";
+} else {
+
+ $cgi->param('plan_weight_eventcode') =~ /^([\w\-]+):(\d+):(.*)$/s
+ or die "illegal plan_weight_eventcode:".
+ $cgi->param('plan_weight_eventcode');
+ $cgi->param('plan', $1);
+ $cgi->param('weight', $2);
+ my $eventcode = $3;
+ my $plandata = '';
+
+ my $rnum;
+ my $rtype;
+ my $reasonm;
+ my $class = '';
+ $class='c' if ($eventcode =~ /cancel/);
+ $class='s' if ($eventcode =~ /suspend/);
+ if ($class) {
+ $cgi->param("${class}reason") =~ /^(-?\d+)$/
+ or $error = "Invalid ${class}reason";
+ $rnum = $1;
+ if ($rnum == -1) {
+ $cgi->param("new${class}reasonT") =~ /^(\d+)$/
+ or $error = "Invalid new${class}reasonT";
+ $rtype = $1;
+ $cgi->param("new${class}reason") =~ /^([\s\w]+)$/
+ or $error = "Invalid new${class}reason";
+ $reasonm = $1;
+ }
+ }
+
+ if ($rnum == -1 && !$error) {
+ my $reason = new FS::reason ({ 'reason' => $reasonm,
+ 'reason_type' => $rtype,
+ });
+ $error = $reason->insert;
+ unless ($error) {
+ $rnum = $reason->reasonnum;
+ $cgi->param("${class}reason", $rnum);
+ $cgi->param("new${class}reason", '');
+ $cgi->param("new${class}reasonT", '');
+ }
+ }
+
+ while ( $eventcode =~ /%%%(\w+)%%%/ ) {
+ my $field = $1;
+ my $value = join(', ', $cgi->param($field) );
+ $cgi->param($field, $value); #in case it errors out
+ $eventcode =~ s/%%%$field%%%/$value/;
+ $plandata .= "$field $value\n";
+ }
+ $cgi->param('eventcode', $eventcode);
+ $cgi->param('plandata', $plandata);
+
+ unless($error) {
+
+ if ( $eventpart ) {
+
+ my $new = new FS::part_bill_event ( {
+ map { $_ => scalar($cgi->param($_)) }
+ fields('part_bill_event'),
+ } );
+ $new->setfield('reason' => $rnum);
+ $error = $new->replace($old);
+
+ } else {
+
+ foreach my $payby ( $cgi->param('payby') ) {
+ my $new = new FS::part_bill_event ( {
+ map { $_ => scalar($cgi->param($_)) }
+ grep { $_ ne 'payby' }
+ fields('part_bill_event')
+ } );
+ $new->setfield('payby' => $payby);
+ $new->setfield('reason' => $rnum );
+ $error = $new->insert;
+ last if $error;
+ }
+
+ }
+
+ }
+
+}
+
+</%init>
diff --git a/httemplate/edit/process/part_event.html b/httemplate/edit/process/part_event.html
new file mode 100644
index 000000000..428025fd1
--- /dev/null
+++ b/httemplate/edit/process/part_event.html
@@ -0,0 +1,86 @@
+<% include( 'elements/process.html',
+ #'debug' => 1,
+ 'table' => 'part_event',
+ 'viewall_dir' => 'browse',
+ 'process_m2name' =>
+ {
+ 'link_table' => 'part_event_condition',
+ 'num_col' => 'eventpart',
+ 'name_col' => 'conditionname',
+ 'names_list' => [ FS::part_event_condition->all_conditionnames() ],
+ 'param_style' => 'name_colN values',
+ 'args_callback' => sub { # FS/FS/m2name_Common.pm
+ my( $object, $prefix, $params, $listref ) = @_;
+ #warn "$object $prefix $params $listref\n";
+
+ my $cond = $object->conditionname;
+
+ my %option_fields = $object->option_fields;
+
+ push @$listref, map {
+ my $field = $_;
+
+ my $cgi_field = "$prefix$cond.$field";
+
+ my $value = $params->{$cgi_field};
+
+ my $info = $option_fields{$_};
+ $info = { label=>$info, type=>'text' }
+ unless ref($info);
+
+ if ( $info->{'type'} =~
+ /^(select|checkbox)-?multiple$/
+ or $info->{'type'} =~ /^select/
+ && $info->{'multiple'}
+ )
+ {
+ #special processing for compound fields
+ $value = { map { $_ => 1 }
+ split(/\0/, $value)
+ };
+ } elsif ( $info->{'type'} eq 'freq' ) {
+ $value .= $params->{$cgi_field.'_units'};
+ }
+
+ #warn "value of $cgi_field is $value\n";
+
+ ( $field => $value );
+ }
+ keys %option_fields;
+ },
+ },
+
+ 'args_callback' => sub {
+
+ my( $cgi, $object ) = @_;
+
+ my $prefix = $object->action.'.';
+
+ map { my $option = $_;
+ #my $value = scalar( $cgi->param( "$prefix$option" ) );
+ my $value = join(',', $cgi->param( "$prefix$option" ) );
+
+ if ( $option eq 'reasonnum' && $value == -1 ) {
+ $value = {
+ 'typenum' => scalar( $cgi->param( "new$prefix${option}T" ) ),
+ 'reason' => scalar( $cgi->param( "new$prefix${option}" ) ),
+ };
+ }
+
+ ( $option => $value );
+ }
+ @{ $object->option_fields_listref };
+
+ },
+
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Edit global billing events',
+)
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit billing events')
+ || $FS::CurrentUser::CurrentUser->access_right('Edit global billing events');
+
+</%init>
diff --git a/httemplate/edit/process/part_export.cgi b/httemplate/edit/process/part_export.cgi
new file mode 100644
index 000000000..b5f82e892
--- /dev/null
+++ b/httemplate/edit/process/part_export.cgi
@@ -0,0 +1,41 @@
+%if ( $error ) {
+% $cgi->param('error', $error );
+<% $cgi->redirect(popurl(2). "part_export.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/part_export.cgi") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $exportnum = $cgi->param('exportnum');
+
+my $old = qsearchs('part_export', { 'exportnum'=>$exportnum } ) if $exportnum;
+
+#fixup options
+#warn join('-', split(',',$cgi->param('options')));
+my %options = map {
+ my $value = $cgi->param($_);
+ $value =~ s/\r\n/\n/g; #browsers? (textarea)
+ $_ => $value;
+} split(',', $cgi->param('options'));
+
+my $new = new FS::part_export ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('part_export')
+} );
+
+my $error;
+if ( $exportnum ) {
+ #warn $old;
+ #warn $exportnum;
+ #warn $new->machine;
+ $error = $new->replace($old,\%options);
+} else {
+ $error = $new->insert(\%options);
+# $exportnum = $new->exportnum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
new file mode 100755
index 000000000..96c5b36b7
--- /dev/null
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -0,0 +1,198 @@
+<% include( 'elements/process.html',
+ #'debug' => 1,
+ 'table' => 'part_pkg',
+ 'agent_virt' => 1,
+ 'agent_null_right' => \@agent_null_right,
+ 'redirect' => $redirect_callback,
+ 'viewall_dir' => 'browse',
+ 'viewall_ext' => 'cgi',
+ 'edit_ext' => 'cgi',
+ 'precheck_callback' => $precheck_callback,
+ 'args_callback' => $args_callback,
+ 'process_m2m' => \@process_m2m,
+ )
+%>
+<%init>
+
+my $customizing = ( ! $cgi->param('pkgpart') && $cgi->param('pkgnum') );
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $edit_global = 'Edit global package definitions';
+my $customize = 'Customize customer package';
+
+die "access denied"
+ unless $curuser->access_right('Edit package definitions')
+ || $curuser->access_right($edit_global)
+ || ( $customizing && $curuser->access_right($customize) );
+
+my @agent_null_right = ( $edit_global );
+push @agent_null_right, $customize if $customizing;
+
+
+my $precheck_callback = sub {
+ my( $cgi ) = @_;
+
+ my $conf = new FS::Conf;
+
+ foreach (qw( setuptax recurtax disabled )) {
+ $cgi->param($_, '') unless defined $cgi->param($_);
+ }
+
+ return 'Must select a tax class'
+ if $cgi->param('taxclass') eq '(select)';
+
+ my @agents = ();
+ foreach ($cgi->param('agent_type')) {
+ /^(\d+)$/;
+ push @agents, $1 if $1;
+ }
+ return "At least one agent type must be specified."
+ unless scalar(@agents)
+ || ( $cgi->param('clone') && $cgi->param('clone') =~ /^\d+$/ )
+ || ( !$cgi->param('pkgpart') && $conf->exists('agent-defaultpkg') )
+ || $cgi->param('disabled')
+ || $cgi->param('agentnum');
+
+ return '';
+
+};
+
+my $custnum = '';
+
+my $args_callback = sub {
+ my( $cgi, $new ) = @_;
+
+ my @args = ( 'primary_svc' => scalar($cgi->param('pkg_svc_primary')) );
+
+ ##
+ #options
+ ##
+
+ $cgi->param('plan') =~ /^(\w+)$/ or die 'unparsable plan';
+ my $plan = $1;
+
+ tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() };
+ my $href = $plans{$plan}->{'fields'};
+
+ my $error = '';
+ my $options = $cgi->param($plan."__OPTIONS");
+ my @options = split(',', $options);
+ my %options =
+ map { my $optionname = $_;
+ my $param = $plan."__$optionname";
+ my $parser = exists($href->{$optionname}{parse})
+ ? $href->{$optionname}{parse}
+ : sub { shift };
+ my $value = join(', ', &$parser($cgi->param($param)));
+ my $check = $href->{$optionname}{check};
+ if ( $check && ! &$check($value) ) {
+ $value = join(', ', $cgi->param($param));
+ $error ||= "Illegal ".
+ ($href->{$optionname}{name}||$optionname). ": $value";
+ }
+ ( $optionname => $value );
+ }
+ @options;
+
+ foreach ( split(',', $cgi->param('taxproductnums') ) ) {
+ my $value = $cgi->param("taxproductnum_$_");
+ $error ||= "Illegal taxproductnum_$_: $value"
+ unless ( $value =~ /^\d*$/ );
+ $options{"usage_taxproductnum_$_"} = $value;
+ }
+
+ $options{$_} = scalar( $cgi->param($_) )
+ for (qw( setup_fee recur_fee ));
+
+ push @args, 'options' => \%options;
+
+ ###
+ #pkg_svc
+ ###
+
+ my %pkg_svc = map { $_ => scalar($cgi->param("pkg_svc$_")) }
+ map { $_->svcpart }
+ qsearch('part_svc', {} );
+
+ push @args, 'pkg_svc' => \%pkg_svc;
+
+ ###
+ # cust_pkg and custnum_ref (inserts only)
+ ###
+ unless ( $cgi->param('pkgpart') ) {
+ push @args, 'cust_pkg' => scalar($cgi->param('pkgnum')),
+ 'custnum_ref' => \$custnum;
+ }
+
+ warn "args: ".join('/', @args). "\n";
+
+ @args;
+
+};
+
+my $redirect_callback = sub {
+ #my( $cgi, $new ) = @_;
+ return '' unless $custnum;
+ popurl(3). "view/cust_main.cgi?keywords=$custnum;dummy=";
+};
+
+#these should probably move to @args above and be processed by part_pkg.pm...
+
+$cgi->param('tax_override') =~ /^([\d,]+)$/;
+my (@tax_overrides) = (grep "$_", split (",", $1));
+
+my @process_m2m = (
+ {
+ 'link_table' => 'part_pkg_taxoverride',
+ 'target_table' => 'tax_class',
+ 'params' => \@tax_overrides,
+ },
+ { 'link_table' => 'part_pkg_link',
+ 'target_table' => 'part_pkg',
+ 'base_field' => 'src_pkgpart',
+ 'target_field' => 'dst_pkgpart',
+ 'hashref' => { 'link_type' => 'bill' },
+ 'params' => [ map $cgi->param($_), grep /^bill_dst_pkgpart/, $cgi->param ],
+ },
+ { 'link_table' => 'part_pkg_link',
+ 'target_table' => 'part_pkg',
+ 'base_field' => 'src_pkgpart',
+ 'target_field' => 'dst_pkgpart',
+ 'hashref' => { 'link_type' => 'svc' },
+ 'params' => [ map $cgi->param($_), grep /^svc_dst_pkgpart/, $cgi->param ],
+ },
+);
+
+foreach my $override_class ($cgi->param) {
+ next unless $override_class =~ /^tax_override_(\w+)$/;
+ my $class = $1;
+
+ my (@tax_overrides) = (grep "$_", split (",", $1))
+ if $cgi->param($override_class) =~ /^([\d,]+)$/;
+
+ push @process_m2m, {
+ 'link_table' => 'part_pkg_taxoverride',
+ 'target_table' => 'tax_class',
+ 'hashref' => { 'usage_class' => $class },
+ 'params' => [ @tax_overrides ],
+ };
+
+}
+
+my $conf = new FS::Conf;
+
+if ( $cgi->param('pkgpart') || ! $conf->exists('agent_defaultpkg') ) {
+ my @agents = ();
+ foreach ($cgi->param('agent_type')) {
+ /^(\d+)$/;
+ push @agents, $1 if $1;
+ }
+ push @process_m2m, {
+ 'link_table' => 'type_pkgs',
+ 'target_table' => 'agent_type',
+ 'params' => \@agents,
+ };
+}
+
+</%init>
diff --git a/httemplate/edit/process/part_pkg_taxclass.html b/httemplate/edit/process/part_pkg_taxclass.html
new file mode 100644
index 000000000..8f149bb94
--- /dev/null
+++ b/httemplate/edit/process/part_pkg_taxclass.html
@@ -0,0 +1,53 @@
+% if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "part_pkg_taxclass.html?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/cust_main_county.cgi?taxclass=". uri_escape($part_pkg_taxclass->taxclass) ) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $part_pkg_taxclass = new FS::part_pkg_taxclass {
+ 'taxclass' => $cgi->param('taxclass'),
+};
+
+#maybe this whole thing should be in a transaction. at some point, no biggie
+#none of the follow-up stuff will fail unless there's a more serious problem
+#than a hanging record in part_pkg_taxclass...
+
+my $error = $part_pkg_taxclass->insert;
+
+unless ( $error ) {
+ #auto-add the new taxclass to any regions that have taxclasses already
+
+ my $sth = dbh->prepare("
+ SELECT country, state, county FROM cust_main_county
+ WHERE taxclass IS NOT NULL AND taxclass != ''
+ GROUP BY country, state, county
+ ") or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ while ( my $row = $sth->fetchrow_hashref ) {
+ warn "inserting for $row";
+ my $cust_main_county = new FS::cust_main_county {
+ 'country' => $row->{country},
+ 'state' => $row->{state},
+ 'county' => $row->{county},
+ 'tax' => 0,
+ 'taxclass' => $part_pkg_taxclass->taxclass,
+ #exempt_amount
+ #taxname
+ #setuptax
+ #recurtax
+ };
+ $error = $cust_main_county->insert;
+ #last if $error;
+ die $error if $error;
+ }
+
+
+}
+
+</%init>
diff --git a/httemplate/edit/process/part_referral.html b/httemplate/edit/process/part_referral.html
new file mode 100755
index 000000000..40cbc97bf
--- /dev/null
+++ b/httemplate/edit/process/part_referral.html
@@ -0,0 +1,12 @@
+<% include( 'elements/process.html',
+ 'table' => 'part_referral',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit advertising sources')
+ || $FS::CurrentUser::CurrentUser->access_right('Edit global advertising sources');
+
+</%init>
diff --git a/httemplate/edit/process/part_svc.cgi b/httemplate/edit/process/part_svc.cgi
new file mode 100755
index 000000000..65de3fc6c
--- /dev/null
+++ b/httemplate/edit/process/part_svc.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::part_svc::process', $cgi;
+
+</%init>
diff --git a/httemplate/edit/process/payment_gateway.html b/httemplate/edit/process/payment_gateway.html
new file mode 100644
index 000000000..b16bc3d27
--- /dev/null
+++ b/httemplate/edit/process/payment_gateway.html
@@ -0,0 +1,35 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "payment_gateway.html?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/payment_gateway.html") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $gatewaynum = $cgi->param('gatewaynum');
+
+my $old = qsearchs('payment_gateway',{'gatewaynum'=>$gatewaynum}) if $gatewaynum;
+
+my $new = new FS::payment_gateway ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('payment_gateway')
+} );
+
+my @options = split(/\r?\n/, $cgi->param('gateway_options') );
+pop @options
+ if scalar(@options) % 2 && $options[-1] =~ /^\s*$/;
+my %options = @options;
+
+my $error;
+if ( $gatewaynum ) {
+ $error=$new->replace($old, \%options);
+} else {
+ $error=$new->insert(\%options);
+ $gatewaynum=$new->getfield('gatewaynum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/pkg_category.html b/httemplate/edit/process/pkg_category.html
new file mode 100644
index 000000000..50cd5cb29
--- /dev/null
+++ b/httemplate/edit/process/pkg_category.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'pkg_category',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/pkg_class.html b/httemplate/edit/process/pkg_class.html
new file mode 100644
index 000000000..b196df3f7
--- /dev/null
+++ b/httemplate/edit/process/pkg_class.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'pkg_class',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/prepay_credit.cgi b/httemplate/edit/process/prepay_credit.cgi
new file mode 100644
index 000000000..8f2eb2b25
--- /dev/null
+++ b/httemplate/edit/process/prepay_credit.cgi
@@ -0,0 +1,62 @@
+%unless ( ref($error) ) {
+% $cgi->param('error', $error );
+<% $cgi->redirect(popurl(3). "edit/prepay_credit.cgi?". $cgi->query_string ) %>
+% } else {
+
+<% include('/elements/header.html', "$num prepaid cards generated".
+ ( $agent ? ' for '.$agent->agent : '' )
+ )
+%>
+
+<FONT SIZE="+1">
+% foreach my $card ( @$error ) {
+
+ <code><% $card %></code>
+ -
+ <% $hashref->{amount} ? sprintf('$%.2f', $hashref->{amount} ) : '' %>
+ <% $hashref->{amount} && $hashref->{seconds} ? 'and' : '' %>
+ <% $hashref->{seconds} ? duration_exact($hashref->{seconds}) : '' %>
+ <% $hashref->{upbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{upbytes}) : '' %>
+ <% $hashref->{downbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{downbytes}) : '' %>
+ <% $hashref->{totalbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{totalbytes}) : '' %>
+ <br>
+% }
+
+</FONT>
+
+<% include('/elements/footer.html') %>
+
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $hashref = {};
+
+my $agent = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agent = qsearchs('agent', { 'agentnum' => $hashref->{agentnum}=$1 } );
+}
+
+my $error = '';
+
+my $num = 0;
+if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) {
+ $num = $1;
+} else {
+ $error = 'Illegal number of prepaid cards: '. $cgi->param('num');
+}
+
+$hashref->{amount} = $cgi->param('amount');
+$hashref->{seconds} = $cgi->param('seconds') * $cgi->param('multiplier');
+$hashref->{upbytes} = $cgi->param('upbytes') * $cgi->param('upmultiplier');
+$hashref->{downbytes} = $cgi->param('downbytes') * $cgi->param('downmultiplier');
+$hashref->{totalbytes} = $cgi->param('totalbytes') * $cgi->param('totalmultiplier');
+
+$error ||= FS::prepay_credit::generate( $num,
+ scalar($cgi->param('type')),
+ $hashref
+ );
+
+</%init>
diff --git a/httemplate/edit/process/quick-charge.cgi b/httemplate/edit/process/quick-charge.cgi
new file mode 100644
index 000000000..8fa57ddea
--- /dev/null
+++ b/httemplate/edit/process/quick-charge.cgi
@@ -0,0 +1,68 @@
+% if ( $error ) {
+% $cgi->param('error', $error );
+<% $cgi->redirect($p.'quick-charge.html?'. $cgi->query_string) %>
+% } else {
+<% header("One-time charge added") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('One-time charge');
+
+my $error = '';
+my $conf = new FS::conf;
+my $param = $cgi->Vars;
+
+my @description = ();
+for ( my $row = 0; exists($param->{"description$row"}); $row++ ) {
+ push @description, $param->{"description$row"}
+ if ($param->{"description$row"} =~ /\S/);
+}
+
+$param->{"custnum"} =~ /^(\d+)$/
+ or $error .= "Illegal customer number " . $param->{"custnum"} . " ";
+my $custnum = $1;
+
+$param->{"amount"} =~ /^\s*(\d+(\.\d{1,2})?)\s*$/
+ or $error .= "Illegal amount " . $param->{"amount"} . " ";
+my $amount = $1;
+
+my $quantity = 1;
+if ( $cgi->param('quantity') =~ /^\s*(\d+)\s*$/ ) {
+ $quantity = $1;
+}
+
+$param->{'tax_override'} =~ /^\s*([,\d]*)\s*$/
+ or $error .= "Illegal tax override " . $param->{"tax_override"} . " ";
+my $override = $1;
+
+if ( $param->{'taxclass'} eq '(select)' ) {
+ $error .= "Must select a tax class. "
+ unless ($conf->exists('enable_taxproducts') &&
+ ( $override || $param->{taxproductnum} )
+ );
+ $cgi->param('taxclass', '');
+}
+
+unless ( $error ) {
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or $error .= "Unknown customer number $custnum. ";
+
+ $error ||= $cust_main->charge( {
+ 'amount' => $amount,
+ 'quantity' => $quantity,
+ 'pkg' => scalar($cgi->param('pkg')),
+ 'setuptax' => scalar($cgi->param('setuptax')),
+ 'taxclass' => scalar($cgi->param('taxclass')),
+ 'taxproductnum' => scalar($cgi->param('taxproductnum')),
+ 'tax_override' => $override,
+ 'classnum' => scalar($cgi->param('classnum')),
+ 'additional' => \@description,
+ } );
+}
+
+</%init>
diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi
new file mode 100644
index 000000000..9c2474330
--- /dev/null
+++ b/httemplate/edit/process/quick-cust_pkg.cgi
@@ -0,0 +1,63 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(3). 'misc/order_pkg.html?'. $cgi->query_string ) %>
+%} else {
+% my $frag = "cust_pkg". $cust_pkg->pkgnum;
+<% header('Package ordered') %>
+ <SCRIPT TYPE="text/javascript">
+ // XXX fancy ajax rebuild table at some point, but a page reload will do for now
+
+ // XXX chop off trailing #target and replace... ?
+ window.top.location = '<% popurl(3). "view/cust_main.cgi?keywords=$custnum;fragment=$frag#$frag" %>';
+
+ </SCRIPT>
+
+ </BODY></HTML>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Order customer package');
+
+#untaint custnum (probably not necessary, searching for it is escape enough)
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die 'illegal custnum '. $cgi->param('custnum');
+my $custnum = $1;
+my $cust_main = qsearchs({
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die 'unknown custnum' unless $cust_main;
+
+#probably not necessary, taken care of by cust_pkg::check
+$cgi->param('pkgpart') =~ /^(\d+)$/
+ or die 'illegal pkgpart '. $cgi->param('pkgpart');
+my $pkgpart = $1;
+$cgi->param('refnum') =~ /^(\d*)$/
+ or die 'illegal refnum '. $cgi->param('refnum');
+my $refnum = $1;
+$cgi->param('locationnum') =~ /^(\-?\d*)$/
+ or die 'illegal locationnum '. $cgi->param('locationnum');
+my $locationnum = $1;
+
+my $cust_pkg = new FS::cust_pkg {
+ 'custnum' => $custnum,
+ 'pkgpart' => $pkgpart,
+ 'refnum' => $refnum,
+ 'locationnum' => $locationnum,
+};
+
+my %opt = ( 'cust_pkg' => $cust_pkg );
+
+if ( $locationnum == -1 ) {
+ my $cust_location = new FS::cust_location {
+ map { $_ => scalar($cgi->param($_)) }
+ qw( custnum address1 address2 city county state zip country )
+ };
+ $opt{'cust_location'} = $cust_location;
+}
+
+my $error = $cust_main->order_pkg( %opt );
+
+</%init>
diff --git a/httemplate/edit/process/rate.cgi b/httemplate/edit/process/rate.cgi
new file mode 100755
index 000000000..48d9322ca
--- /dev/null
+++ b/httemplate/edit/process/rate.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $server = new FS::UI::Web::JSRPC 'FS::rate::process', $cgi;
+
+</%init>
diff --git a/httemplate/edit/process/rate_detail.html b/httemplate/edit/process/rate_detail.html
new file mode 100644
index 000000000..6200d615f
--- /dev/null
+++ b/httemplate/edit/process/rate_detail.html
@@ -0,0 +1,13 @@
+<% include( 'elements/process.html',
+ 'table' => 'rate_detail',
+ 'popup_reload' => 'Rate changed', #a popup "parent reload" for now
+ #someday change the individual element and go away instead
+ )
+%>
+<%init>
+
+my $conf = new FS::Conf;
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/rate_region.cgi b/httemplate/edit/process/rate_region.cgi
new file mode 100755
index 000000000..882991e9d
--- /dev/null
+++ b/httemplate/edit/process/rate_region.cgi
@@ -0,0 +1,57 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "rate_region.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/rate_region.html") %>
+%}
+<%init>
+
+my $conf = new FS::Conf;
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $regionnum = $cgi->param('regionnum');
+
+my $old = qsearchs('rate_region', { 'regionnum' => $regionnum } ) if $regionnum;
+
+my $new = new FS::rate_region ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } ( fields('rate_region') )
+} );
+
+my $countrycode = $cgi->param('countrycode');
+my @npa = split(/\s*,\s*/, $cgi->param('npa'));
+$npa[0] = '' unless @npa;
+my @rate_prefix = map {
+ #my($npa,$nxx) = split('-', $_);
+ s/\D//g;
+ new FS::rate_prefix {
+ 'countrycode' => $countrycode,
+ #'npa' => $npa,
+ #'nxx' => $nxx,
+ 'npa' => $_,
+ }
+ } @npa;
+
+my @dest_detail = map {
+ my $ratenum = $_->ratenum;
+ new FS::rate_detail {
+ 'ratenum' => $ratenum,
+ map { $_ => $cgi->param("$_$ratenum") }
+ qw( min_included min_charge sec_granularity classnum )
+ };
+} qsearch('rate', {} );
+
+
+my $error;
+if ( $regionnum ) {
+ $error = $new->replace($old, 'rate_prefix' => \@rate_prefix,
+ 'dest_detail' => \@dest_detail, );
+} else {
+ $error = $new->insert( 'rate_prefix' => \@rate_prefix,
+ 'dest_detail' => \@dest_detail, );
+ $regionnum = $new->getfield('regionnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/reason.html b/httemplate/edit/process/reason.html
new file mode 100644
index 000000000..cb79ed254
--- /dev/null
+++ b/httemplate/edit/process/reason.html
@@ -0,0 +1,12 @@
+<% include( 'elements/process.html',
+ 'table' => 'reason',
+ 'redirect' => popurl(3) . 'browse/reason.html?class=' .
+ $cgi->param('class') . '&',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/reason_type.html b/httemplate/edit/process/reason_type.html
new file mode 100644
index 000000000..3172b27c4
--- /dev/null
+++ b/httemplate/edit/process/reason_type.html
@@ -0,0 +1,12 @@
+<% include( 'elements/process.html',
+ 'table' => 'reason_type',
+ 'redirect' => popurl(3) . 'browse/reason_type.html?class=' .
+ $cgi->param('class') . '&',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/reg_code.cgi b/httemplate/edit/process/reg_code.cgi
new file mode 100644
index 000000000..035e10b90
--- /dev/null
+++ b/httemplate/edit/process/reg_code.cgi
@@ -0,0 +1,45 @@
+%unless ( ref($error) ) {
+% $cgi->param('error'. $error );
+<% $cgi->redirect(popurl(3). "edit/reg_code.cgi?". $cgi->query_string ) %>
+% } else {
+
+<% include("/elements/header.html","$num registration codes generated for ". $agent->agent, menubar(
+ 'View all agents' => popurl(3). 'browse/agent.cgi',
+) ) %>
+
+<PRE><FONT SIZE="+1">
+% foreach my $code ( @$error ) {
+ <% $code %>
+% }
+</FONT></PRE>
+
+<% include('/elements/footer.html') %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('agentnum') =~ /^(\d+)$/
+ or errorpage('illegal agentnum '. $cgi->param('agentnum'));
+my $agentnum = $1;
+my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+
+my $error = '';
+
+my $num = 0;
+if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) {
+ $num = $1;
+} else {
+ $error = 'Illegal number of codes: '. $cgi->param('num');
+}
+
+my @pkgparts =
+ map { /^pkgpart(.*)$/; $1 }
+ grep { $cgi->param($_) }
+ grep { /^pkgpart/ }
+ $cgi->param;
+
+$error ||= $agent->generate_reg_codes($num, \@pkgparts);
+
+</%init>
diff --git a/httemplate/edit/process/router.cgi b/httemplate/edit/process/router.cgi
new file mode 100644
index 000000000..3cbb8c58e
--- /dev/null
+++ b/httemplate/edit/process/router.cgi
@@ -0,0 +1,20 @@
+<% include('elements/process.html',
+ 'table' => 'router',
+ 'viewall_dir' => 'browse',
+ 'viewall_ext' => 'cgi',
+ 'edit_ext' => 'cgi',
+ 'process_m2m' => { 'link_table' => 'part_svc_router',
+ 'target_table' => 'part_svc',
+ },
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Broadband global configuration',
+ )
+%>
+<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+</%init>
diff --git a/httemplate/edit/process/svc_Common.html b/httemplate/edit/process/svc_Common.html
new file mode 100644
index 000000000..cf5f01f71
--- /dev/null
+++ b/httemplate/edit/process/svc_Common.html
@@ -0,0 +1,16 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => $table,
+ 'redirect' => popurl(3)."view/svc_Common.html?svcdb=$table;svcnum=",
+ 'error_redirect' => popurl(3)."edit/svc_Common.html?svcdb=$table;",
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparsable svcdb";
+my $table = $1;
+require "FS/$table.pm";
+
+</%init>
diff --git a/httemplate/edit/process/svc_acct.cgi b/httemplate/edit/process/svc_acct.cgi
new file mode 100755
index 000000000..0a89e253c
--- /dev/null
+++ b/httemplate/edit/process/svc_acct.cgi
@@ -0,0 +1,64 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_acct.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_acct.cgi?" . $svcnum ) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum = $1;
+
+my $old;
+if ( $svcnum ) {
+ $old = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
+ or die "fatal: can't find account (svcnum $svcnum)!";
+} else {
+ $old = '';
+}
+
+#unmunge popnum
+$cgi->param('popnum', (split(/:/, $cgi->param('popnum') ))[0] );
+
+#unmunge passwd
+if ( $cgi->param('_password') eq '*HIDDEN*' ) {
+ die "fatal: no previous account to recall hidden password from!" unless $old;
+ $cgi->param('_password',$old->getfield('_password'));
+}
+
+#unmunge usergroup
+$cgi->param('usergroup', [ $cgi->param('radius_usergroup') ] );
+
+#unmunge bytecounts
+foreach (map { $_,$_."_threshold" } qw( upbytes downbytes totalbytes )) {
+ $cgi->param($_, FS::UI::bytecount::parse_bytecount($cgi->param($_)) );
+}
+
+my %hash = $svcnum ? $old->hash : ();
+map {
+ $hash{$_} = scalar($cgi->param($_));
+ #} qw(svcnum pkgnum svcpart username _password popnum uid gid finger dir
+ # shell quota slipip)
+ } (fields('svc_acct'), qw ( pkgnum svcpart usergroup ));
+my $new = new FS::svc_acct ( \%hash );
+
+my $error;
+if ( $svcnum ) {
+ foreach (grep { $old->$_ != $new->$_ } qw( seconds upbytes downbytes totalbytes )) {
+ my %hash = map { $_ => $new->$_ }
+ grep { $new->$_ }
+ qw( seconds upbytes downbytes totalbytes );
+
+ $error = $new->set_usage(\%hash); #unoverlimit and trigger radius changes
+ last; #once is enough
+ }
+ $error ||= $new->replace($old);
+} else {
+ $error = $new->insert;
+ $svcnum = $new->svcnum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/svc_acct_pop.cgi b/httemplate/edit/process/svc_acct_pop.cgi
new file mode 100755
index 000000000..6e823a824
--- /dev/null
+++ b/httemplate/edit/process/svc_acct_pop.cgi
@@ -0,0 +1,33 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_acct_pop.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/svc_acct_pop.cgi") %>
+%}
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Dialup configuration')
+ || $curuser->access_right('Dialup global configuration');
+
+my $popnum = $cgi->param('popnum');
+
+my $old = qsearchs('svc_acct_pop',{'popnum'=>$popnum}) if $popnum;
+
+my $new = new FS::svc_acct_pop ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('svc_acct_pop')
+} );
+
+my $error = '';
+if ( $popnum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $popnum=$new->getfield('popnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/svc_broadband.cgi b/httemplate/edit/process/svc_broadband.cgi
new file mode 100644
index 000000000..d5c9820bb
--- /dev/null
+++ b/httemplate/edit/process/svc_broadband.cgi
@@ -0,0 +1,8 @@
+<% include('elements/svc_Common.html', 'table' => 'svc_broadband') %>
+<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/process/svc_domain.cgi b/httemplate/edit/process/svc_domain.cgi
new file mode 100755
index 000000000..9993a879e
--- /dev/null
+++ b/httemplate/edit/process/svc_domain.cgi
@@ -0,0 +1,33 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_domain.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+#remove this to actually test the domains!
+$FS::svc_domain::whois_hack = 1;
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum = $1;
+
+my $new = new FS::svc_domain ( {
+ map {
+ $_, scalar($cgi->param($_));
+ #} qw(svcnum pkgnum svcpart domain action purpose)
+ } ( fields('svc_domain'), qw( pkgnum svcpart action purpose ) )
+} );
+
+my $error = '';
+if ($cgi->param('svcnum')) {
+ $error="Can't modify a domain!";
+} else {
+ $error=$new->insert;
+ $svcnum=$new->svcnum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/svc_external.cgi b/httemplate/edit/process/svc_external.cgi
new file mode 100755
index 000000000..673e5a5a0
--- /dev/null
+++ b/httemplate/edit/process/svc_external.cgi
@@ -0,0 +1,31 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_external.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_external.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum =$1;
+
+my $old = qsearchs('svc_external',{'svcnum'=>$svcnum}) if $svcnum;
+
+my $new = new FS::svc_external ( {
+ map {
+ ($_, scalar($cgi->param($_)));
+ } ( fields('svc_external'), qw( pkgnum svcpart ) )
+} );
+
+my $error = '';
+if ( $svcnum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $svcnum = $new->getfield('svcnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/svc_forward.cgi b/httemplate/edit/process/svc_forward.cgi
new file mode 100755
index 000000000..fffad84d6
--- /dev/null
+++ b/httemplate/edit/process/svc_forward.cgi
@@ -0,0 +1,31 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_forward.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_forward.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum =$1;
+
+my $old = qsearchs('svc_forward',{'svcnum'=>$svcnum}) if $svcnum;
+
+my $new = new FS::svc_forward ( {
+ map {
+ ($_, scalar($cgi->param($_)));
+ } ( fields('svc_forward'), qw( pkgnum svcpart ) )
+} );
+
+my $error = '';
+if ( $svcnum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $svcnum = $new->getfield('svcnum');
+}
+
+</%init>
diff --git a/httemplate/edit/process/svc_phone.html b/httemplate/edit/process/svc_phone.html
new file mode 100644
index 000000000..27a703cdf
--- /dev/null
+++ b/httemplate/edit/process/svc_phone.html
@@ -0,0 +1,10 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => 'svc_phone',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/process/svc_www.cgi b/httemplate/edit/process/svc_www.cgi
new file mode 100644
index 000000000..f02d25305
--- /dev/null
+++ b/httemplate/edit/process/svc_www.cgi
@@ -0,0 +1,38 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "svc_www.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_www.cgi?" . $svcnum ) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum = $1;
+
+my $old;
+if ( $svcnum ) {
+ $old = qsearchs('svc_www', { 'svcnum' => $svcnum } )
+ or die "fatal: can't find website (svcnum $svcnum)!";
+} else {
+ $old = '';
+}
+
+my $new = new FS::svc_www ( {
+ map {
+ ($_, scalar($cgi->param($_)));
+ #} qw(svcnum pkgnum svcpart recnum usersvc)
+ } ( fields('svc_www'), qw( pkgnum svcpart ) )
+} );
+
+my $error;
+if ( $svcnum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $svcnum = $new->svcnum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/tax_class.html b/httemplate/edit/process/tax_class.html
new file mode 100644
index 000000000..339c9083e
--- /dev/null
+++ b/httemplate/edit/process/tax_class.html
@@ -0,0 +1,49 @@
+% if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "tax_class.html?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/tax_rate.cgi?taxclassnum=". uri_escape($tax_class->taxclassnum) ) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $tax_class = new FS::tax_class {
+ 'taxclass' => $cgi->param('taxclass'),
+ 'description' => $cgi->param('description'),
+};
+
+#maybe this whole thing should be in a transaction. at some point, no biggie
+#none of the follow-up stuff will fail unless there's a more serious problem
+#than a hanging record in tax_class...
+
+my $error = $tax_class->insert;
+
+# all of this is highly dubious at the moment
+
+#unless ( $error ) {
+# #auto-add the new taxclass to any regions that have taxclasses already
+#
+# my $sth = dbh->prepare("
+# SELECT geocode FROM tax_rate
+# WHERE taxclass IS NOT NULL AND taxclass != ''
+# GROUP BY geocode
+# ") or die dbh->errstr;
+# $sth->execute or die $sth->errstr;
+#
+# while ( my $row = $sth->fetchrow_hashref ) {
+# warn "inserting for $row";
+# my $cust_main_county = new FS::tax_rate {
+# 'geocode' => $row->{geocode},
+# 'tax' => 0,
+# 'taxclassnum' => $tax_class->taxclassnum,
+# };
+# $error = $cust_main_county->insert;
+# #last if $error;
+# die $error if $error;
+# }
+#
+#}
+
+</%init>
diff --git a/httemplate/edit/process/tax_rate.html b/httemplate/edit/process/tax_rate.html
new file mode 100644
index 000000000..431e54264
--- /dev/null
+++ b/httemplate/edit/process/tax_rate.html
@@ -0,0 +1,22 @@
+<% include( 'elements/process.html',
+ 'table' => 'tax_rate',
+ 'value_callback' => $value_callback,
+ 'popup_reload' => 'Tax changed', #a popup "parent reload" for now
+ #someday change the individual element and go away instead
+ )
+%>
+<%once>
+
+my $value_callback = sub { my ($field, $value) = @_;
+ ($field =~ /^(tax|excessrate|usetax|useexcessrate)$/)
+ ? $value/100
+ : $value
+ };
+</%once>
+<%init>
+
+my $conf = new FS::Conf;
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/usage_class.html b/httemplate/edit/process/usage_class.html
new file mode 100644
index 000000000..cf50cb762
--- /dev/null
+++ b/httemplate/edit/process/usage_class.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'usage_class',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/quick-charge.html b/httemplate/edit/quick-charge.html
new file mode 100644
index 000000000..c18b2bc64
--- /dev/null
+++ b/httemplate/edit/quick-charge.html
@@ -0,0 +1,197 @@
+<% include("/elements/header-popup.html", 'One-time charge', '',
+ ( $cgi->param('error') ? '' : 'onload="addRow()"' ),
+ )
+%>
+
+<% include('/elements/error.html') %>
+
+<SCRIPT TYPE="text/javascript">
+
+function enable_quick_charge () {
+ if ( document.QuickChargeForm.amount.value
+ && document.QuickChargeForm.pkg.value ) {
+ document.QuickChargeForm.submit.disabled = false;
+ } else {
+ document.QuickChargeForm.submit.disabled = true;
+ }
+}
+
+function validate_quick_charge () {
+ var pkg = document.QuickChargeForm.pkg.value;
+ var pkg_regex = /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/ ;
+ var amount = document.QuickChargeForm.amount.value;
+ var amount_regex = /^\s*\$?\s*(\d+(\.\d{1,2})?)\s*$/ ;
+ var rval = true;
+
+ if ( ! amount_regex.test(amount) ) {
+ alert('Illegal amount - enter an amount to charge, for example, "5" or "43" or "21.46".');
+ return false;
+ }
+ if ( String(pkg).length < 1 ) {
+ rval = false;
+ }
+ if ( ! pkg_regex.test(pkg) ) {
+ rval = false;
+ }
+ var i=0;
+ for (i=0; i < rownum; i++) {
+ if (! eval('pkg_regex.test(document.QuickChargeForm.description' + i + '.value)')){
+ rval = false;
+ break;
+ }
+ }
+ if (rval == true) {
+ return true;
+ }
+
+ if ( ! pkg ) {
+ alert('Enter a description for the one-time charge');
+ return false;
+ }
+
+ alert('Illegal description - spaces, letters, numbers, and the following punctuation characters are allowed: . , ! ? @ # $ % & ( ) - + ; : ' + "'" + ' " = [ ]' );
+ return false;
+}
+
+</SCRIPT>
+
+<FORM ACTION="process/quick-charge.cgi" NAME="QuickChargeForm" ID="QuickChargeForm" METHOD="POST" onsubmit="document.QuickChargeForm.submit.disabled=true;return validate_quick_charge();">
+
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+
+<TABLE ID="QuickChargeTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 STYLE="background-color: #cccccc">
+
+<TR>
+ <TD ALIGN="right">Amount </TD>
+ <TD>
+ $<INPUT TYPE="text" NAME="amount" SIZE=6 VALUE="<% $amount %>" onChange="enable_quick_charge()" onKeyPress="enable_quick_charge()">
+ </TD>
+</TR>
+
+% if ( $conf->exists('invoice-unitprice') ) {
+ <TR>
+ <TD ALIGN="right">Quantity </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="quantity" SIZE=4 VALUE="<% $quantity %>">
+ </TD>
+ </TR>
+% }
+
+<% include('/elements/tr-select-pkg_class.html', 'curr_value' => $cgi->param('classnum') ) %>
+
+
+<TR>
+ <TD ALIGN="right">Tax exempt </TD>
+ <TD><INPUT TYPE="checkbox" NAME="setuptax" VALUE="Y" <% $cgi->param('setuptax') ? 'CHECKED' : '' %>></TD>
+</TR>
+
+<% include('/elements/tr-select-taxclass.html', 'curr_value' => $cgi->param('taxclass') ) %>
+
+<% include('/elements/tr-select-taxproduct.html', 'label' => 'Tax product', 'onclick' => 'parent.taxproductmagic(this);', 'curr_value' => $cgi->param('taxproductnum') ) %>
+
+<% include('/elements/tr-select-taxoverride.html', 'onclick' => 'parent.taxoverridemagic(this);', 'curr_value' => $cgi->param('tax_override') ) %>
+
+<TR>
+ <TD ALIGN="right">Description </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="pkg" SIZE="50" MAXLENGTH="50" VALUE="<% $pkg %>" onChange="enable_quick_charge()" onKeyPress="enable_quick_charge()">
+ </TD>
+</TR>
+
+<TR>
+ <TD></TD>
+ <TD><FONT SIZE="-1">Optional additional description (also printed on invoice): </FONT></TD>
+</TR>
+
+% my $row = 0;
+% if ( $cgi->param('error') || $cgi->param('magic') ) {
+% my $param = $cgi->Vars;
+%
+% for ( $row = 0; exists($param->{"description$row"}); $row++ ) {
+
+ <TR>
+ <TD></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="description<% $row %>" SIZE="60" MAXLENGTH="65" VALUE="<% $param->{"description$row"} |h %>" rownum="<% $row %>" onkeyup = "possiblyAddRow;" >
+ </TD>
+ </TR>
+% }
+% }
+
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" ID="submit" NAME="submit" VALUE="Add one-time charge" <% $cgi->param('error') ? '' :' DISABLED' %>>
+
+</FORM>
+
+
+<SCRIPT TYPE="text/javascript">
+
+ var rownum = <% $row %>;
+
+ function possiblyAddRow() {
+ if ( ( rownum - this.getAttribute('rownum') ) == 1 ) {
+ addRow();
+ }
+ }
+
+ function addRow() {
+
+ var table = document.getElementById('QuickChargeTable');
+ var tablebody = table.getElementsByTagName('tbody').item(0);
+
+ var row = document.createElement('TR');
+
+ var empty_cell = document.createElement('TD');
+ row.appendChild(empty_cell);
+
+ var description_cell = document.createElement('TD');
+
+ var description_input = document.createElement('INPUT');
+ description_input.setAttribute('name', 'description'+rownum);
+ description_input.setAttribute('id', 'description'+rownum);
+ description_input.setAttribute('size', 60);
+ description_input.setAttribute('maxLength', 65);
+ description_input.setAttribute('rownum', rownum);
+ description_input.onkeyup = possiblyAddRow;
+ description_cell.appendChild(description_input);
+
+ row.appendChild(description_cell);
+
+ tablebody.appendChild(row);
+
+ rownum++;
+
+ }
+
+</SCRIPT>
+
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('One-time charge');
+
+my $conf = new FS::Conf;
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
+my $custnum = $1;
+
+my $amount = '';
+if ( $cgi->param('amount') =~ /^\s*\$?\s*(\d+(\.\d{1,2})?)\s*$/ ) {
+ $amount = $1;
+}
+
+my $quantity = 1;
+if ( $cgi->param('quantity') =~ /^\s*(\d+)\s*$/ ) {
+ $quantity = $1;
+}
+
+$cgi->param('pkg') =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/
+ or die 'illegal description';
+my $pkg = $1;
+
+</%init>
diff --git a/httemplate/edit/rate.cgi b/httemplate/edit/rate.cgi
new file mode 100644
index 000000000..4c0abfe01
--- /dev/null
+++ b/httemplate/edit/rate.cgi
@@ -0,0 +1,43 @@
+<% include("/elements/header.html","$action Rate plan", menubar(
+ 'View all rate plans' => "${p}browse/rate.cgi",
+ ))
+%>
+
+<% include('/elements/progress-init.html',
+ 'OneTrueForm',
+ [ 'rate', 'min_', 'sec_' ],
+ 'process/rate.cgi',
+ $p.'browse/rate.cgi',
+ )
+%>
+<FORM NAME="OneTrueForm">
+<INPUT TYPE="hidden" NAME="ratenum" VALUE="<% $rate->ratenum %>">
+
+Rate plan
+<INPUT TYPE="text" NAME="ratename" SIZE=32 VALUE="<% $rate->ratename %>">
+<BR><BR>
+
+<INPUT NAME="submit" TYPE="button" VALUE="<%
+ $rate->ratenum ? "Apply changes" : "Add rate plan"
+%>" onClick="document.OneTrueForm.submit.disabled=true; process();">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $rate;
+if ( $cgi->keywords ) {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $rate = qsearchs( 'rate', { 'ratenum' => $1 } );
+} else { #adding
+ $rate = new FS::rate {};
+}
+my $action = $rate->ratenum ? 'Edit' : 'Add';
+
+</%init>
diff --git a/httemplate/edit/rate_detail.html b/httemplate/edit/rate_detail.html
new file mode 100644
index 000000000..dd8c3f6b3
--- /dev/null
+++ b/httemplate/edit/rate_detail.html
@@ -0,0 +1,63 @@
+<% include('elements/edit.html',
+ 'popup' => 1,
+ 'name' => $name,
+ 'table' => 'rate_detail',
+ 'labels' => { 'ratedetailnum' => 'Rate', #should hide...
+ 'dest_regionname' => 'Region',
+ 'dest_prefixes_short' => 'Prefix(es)',
+ 'min_included' => 'Included minutes/calls',
+ 'min_charge' => 'Charge per minute/call',
+ 'sec_granularity' => 'Granularity',
+ 'classnum' => 'Usage class',
+ },
+ 'fields' => [
+ { field=>'ratenum', type=>'hidden', },
+ { field=>'orig_regionnum', type=>'hidden', },
+ { field=>'dest_regionnum', type=>'hidden', },
+ { field=>'dest_regionname', type=>'fixed', },
+ { field=>'dest_prefixes_short', type=>'fixed', },
+ { field=>'min_included', type=>'text', size=>5 },
+ { field=>'min_charge', type=>'money', size=>4 },
+ { field =>'sec_granularity',
+ type =>'select',
+ options => [ keys %granularity ],
+ labels => \%granularity,
+ disable_empty => 1,
+ },
+ { field =>'classnum',
+ type =>'select-table',
+ table =>'usage_class',
+ name_col =>'classname',
+ empty_label =>'(default)',
+ hashref =>{ disabled => '' },
+ },
+
+ ],
+ )
+%>
+<%once>
+
+tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
+
+</%once>
+
+<%init>
+
+my $conf = new FS::Conf;
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#slightly inefficient, i suppose an edit+error callback would be better
+my $name = 'rate';
+my ($keywords) = $cgi->keywords;
+if ( $keywords =~ /^(\d+)$/
+ || $cgi->param('ratedetailnum') =~ /^(\d+)$/ ) {
+ my $rate_detail = qsearchs('rate_detail', { 'ratedetailnum' => $1 } )
+ or die "unknown ratedetailnum $1";
+ $name =
+ $rate_detail->rate->ratename. ' rate for '. $rate_detail->dest_regionname;
+}
+
+#sec_granularity should default to 60! for new rates when this gets used for em
+
+</%init>
diff --git a/httemplate/edit/rate_region.cgi b/httemplate/edit/rate_region.cgi
new file mode 100644
index 000000000..9ca3a3569
--- /dev/null
+++ b/httemplate/edit/rate_region.cgi
@@ -0,0 +1,163 @@
+<% include("/elements/header.html","$action Region", menubar(
+ 'View all regions' => "${p}browse/rate_region.html",
+ ))
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/rate_region.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="regionnum" VALUE="<% $rate_region->regionnum %>">
+
+%# region info
+
+<% ntable('#cccccc') %>
+
+ <TR>
+ <TH ALIGN="right">Region name</TH>
+ <TD><INPUT TYPE="text" NAME="regionname" SIZE=32 VALUE="<% $rate_region->regionname %>"></TR>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Country code</TH>
+ <TD><INPUT TYPE="text" NAME="countrycode" SIZE=4 MAXLENGTH=3 VALUE="<% $countrycode %>"></TR>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">
+ <B>Prefixes</B>
+ <BR><FONT SIZE="-1">(comma-separated)</FONT>
+ </TD>
+ <TD>
+ <TEXTAREA NAME="npa" WRAP=SOFT><% join(', ', map { $_->npa. (length($_->nxx) ? '-'.$_->nxx : '') } @rate_prefix ) %></TEXTAREA>
+ </TD>
+ </TR>
+
+</TABLE>
+
+%# rate plan info
+
+<BR>
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ Rate plan
+ </TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE=-1>Included<BR>minutes/calls</FONT>
+ </TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE=-1>Charge per<BR>minute/call</FONT>
+ </TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE=-1>Granularity</FONT>
+ </TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE=-1>Usage class</FONT>
+ </TH>
+ </TR>
+
+% foreach my $rate ( qsearch('rate', {}) ) {
+%
+% my $n = $rate->ratenum;
+% my $rate_detail = $rate->dest_detail($rate_region)
+% || new FS::rate_region { 'min_included' => 0,
+% 'min_charge' => 0,
+% 'sec_granularity' => '60'
+% };
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="<%$p%>edit/rate.cgi?<% $rate->ratenum %>"><% $rate->ratename %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <INPUT TYPE="text" SIZE=9 NAME="min_included<%$n%>" VALUE="<% $cgi->param("min_included$n") || $rate_detail->min_included |h %>">
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ $<INPUT TYPE="text" SIZE=6 NAME="min_charge<%$n%>" VALUE="<% $cgi->param("min_charge$n") || $rate_detail->min_charge |h %>">
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <SELECT NAME="sec_granularity<%$n%>">
+% foreach my $granularity ( keys %granularity ) {
+ <OPTION VALUE="<%$granularity%>"<% $granularity == ( $cgi->param("sec_granularity$n") || $rate_detail->sec_granularity ) ? ' SELECTED' : '' %>><%$granularity{$granularity}%>
+% }
+ </SELECT>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% include( '/elements/select-table.html',
+ 'element_name' => "classnum$n",
+ 'table' => 'usage_class',
+ 'name_col' => 'classname',
+ 'empty_label' => '(default)',
+ 'hashref' => { disabled => '' },
+ 'curr_value' => ( $cgi->param("classnum$n") ||
+ $rate_detail->classnum ),
+ )
+ %>
+ </TD>
+
+ </TR>
+
+% }
+
+</TABLE>
+
+
+<BR><BR>
+<INPUT TYPE="submit" VALUE="<% $rate_region->regionnum ? "Apply changes" : "Add region" %>">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $rate_region;
+if ( $cgi->param('error') ) {
+ $rate_region = new FS::rate_region ( {
+ map { $_, scalar($cgi->param($_)) } fields('rate_region')
+ } );
+} elsif ( $cgi->keywords ) {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "unparsable regionnum";
+ $rate_region = qsearchs( 'rate_region', { 'regionnum' => $1 } )
+ or die "unknown regionnum $1\n";
+} else { #adding
+ $rate_region = new FS::rate_region {};
+}
+my $action = $rate_region->regionnum ? 'Edit' : 'Add';
+
+my $p1 = popurl(1);
+
+tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
+
+my @rate_prefix = $rate_region->rate_prefix;
+my $countrycode = '';
+if ( @rate_prefix ) {
+ $countrycode = $rate_prefix[0]->countrycode;
+ foreach my $rate_prefix ( @rate_prefix ) {
+ errorpage('multiple country codes per region not yet supported by web UI')
+ unless $rate_prefix->countrycode eq $countrycode;
+ }
+}
+
+</%init>
diff --git a/httemplate/edit/reason.html b/httemplate/edit/reason.html
new file mode 100644
index 000000000..620a2ea15
--- /dev/null
+++ b/httemplate/edit/reason.html
@@ -0,0 +1,50 @@
+%
+% $cgi->param('class') =~ /^(\w)$/ or die "illegal class";
+% my $class=$1;
+%
+% my $classname = $FS::reason_type::class_name{$class};
+%
+% my (@types) = qsearch( 'reason_type', { 'class' => $class } );
+%
+% unless (scalar(@types)) {
+% print $cgi->redirect( "reason_type.html?class=$class" );
+% }
+<% include( 'elements/edit.html',
+ 'name' => ucfirst($classname) . ' Reason',
+ 'table' => 'reason',
+ 'labels' => {
+ 'reasonnum' => ucfirst($classname) . ' Reason',
+ 'reason_type' => ucfirst($classname) . ' Reason type',
+ 'reason' => ucfirst($classname) . ' Reason',
+ 'disabled' => 'Disabled',
+ 'class' => '',
+ },
+ 'fields' => [
+ { 'field' => 'reason_type',
+ 'type' => 'select',
+ #XXX use something more sane than a hashref
+ #then fix tr-select.html
+ 'value' => { 'vcolumn' => 'typenum',
+ 'ccolumn' => 'type',
+ 'values' => \@types,
+ },
+ },
+ 'reason',
+ { 'field' => 'class',
+ 'type' => 'hidden',
+ 'value' => $class,
+ },
+ { 'field' => 'disabled',
+ 'type' => 'checkbox',
+ 'value' => 'Y'
+ },
+ ],
+ 'viewall_url' => $p . "browse/reason.html?class=$class",
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/reason_type.html b/httemplate/edit/reason_type.html
new file mode 100644
index 000000000..ea5650ec3
--- /dev/null
+++ b/httemplate/edit/reason_type.html
@@ -0,0 +1,29 @@
+<% include( 'elements/edit.html',
+ 'name' => $classname . ' Reason Type',
+ 'table' => 'reason_type',
+ 'labels' => {
+ 'typenum' => $classname . ' reason type',
+ 'type' => $classname . ' reason type name',
+ 'class' => '',
+ },
+ 'fields' => [
+ 'type',
+ { 'field' => 'class',
+ 'type' => 'hidden',
+ },
+ ],
+ 'viewall_url' => $p . "browse/reason_type.html?class=$class",
+ 'new_hashref_callback' => sub {{ 'class' => $class }},
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('class') =~ /^(\w)$/;
+my $class = $1;
+
+my $classname = $FS::reason_type::class_name{$class};
+
+</%init>
diff --git a/httemplate/edit/reg_code.cgi b/httemplate/edit/reg_code.cgi
new file mode 100644
index 000000000..e57ac09bf
--- /dev/null
+++ b/httemplate/edit/reg_code.cgi
@@ -0,0 +1,44 @@
+<% include('/elements/header.html', 'Generate registration codes for '. $agent->agent) %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%popurl(1)%>process/reg_code.cgi" METHOD="POST" NAME="OneTrueForm" onSubmit="document.OneTrueForm.submit.disabled=true">
+<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agent->agentnum %>">
+
+Generate
+% my $num = '';
+% if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) {
+% $num = $1;
+% }
+<INPUT TYPE="text" NAME="num" VALUE="<% $num %>" SIZE=5 MAXLENGTH=4>
+registration codes for <B><% $agent->agent %></B> allowing the following packages:
+<BR><BR>
+
+% foreach my $part_pkg ( qsearch('part_pkg', { 'disabled' => '' } ) ) {
+% my $pkgpart = $part_pkg->pkgpart;
+
+ <INPUT TYPE="checkbox" NAME="pkgpart<% $pkgpart %>" <% $cgi->param("pkgpart$pkgpart") ? 'CHECKED' : '' %>>
+ <% $part_pkg->pkg %> - <% $part_pkg->comment %>
+ <BR>
+
+% }
+
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Generate">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agentnum = $cgi->param('agentnum');
+$agentnum =~ /^(\d+)$/ or errorpage("illegal agentnum $agentnum");
+$agentnum = $1;
+my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+
+</%init>
diff --git a/httemplate/edit/router.cgi b/httemplate/edit/router.cgi
new file mode 100755
index 000000000..19e63b3e8
--- /dev/null
+++ b/httemplate/edit/router.cgi
@@ -0,0 +1,44 @@
+<% include('elements/edit.html',
+ 'post_url' => popurl(1).'process/router.cgi',
+ 'name' => 'router',
+ 'table' => 'router',
+ 'viewall_url' => "${p}browse/router.cgi",
+ 'labels' => { 'routernum' => 'Router',
+ 'routername' => 'Name',
+ 'svc_part' => 'Service',
+ },
+ 'fields' => [
+ { 'field'=>'routername', 'type'=>'text', 'size'=>32 },
+ { 'field'=>'agentnum', 'type'=>'select-agent' },
+ ],
+ 'error_callback' => $callback,
+ 'edit_callback' => $callback,
+ 'new_callback' => $callback,
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Broadband global configuration');
+
+my $callback = sub {
+ my ($cgi, $object, $fields) = (shift, shift, shift);
+ unless ($object->svcnum) {
+ push @{$fields},
+ { 'type' => 'tablebreak-tr-title',
+ 'value' => 'Select the service types available on this router',
+ },
+ { 'field' => 'svc_part',
+ 'type' => 'checkboxes-table',
+ 'target_table' => 'part_svc',
+ 'link_table' => 'part_svc_router',
+ 'name_col' => 'svc',
+ 'hashref' => { 'svcdb' => 'svc_broadband', 'disabled' => '' },
+ };
+ }
+};
+
+</%init>
diff --git a/httemplate/edit/svc_Common.html b/httemplate/edit/svc_Common.html
new file mode 100644
index 000000000..6666d9720
--- /dev/null
+++ b/httemplate/edit/svc_Common.html
@@ -0,0 +1,33 @@
+<% include('elements/svc_Common.html',
+ 'table' => $table,
+ 'post_url' => popurl(1). "process/svc_Common.html",
+ %opt,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+# false laziness w/view/svc_Common.html
+
+$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparsable svcdb";
+my $table = $1;
+require "FS/$table.pm";
+
+my %opt;
+if ( UNIVERSAL::can("FS::$table", 'table_info') ) {
+ $opt{'name'} = "FS::$table"->table_info->{'name'};
+
+ my $fields = "FS::$table"->table_info->{'fields'};
+ my %labels = map { $_ => ( ref($fields->{$_})
+ ? $fields->{$_}{'label'}
+ : $fields->{$_}
+ );
+ }
+ keys %$fields;
+ $opt{'labels'} = \%labels;
+
+}
+
+</%init>
diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi
new file mode 100755
index 000000000..58283ef54
--- /dev/null
+++ b/httemplate/edit/svc_acct.cgi
@@ -0,0 +1,452 @@
+<% include('/elements/header.html', "$action $svc account") %>
+
+<% include('/elements/error.html') %>
+
+% if ( $cust_main ) {
+
+ <% include( '/elements/small_custview.html', $cust_main, '', 1,
+ popurl(2) . "view/cust_main.cgi") %>
+ <BR>
+% }
+
+
+<FORM NAME="OneTrueForm" ACTION="<% $p1 %>process/svc_acct.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
+
+<% ntable("#cccccc",2) %>
+
+<TR>
+ <TD ALIGN="right">Service</TD>
+ <TD BGCOLOR="#eeeeee"><% $part_svc->svc %></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Username</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="username" VALUE="<% $username %>" SIZE=<% $ulen2 %> MAXLENGTH=<% $ulen %>>
+ </TD>
+</TR>
+
+%if ( $part_svc->part_svc_column('_password')->columnflag ne 'F' ) {
+<TR>
+ <TD ALIGN="right">Password</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
+ (blank to generate)
+ </TD>
+</TR>
+%}else{
+ <INPUT TYPE="hidden" NAME="_password" VALUE="<% $password %>">
+%}
+%
+%my $sec_phrase = $svc_acct->sec_phrase;
+%if ( $conf->exists('security_phrase')
+% && $part_svc->part_svc_column('sec_phrase')->columnflag ne 'F' ) {
+%
+
+
+ <TR>
+ <TD ALIGN="right">Security phrase</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="sec_phrase" VALUE="<% $sec_phrase %>" SIZE=32>
+ (for forgotten passwords)
+ </TD>
+ </TD>
+% } else {
+
+
+ <INPUT TYPE="hidden" NAME="sec_phrase" VALUE="<% $sec_phrase %>">
+% }
+%
+%#domain
+%my $domsvc = $svc_acct->domsvc || 0;
+%if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'F' ) {
+%
+
+
+ <INPUT TYPE="hidden" NAME="domsvc" VALUE="<% $domsvc %>">
+% } else {
+%
+% my %svc_domain = ();
+%
+% if ( $domsvc ) {
+% my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $domsvc, } );
+% if ( $svc_domain ) {
+% $svc_domain{$svc_domain->svcnum} = $svc_domain;
+% } else {
+% warn "unknown svc_domain.svcnum for svc_acct.domsvc: $domsvc";
+% }
+% }
+%
+% %svc_domain = (%svc_domain,
+% domain_select_hash FS::svc_acct('svcpart' => $svcpart,
+% 'pkgnum' => $pkgnum,
+% )
+% );
+%
+
+
+ <TR>
+ <TD ALIGN="right">Domain</TD>
+ <TD>
+ <SELECT NAME="domsvc" SIZE=1>
+% foreach my $svcnum (
+% sort { $svc_domain{$a} cmp $svc_domain{$b} }
+% keys %svc_domain
+% ) {
+% my $svc_domain = $svc_domain{$svcnum};
+%
+
+
+ <OPTION VALUE="<% $svcnum %>" <% $svcnum == $domsvc ? ' SELECTED' : '' %>><% $svc_domain{$svcnum} %>
+% }
+
+ </SELECT>
+ </TD>
+ </TR>
+% }
+%
+%#pop
+%my $popnum = $svc_acct->popnum || 0;
+%if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) {
+%
+
+
+ <INPUT TYPE="hidden" NAME="popnum" VALUE="<% $popnum %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">Access number</TD>
+ <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
+ </TR>
+% }
+% #uid/gid
+% foreach my $xid (qw( uid gid )) {
+%
+% if ( $part_svc->part_svc_column($xid)->columnflag =~ /^[FA]$/
+% || ! $conf->exists("svc_acct-edit_$xid")
+% ) {
+%
+% if ( length($svc_acct->$xid()) ) {
+
+
+ <TR>
+ <TD ALIGN="right"><% uc($xid) %></TD>
+ <TD BGCOLOR="#eeeeee"><% $svc_acct->$xid() %></TD>
+ <TD>
+ </TD>
+ </TR>
+% }
+
+
+ <INPUT TYPE="hidden" NAME="<% $xid %>" VALUE="<% $svc_acct->$xid() %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right"><% uc($xid) %></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="<% $xid %>" SIZE=8 MAXLENGTH=6 VALUE="<% $svc_acct->$xid() %>">
+ </TD>
+ </TR>
+% }
+% }
+%
+%#finger
+%if ( $part_svc->part_svc_column('uid')->columnflag eq 'F'
+% && ! $svc_acct->finger ) {
+%
+
+
+ <INPUT TYPE="hidden" NAME="finger" VALUE="">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">GECOS</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="finger" VALUE="<% $svc_acct->finger %>">
+ </TD>
+ </TR>
+% }
+%
+%#dir
+%if ( $part_svc->part_svc_column('dir')->columnflag eq 'F'
+% || !$curuser->access_right('Edit home dir')
+% ) {
+
+
+<INPUT TYPE="hidden" NAME="dir" VALUE="<% $svc_acct->dir %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">Home directory</TD>
+ <TD><INPUT TYPE="text" NAME="dir" VALUE="<% $svc_acct->dir %>"></TD>
+ </TR>
+% }
+%
+%#shell
+%my $shell = $svc_acct->shell;
+%if ( $part_svc->part_svc_column('shell')->columnflag eq 'F'
+% || ( !$shell && $part_svc->part_svc_column('uid')->columnflag eq 'F' )
+% ) {
+%
+
+
+ <INPUT TYPE="hidden" NAME="shell" VALUE="<% $shell %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">Shell</TD>
+ <TD>
+ <SELECT NAME="shell" SIZE=1>
+%
+% my($etc_shell);
+% foreach $etc_shell (@shells) {
+%
+
+
+ <OPTION<% $etc_shell eq $shell ? ' SELECTED' : '' %>><% $etc_shell %>
+% }
+
+
+ </SELECT>
+ </TD>
+ </TR>
+% }
+% if ( $part_svc->part_svc_column('quota')->columnflag eq 'F' ) {
+
+
+ <INPUT TYPE="hidden" NAME="quota" VALUE="<% $svc_acct->quota %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">Quota:</TD>
+ <TD><INPUT TYPE="text" NAME="quota" VALUE="<% $svc_acct->quota %>"></TD>
+ </TR>
+% }
+% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) {
+
+
+ <INPUT TYPE="hidden" NAME="slipip" VALUE="<% $svc_acct->slipip %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right">IP</TD>
+ <TD><INPUT TYPE="text" NAME="slipip" VALUE="<% $svc_acct->slipip %>"></TD>
+ </TR>
+% }
+%
+% my %label = ( seconds => 'Time',
+% upbytes => 'Upload bytes',
+% downbytes => 'Download bytes',
+% totalbytes => 'Total bytes',
+% );
+% foreach my $uf (keys %label) {
+% my $tf = $uf . "_threshold";
+% if ( $curuser->access_right('Edit usage') ) {
+ <TR>
+ <TD ALIGN="right"><% $label{$uf} %> remaining</TD>
+ <TD><INPUT TYPE="text" NAME="<% $uf %>" VALUE="<% $svc_acct->$uf %>">(blank disables)</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><% $label{$uf} %> threshold</TD>
+ <TD><INPUT TYPE="text" NAME="<% $tf %>" VALUE="<% $svc_acct->$tf %>">(blank disables)</TD>
+ </TR>
+% }else{
+ <INPUT TYPE="hidden" NAME="<% $uf %>" VALUE="<% $svc_acct->$uf %>">
+ <INPUT TYPE="hidden" NAME="<% $tf %>" VALUE="<% $svc_acct->$tf %>">
+% }
+% }
+%
+%foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) {
+% $r =~ /^^r(adius|[cr])_(.+)$/ or next; #?
+% my $a = $2;
+%
+% if ( $part_svc->part_svc_column($r)->columnflag =~ /^[FA]$/ ) {
+
+
+ <INPUT TYPE="hidden" NAME="<% $r %>" VALUE="<% $svc_acct->getfield($r) %>">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right"><% $FS::raddb::attrib{$a} %></TD>
+ <TD><INPUT TYPE="text" NAME="<% $r %>" VALUE="<% $svc_acct->getfield($r) %>"></TD>
+ </TR>
+% }
+% }
+
+
+
+<TR>
+ <TD ALIGN="right">RADIUS groups</TD>
+% if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) {
+
+
+ <TD BGCOLOR="#eeeeee"><% join('<BR>', @groups) %></TD>
+% } else {
+
+
+ <TD><% FS::svc_acct::radius_usergroup_selector( \@groups ) %></TD>
+% }
+
+
+</TR>
+% foreach my $field ($svc_acct->virtual_fields) {
+% # If the flag is X, it won't even show up in $svc_acct->virtual_fields.
+% if ( $part_svc->part_svc_column($field)->columnflag ne 'F' ) {
+
+
+ <% $svc_acct->pvf($field)->widget('HTML', 'edit', $svc_acct->getfield($field)) %>
+% }
+% }
+
+
+</TABLE>
+<BR>
+
+<INPUT TYPE="submit" VALUE="Submit">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my $conf = new FS::Conf;
+my @shells = $conf->config('shells');
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct, @groups);
+if ( $cgi->param('error') ) {
+
+ $svc_acct = new FS::svc_acct ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_acct')
+ } );
+ $svcnum = $svc_acct->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+ die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
+ @groups = $cgi->param('radius_usergroup');
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_acct = new FS::svc_acct({svcpart => $svcpart});
+
+ $svcnum='';
+
+} else { #editing
+
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum=$1;
+ $svc_acct=qsearchs('svc_acct',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_acct) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum=$cust_svc->pkgnum;
+ $svcpart=$cust_svc->svcpart;
+
+ $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+ die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
+
+ @groups = $svc_acct->radius_groups;
+
+}
+
+my( $cust_pkg, $cust_main ) = ( '', '' );
+if ( $pkgnum ) {
+ $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } );
+ $cust_main = $cust_pkg->cust_main;
+}
+
+unless ( $svcnum || $cgi->param('error') ) { #adding
+
+ #set gecos
+ if ($cust_main) {
+ unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) {
+ $svc_acct->setfield('finger',
+ $cust_main->getfield('first') . " " . $cust_main->getfield('last')
+ );
+ }
+ }
+
+ $svc_acct->set_default_and_fixed( {
+ #false laziness w/svc-acct::_fieldhandlers
+ 'usergroup' => sub {
+ my( $self, $groups ) = @_;
+ if ( ref($groups) eq 'ARRAY' ) {
+ @groups = @$groups;
+ $groups;
+ } elsif ( length($groups) ) {
+ @groups = split(/\s*,\s*/, $groups);
+ [ @groups ];
+ } else {
+ @groups = ();
+ [];
+ }
+ }
+ } );
+
+}
+
+#fixed radius groups always override & display
+if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) {
+ @groups = split(',', $part_svc->part_svc_column('usergroup')->columnvalue);
+}
+
+my $action = $svcnum ? 'Edit' : 'Add';
+
+my $svc = $part_svc->getfield('svc');
+
+my $otaker = getotaker;
+
+my $username = $svc_acct->username;
+my $password;
+if ( $svc_acct->_password ) {
+ if ( $conf->exists('showpasswords') || ! $svcnum ) {
+ $password = $svc_acct->_password;
+ } else {
+ $password = "*HIDDEN*";
+ }
+} else {
+ $password = '';
+}
+
+my $ulen =
+ $conf->exists('usernamemax')
+ ? $conf->config('usernamemax')
+ : dbdef->table('svc_acct')->column('username')->length;
+my $ulen2 = $ulen+2;
+
+my $pmax = $conf->config('passwordmax') || 8;
+my $pmax2 = $pmax+2;
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/svc_acct_pop.cgi b/httemplate/edit/svc_acct_pop.cgi
new file mode 100755
index 000000000..5930a38be
--- /dev/null
+++ b/httemplate/edit/svc_acct_pop.cgi
@@ -0,0 +1,53 @@
+<% include('/elements/header.html', "$action Access Number", menubar(
+ 'View all Access Numbers' => popurl(2). "browse/svc_acct_pop.cgi",
+ ))
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/svc_acct_pop.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="popnum" VALUE="<% $hashref->{popnum} %>">
+Access Number #<% $hashref->{popnum} ? $hashref->{popnum} : "(NEW)" %>
+
+<PRE>
+City <INPUT TYPE="text" NAME="city" SIZE=32 VALUE="<% $hashref->{city} %>">
+State <INPUT TYPE="text" NAME="state" SIZE=16 MAXLENGTH=16 VALUE="<% $hashref->{state} %>">
+Area Code <INPUT TYPE="text" NAME="ac" SIZE=4 MAXLENGTH=3 VALUE="<% $hashref->{ac} %>">
+Exchange <INPUT TYPE="text" NAME="exch" SIZE=4 MAXLENGTH=3 VALUE="<% $hashref->{exch} %>">
+Local <INPUT TYPE="text" NAME="loc" SIZE=5 MAXLENGTH=4 VALUE="<% $hashref->{loc} %>">
+</PRE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="<% $hashref->{popnum} ? "Apply changes" : "Add Access Number" %>">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Dialup configuration')
+ || $curuser->access_right('Dialup global configuration');
+
+my $svc_acct_pop;
+if ( $cgi->param('error') ) {
+ $svc_acct_pop = new FS::svc_acct_pop ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_acct_pop')
+ } );
+} elsif ( $cgi->keywords ) { #editing
+ my($query)=$cgi->keywords;
+ $query =~ /^(\d+)$/;
+ $svc_acct_pop=qsearchs('svc_acct_pop',{'popnum'=>$1});
+} else { #adding
+ $svc_acct_pop = new FS::svc_acct_pop {};
+}
+my $action = $svc_acct_pop->popnum ? 'Edit' : 'Add';
+my $hashref = $svc_acct_pop->hashref;
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi
new file mode 100644
index 000000000..e60c76c90
--- /dev/null
+++ b/httemplate/edit/svc_broadband.cgi
@@ -0,0 +1,105 @@
+<% include('elements/svc_Common.html',
+ 'post_url' => popurl(1). 'process/svc_broadband.cgi',
+ 'name' => 'broadband service',
+ 'table' => 'svc_broadband',
+ 'labels' => { 'svcnum' => 'Service #',
+ 'description' => 'Description',
+ 'ip_addr' => 'IP address',
+ 'speed_down' => 'Download speed',
+ 'speed_up' => 'Upload speed',
+ 'blocknum' => 'Router/Block',
+ 'block_label' => 'Router/Block',
+ 'mac_addr' => 'MAC address',
+ 'latitude' => 'Latitude',
+ 'longitude' => 'Longitude',
+ 'altitude' => 'Altitude',
+ 'vlan_profile' => 'VLAN profile',
+ 'authkey' => 'Authentication key',
+ },
+ 'fields' => \@fields,
+ 'field_callback' => $callback,
+ 'dummy' => $cgi->query_string,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+# If it's stupid but it works, it's still stupid.
+# -Kristian
+
+my $conf = new FS::Conf;
+
+my @fields = (
+ qw( description ip_addr speed_down speed_up blocknum ),
+ { field=>'block_label', type=>'fixed' },
+ qw( mac_addr latitude longitude altitude vlan_profile authkey )
+);
+
+my $fixedblock = '';
+
+my $callback = sub {
+ my ($cgi, $object, $fieldref) = @_;
+
+ my $svcpart = $object->svcnum ? $object->cust_svc->svcpart
+ : $cgi->param('svcpart');
+
+ my $part_svc = qsearchs( 'part_svc', { svcpart => $svcpart } );
+ die "No part_svc entry!" unless $part_svc;
+
+ my $columndef = $part_svc->part_svc_column($fieldref->{'field'});
+ if ($columndef->columnflag eq 'F') {
+ $fieldref->{'type'} = 'fixed';
+ $fieldref->{'value'} = $columndef->columnvalue;
+ $fixedblock = $fieldref->{value}
+ if $fieldref->{field} eq 'blocknum';
+ }
+
+ if ($object->svcnum) {
+
+ $fieldref->{type} = 'hidden'
+ if $fieldref->{field} eq 'blocknum';
+
+ $fieldref->{value} = $object->addr_block->label
+ if $fieldref->{field} eq 'block_label';
+
+ } else {
+
+ if ($fieldref->{field} eq 'block_label') {
+ if ($fixedblock) {
+ $object->blocknum($fixedblock);
+ $fieldref->{value} = $object->addr_block->label;
+ }else{
+ $fieldref->{type} = 'hidden';
+ }
+ }
+
+ if ($fieldref->{field} eq 'blocknum') {
+ if ( $fixedblock or $conf->exists('auto_router') ) {
+ $fieldref->{type} = 'hidden';
+ $fieldref->{value} = $fixedblock;
+ return;
+ }
+
+ my $cust_pkg = qsearchs( 'cust_pkg', {pkgnum => $cgi->param('pkgnum')} );
+ die "No cust_pkg entry!" unless $cust_pkg;
+
+ $object->svcpart($part_svc->svcpart);
+ my @addr_block =
+ grep { ! $_->agentnum
+ || $cust_pkg->cust_main->agentnum == $_->agentnum
+ && $FS::CurrentUser::CurrentUser->agentnum($_->agentnum)
+ }
+ map { $_->addr_block } $object->allowed_routers;
+ my @options = map { $_->blocknum } @addr_block;
+ my %option_labels = map { ( $_->blocknum => $_->label ) } @addr_block;
+ $fieldref->{type} = 'select';
+ $fieldref->{options} = \@options;
+ $fieldref->{labels} = \%option_labels;
+ }
+
+ }
+};
+
+</%init>
diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi
new file mode 100755
index 000000000..56ba604bf
--- /dev/null
+++ b/httemplate/edit/svc_domain.cgi
@@ -0,0 +1,91 @@
+<% include('/elements/header.html', "$action $svc", '') %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/svc_domain.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+<INPUT TYPE="radio" NAME="action" VALUE="N"<% $kludge_action eq 'N' ? ' CHECKED' : '' %>>New
+<BR>
+
+<INPUT TYPE="radio" NAME="action" VALUE="M"<% $kludge_action eq 'M' ? ' CHECKED' : '' %>>Transfer
+
+<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="<% $domain %>" SIZE=28 MAXLENGTH=63>
+
+<BR>Purpose/Description: <INPUT TYPE="text" NAME="purpose" VALUE="<% $purpose %>" SIZE=64>
+
+<P><INPUT TYPE="submit" VALUE="Submit">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my($svcnum, $pkgnum, $svcpart, $kludge_action, $purpose, $part_svc,
+ $svc_domain);
+if ( $cgi->param('error') ) {
+
+ $svc_domain = new FS::svc_domain ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_domain')
+ } );
+ $svcnum = $svc_domain->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $kludge_action = $cgi->param('action');
+ $purpose = $cgi->param('purpose');
+ $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
+ die "No part_svc entry!" unless $part_svc;
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_domain = new FS::svc_domain({});
+
+ $svcnum='';
+
+ $svc_domain->set_default_and_fixed;
+
+} else { #editing
+
+ $kludge_action = '';
+ $purpose = '';
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum=$1;
+ $svc_domain=qsearchs('svc_domain',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_domain) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum=$cust_svc->pkgnum;
+ $svcpart=$cust_svc->svcpart;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+}
+my $action = $svcnum ? 'Edit' : 'Add';
+
+my $svc = $part_svc->getfield('svc');
+
+my $otaker = getotaker;
+
+my $domain = $svc_domain->domain;
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/svc_external.cgi b/httemplate/edit/svc_external.cgi
new file mode 100644
index 000000000..0df842b21
--- /dev/null
+++ b/httemplate/edit/svc_external.cgi
@@ -0,0 +1,102 @@
+<% include('/elements/header.html', "External service $action") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/svc_external.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+Service #<B><% $svcnum ? $svcnum : "(NEW)" %></B>
+<BR><BR>
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+% my $id = $svc_external->id;
+% my $title = $svc_external->title;
+%
+<% &ntable("#cccccc",2) %>
+ <TR>
+ <TD ALIGN="right">External ID</TD>
+ <TD><INPUT TYPE="text" NAME="id" VALUE="<% $id %>"></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Title</TD>
+ <TD><INPUT TYPE="text" NAME="title" VALUE="<% $title %>"></TD>
+ </TR>
+
+% foreach my $field ($svc_external->virtual_fields) {
+% if ( $part_svc->part_svc_column($field)->columnflag ne 'F' ) {
+% # If the flag is X, it won't even show up in $svc_acct->virtual_fields.
+ <% $svc_external->pvf($field)->widget( 'HTML',
+ 'edit',
+ $svc_external->getfield($field)
+ )
+ %>
+% }
+% }
+
+</TABLE>
+<BR>
+
+<INPUT TYPE="submit" VALUE="Submit">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my( $svcnum, $pkgnum, $svcpart, $part_svc, $svc_external );
+if ( $cgi->param('error') ) {
+
+ $svc_external = new FS::svc_external ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_external')
+ } );
+ $svcnum = $svc_external->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_external = new FS::svc_external { svcpart => $svcpart };
+
+ $svcnum='';
+
+ $svc_external->set_default_and_fixed;
+
+} else { #adding
+
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum=$1;
+ $svc_external=qsearchs('svc_external',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_external) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum=$cust_svc->pkgnum;
+ $svcpart=$cust_svc->svcpart;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+}
+my $action = $svc_external->svcnum ? 'Edit' : 'Add';
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/svc_forward.cgi b/httemplate/edit/svc_forward.cgi
new file mode 100755
index 000000000..96a00a5aa
--- /dev/null
+++ b/httemplate/edit/svc_forward.cgi
@@ -0,0 +1,175 @@
+<% include('/elements/header.html', "Mail Forward $action") %>
+
+<% include('/elements/error.html') %>
+
+Service #<% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
+Service: <B><% $part_svc->svc %></B><BR><BR>
+
+<FORM ACTION="process/svc_forward.cgi" METHOD="POST">
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+<SCRIPT TYPE="text/javascript">
+function srcchanged(what) {
+ if ( what.options[what.selectedIndex].value == 0 ) {
+ what.form.src.disabled = false;
+ what.form.src.style.backgroundColor = "white";
+ } else {
+ what.form.src.disabled = true;
+ what.form.src.style.backgroundColor = "lightgrey";
+ }
+}
+function dstchanged(what) {
+ if ( what.options[what.selectedIndex].value == 0 ) {
+ what.form.dst.disabled = false;
+ what.form.dst.style.backgroundColor = "white";
+ } else {
+ what.form.dst.disabled = true;
+ what.form.dst.style.backgroundColor = "lightgrey";
+ }
+}
+</SCRIPT>
+
+<% ntable("#cccccc",2) %>
+<TR><TD ALIGN="right">Email to</TD>
+<TD><SELECT NAME="srcsvc" SIZE=1 onChange="srcchanged(this)">
+% foreach $_ (keys %email) {
+
+ <OPTION<% $_ eq $srcsvc ? " SELECTED" : "" %> VALUE="<% $_ %>"><% $email{$_} %></OPTION>
+% }
+% if ( $svc_forward->dbdef_table->column('src') ) {
+
+ <OPTION <% $src ? 'SELECTED' : '' %> VALUE="0">(other email address)</OPTION>
+% }
+
+</SELECT>
+% if ( $svc_forward->dbdef_table->column('src') ) {
+
+<INPUT TYPE="text" NAME="src" VALUE="<% $src %>" <% ( $src || !scalar(%email) ) ? '' : 'DISABLED STYLE="background-color: lightgrey"' %>>
+% }
+
+</TD></TR>
+
+<TR><TD ALIGN="right">Forwards to</TD>
+<TD><SELECT NAME="dstsvc" SIZE=1 onChange="dstchanged(this)">
+% foreach $_ (keys %email) {
+
+ <OPTION<% $_ eq $dstsvc ? " SELECTED" : "" %> VALUE="<% $_ %>"><% $email{$_} %></OPTION>
+% }
+
+<OPTION <% $dst ? 'SELECTED' : '' %> VALUE="0">(other email address)</OPTION>
+</SELECT>
+<INPUT TYPE="text" NAME="dst" VALUE="<% $dst %>" <% ( $dst || !scalar(%email) ) ? '' : 'DISABLED STYLE="background-color: lightgrey"' %>>
+</TD></TR>
+ </TABLE>
+<BR><INPUT TYPE="submit" VALUE="Submit">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my $conf = new FS::Conf;
+
+my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_forward);
+if ( $cgi->param('error') ) {
+ $svc_forward = new FS::svc_forward ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_forward')
+ } );
+ $svcnum = $svc_forward->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_forward = new FS::svc_forward({});
+
+ $svcnum='';
+
+ $svc_forward->set_default_and_fixed;
+
+} else { #editing
+
+ my($query) = $cgi->keywords;
+
+ $query =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum=$1;
+ $svc_forward=qsearchs('svc_forward',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_forward) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum=$cust_svc->pkgnum;
+ $svcpart=$cust_svc->svcpart;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+}
+my $action = $svc_forward->svcnum ? 'Edit' : 'Add';
+
+my %email;
+
+#starting with those currently attached
+foreach my $method (qw( srcsvc_acct dstsvc_acct )) {
+ my $svc_acct = $svc_forward->$method();
+ $email{$svc_acct->svcnum} = $svc_acct->email if $svc_acct;
+}
+
+if ($pkgnum) {
+
+ #find all possible user svcnums (and emails)
+
+ #and including the rest for this customer
+ my($u_part_svc,@u_acct_svcparts);
+ foreach $u_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_acct'}) ) {
+ push @u_acct_svcparts,$u_part_svc->getfield('svcpart');
+ }
+
+ my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ my($custnum)=$cust_pkg->getfield('custnum');
+ my($i_cust_pkg);
+ foreach $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) {
+ my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum');
+ my($acct_svcpart);
+ foreach $acct_svcpart (@u_acct_svcparts) { #now find the corresponding
+ #record(s) in cust_svc ( for this
+ #pkgnum ! )
+ foreach my $i_cust_svc (
+ qsearch( 'cust_svc', { 'pkgnum' => $cust_pkgnum,
+ 'svcpart' => $acct_svcpart } )
+ ) {
+ my $svc_acct =
+ qsearchs( 'svc_acct', { 'svcnum' => $i_cust_svc->svcnum } );
+ $email{$svc_acct->svcnum} = $svc_acct->email;
+ }
+ }
+ }
+
+} elsif ( $action eq 'Add' ) {
+ die "\$action eq Add, but \$pkgnum is null!\n";
+}
+
+my($srcsvc,$dstsvc,$dst)=(
+ $svc_forward->srcsvc,
+ $svc_forward->dstsvc,
+ $svc_forward->dst,
+);
+my $src = $svc_forward->dbdef_table->column('src') ? $svc_forward->src : '';
+
+</%init>
diff --git a/httemplate/edit/svc_phone.cgi b/httemplate/edit/svc_phone.cgi
new file mode 100644
index 000000000..d7629ab6f
--- /dev/null
+++ b/httemplate/edit/svc_phone.cgi
@@ -0,0 +1,27 @@
+<% include( 'elements/svc_Common.html',
+ 'name' => 'Phone number',
+ 'table' => 'svc_phone',
+ 'fields' => [ 'countrycode',
+ { field => 'phonenum',
+ type => 'select-did',
+ label => 'Phone number',
+ },
+ 'sip_password',
+ 'pin',
+ 'phone_name',
+ ],
+ 'labels' => {
+ 'countrycode' => 'Country code',
+ 'phonenum' => 'Phone number',
+ 'sip_password' => 'SIP password',
+ 'pin' => 'Voicemail PIN',
+ 'phone_name' => 'Name',
+ },
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/svc_www.cgi b/httemplate/edit/svc_www.cgi
new file mode 100644
index 000000000..eeb6f678c
--- /dev/null
+++ b/httemplate/edit/svc_www.cgi
@@ -0,0 +1,240 @@
+<% include('/elements/header.html', "Web Hosting $action") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/svc_www.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+Service #<B><% $svcnum ? $svcnum : "(NEW)" %></B>
+<BR><BR>
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+% my $recnum = $svc_www->recnum;
+% my $usersvc = $svc_www->usersvc;
+
+<% &ntable("#cccccc",2) %>
+
+ <TR>
+ <TD ALIGN="right">Zone</TD>
+ <TD>
+ <SELECT NAME="recnum" SIZE=1>
+% foreach $_ (keys %arec) {
+ <OPTION<% $_ eq $recnum ? " SELECTED" : "" %> VALUE="<%$_%>"><%$arec{$_}%>
+% }
+ </SELECT>
+ </TD>
+ </TR>
+
+% if ( $part_svc->part_svc_column('usersvc')->columnflag ne 'F'
+% || $part_svc->part_svc_column('usersvc')->columnvalue !~ /^\s*$/) {
+ <TR>
+ <TD ALIGN="right">Username</TD>
+ <TD>
+ <SELECT NAME="usersvc" SIZE=1>
+ <OPTION VALUE="">(none)
+% foreach $_ (keys %svc_acct) {
+ <OPTION<% ($_ eq $usersvc) ? " SELECTED" : "" %> VALUE="<%$_%>"><% $svc_acct{$_} %>
+% }
+ <SELECT>
+ </TD>
+ </TR>
+% }
+
+% if ( $part_svc->part_svc_column('config')->columnflag ne 'F' &&
+% $FS::CurrentUser::CurrentUser->access_right('Edit www config') ) {
+ <TR>
+ <TD ALIGN="right">Config lines</TD>
+ <TD>
+ <TEXTAREA NAME="config" rows="15" cols="80"><% $config |h %></TEXTAREA>
+ </TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="config" VALUE="<% $config |h %>">
+%}
+
+% foreach my $field ($svc_www->virtual_fields) {
+% if ( $part_svc->part_svc_column($field)->columnflag ne 'F' ) {
+% # If the flag is X, it won't even show up in $svc_acct->virtual_fields.
+ <% $svc_www->pvf($field)->widget( 'HTML', 'edit',
+ $svc_www->getfield($field)
+ )
+ %>
+% }
+% }
+
+</TABLE>
+<BR>
+
+<INPUT TYPE="submit" VALUE="Submit">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my $conf = new FS::Conf;
+
+my( $svcnum, $pkgnum, $svcpart, $part_svc, $svc_www, $config );
+
+if ( $cgi->param('error') ) {
+
+ $svc_www = new FS::svc_www ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_www')
+ } );
+ $svcnum = $svc_www->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $config = $cgi->param('config');
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+ $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+ $pkgnum = $1;
+ $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+ $svcpart = $1;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ $svc_www = new FS::svc_www { svcpart => $svcpart };
+
+ $svcnum='';
+
+ $svc_www->set_default_and_fixed;
+
+} else { #editing
+
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum=$1;
+ $svc_www=qsearchs('svc_www',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_www) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum = $cust_svc->pkgnum;
+ $svcpart = $cust_svc->svcpart;
+ $config = $svc_www->config;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+}
+my $action = $svc_www->svcnum ? 'Edit' : 'Add';
+
+my( %svc_acct, %arec );
+if ($pkgnum) {
+
+ my @u_acct_svcparts;
+ foreach my $svcpart (
+ map { $_->svcpart } qsearch( 'part_svc', { 'svcdb' => 'svc_acct' } )
+ ) {
+ next if $conf->exists('svc_www-usersvc_svcpart')
+ && ! grep { $svcpart == $_ }
+ $conf->config('svc_www-usersvc_svcpart');
+ push @u_acct_svcparts, $svcpart;
+ }
+
+ my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ my($custnum)=$cust_pkg->getfield('custnum');
+ my($i_cust_pkg);
+ foreach $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) {
+ my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum');
+ my($acct_svcpart);
+ foreach $acct_svcpart (@u_acct_svcparts) { #now find the corresponding
+ #record(s) in cust_svc ( for this
+ #pkgnum ! )
+ my($i_cust_svc);
+ foreach $i_cust_svc ( qsearch('cust_svc',{'pkgnum'=>$cust_pkgnum,'svcpart'=>$acct_svcpart}) ) {
+ my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$i_cust_svc->getfield('svcnum')});
+ $svc_acct{$svc_acct->getfield('svcnum')}=
+ $svc_acct->cust_svc->part_svc->svc. ': '. $svc_acct->email;
+ }
+ }
+ }
+
+
+ my($d_part_svc,@d_acct_svcparts);
+ foreach $d_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_domain'}) ) {
+ push @d_acct_svcparts,$d_part_svc->getfield('svcpart');
+ }
+
+ foreach $i_cust_pkg ( qsearch( 'cust_pkg', { 'custnum' => $custnum } ) ) {
+ my $cust_pkgnum = $i_cust_pkg->pkgnum;
+
+ foreach my $acct_svcpart (@d_acct_svcparts) {
+
+ foreach my $i_cust_svc (
+ qsearch( 'cust_svc', { 'pkgnum' => $cust_pkgnum,
+ 'svcpart' => $acct_svcpart } )
+ ) {
+ my $svc_domain =
+ qsearchs( 'svc_domain', { 'svcnum' => $i_cust_svc->svcnum } );
+
+ my $extra_sql = "AND ( rectype = 'A' OR rectype = 'CNAME' )";
+ unless ( $conf->exists('svc_www-enable_subdomains') ) {
+ $extra_sql .= " AND ( reczone = '\@' OR reczone = '".
+ $svc_domain->domain. ".' )";
+ }
+
+ foreach my $domain_rec (
+ qsearch( 'domain_record',
+ {
+ 'svcnum' => $svc_domain->svcnum,
+ },
+ '',
+ $extra_sql,
+ )
+ ) {
+ $arec{$domain_rec->recnum} = $domain_rec->zone;
+ }
+
+ if ( $conf->exists('svc_www-enable_subdomains') ) {
+ $arec{'www.'. $svc_domain->domain} = 'www.'. $svc_domain->domain
+ unless qsearchs( 'domain_record', {
+ svcnum => $svc_domain->svcnum,
+ reczone => 'www',
+ } )
+ || qsearchs( 'domain_record', {
+ svcnum => $svc_domain->svcnum,
+ reczone => 'www.'.$svc_domain->domain.'.',
+ } );
+ }
+
+ $arec{'@.'. $svc_domain->domain} = $svc_domain->domain
+ unless qsearchs('domain_record', {
+ svcnum => $svc_domain->svcnum,
+ reczone => '@',
+ } )
+ || qsearchs('domain_record', {
+ svcnum => $svc_domain->svcnum,
+ reczone => $svc_domain->domain.'.',
+ } );
+
+ }
+
+ }
+ }
+
+} elsif ( $action eq 'Edit' ) {
+
+ my($domain_rec) = qsearchs('domain_record', { 'recnum'=>$svc_www->recnum });
+ $arec{$svc_www->recnum} = join '.', $domain_rec->recdata, $domain_rec->reczone;
+
+} else {
+ die "\$action eq Add, but \$pkgnum is null!\n";
+}
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/tax_class.html b/httemplate/edit/tax_class.html
new file mode 100644
index 000000000..d3e2e821f
--- /dev/null
+++ b/httemplate/edit/tax_class.html
@@ -0,0 +1,36 @@
+<% include('/elements/header.html', "$action taxclass") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/tax_class.html" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="taxclassnum" VALUE="">
+<INPUT TYPE="hidden" NAME="data_vendor" VALUE="">
+
+Tax class <INPUT TYPE="text" NAME="taxclass" VALUE="<% $taxclass |h %>"><BR>
+Description <INPUT TYPE="text" NAME="description" VALUE="<% $description |h %>">
+
+<BR><BR>
+<INPUT TYPE="submit" VALUE="<% $action %> taxclass">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $taxclass = '';
+my $description = '';
+if ( $cgi->param('error') ) {
+ $taxclass = $cgi->param('taxclass');
+ $description = $cgi->param('description');
+}
+
+my $action = 'Add';
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/tax_rate.html b/httemplate/edit/tax_rate.html
new file mode 100644
index 000000000..bff699946
--- /dev/null
+++ b/httemplate/edit/tax_rate.html
@@ -0,0 +1,106 @@
+<% include('elements/edit.html',
+ 'popup' => 1,
+ 'name' => 'Tax rate', #Edit tax rate
+ 'table' => 'tax_rate',
+ 'labels' => $labels,
+ 'fields' => \@fields,
+ 'value_callback' => $value_callback,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+my $value_callback =
+ sub { my ( $field, $value ) = @_;
+ ( $field =~ /^(tax|excessrate|usetax|useexcessrate)$/ )
+ ? $value*100
+ : $value;
+ };
+
+</%once>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $taxnum;
+if ( $cgi->param('error') ) {
+ $cgi->param('taxnum') =~ /^(\d+)$/ or die 'error, but no taxnum';
+ $taxnum = $1;
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die 'no taxnum';
+ $taxnum = $1;
+}
+
+my $tax_rate = qsearchs('tax_rate', { 'taxnum' => $taxnum })
+ or die "unknown taxnum $1";
+
+my $labels = { 'taxnum' => 'Tax',
+ 'data_vendor' => 'Data vendor',
+ 'geocode' => 'Vendor location code',
+ 'location' => 'Tax auth loc code',
+ 'taxclass_description' => 'Tax class',
+ 'taxname' => 'Tax name',
+ 'effective_date' => 'Effective date',
+ 'tax' => 'Tax rate (1st bracket)',
+ 'excessrate' => 'Tax rate (2nd bracket)',
+ 'taxbase' => 'First bracket',
+ 'taxmax' => 'Max tax',
+ 'usetax' => 'Use tax rate (1st bracket)',
+ 'useexcessrate' => 'Use tax rate (2nd bracket)',
+ 'unittype_name' => 'Units',
+ 'fee' => 'Fee per unit (1st bracket)',
+ 'excessfee' => 'Fee per unit (2st bracket)',
+ 'feebase' => 'Units in first bracket',
+ 'feemax' => 'Max Units',
+ 'maxtype_name' => 'Threshold accumulation',
+ 'taxauth_name', => 'Tax authority',
+ 'basetype_name' => 'Basis',
+ 'passtype_name' => 'Passthru',
+ 'passflag' => 'Passable',
+ 'setuptax' => 'This tax not applicable to setup fees',
+ 'recurtax' => 'This tax not applicable to recurring fees',
+ };
+
+my @fields = (
+ { type=>'tablebreak-tr-title', value=>'Location' },
+ { field=>'data_vendor', type=>'hidden',},
+ { field=>'geocode', type=>'fixed' },
+ { field=>'taxclassnum', type=>'hidden' } ,
+ { field=>'taxclass_description', type=>'fixed' } ,
+ { field=>'taxname', type=>'text' } ,
+ { field=>'effective_date', type=>'fixed' } ,
+ { field=>'location', type=>'text' },
+ { type=>'tablebreak-tr-title', value=>'Money based rates' },
+ { field=>'tax', type=>'percentage' } ,
+ { field=>'excessrate', type=>'percentage' } ,
+ { field=>'taxbase', type=>'money' } ,
+ { field=>'taxmax', type=>'money' } ,
+ { field=>'usetax', type=>'percentage' } ,
+ { field=>'useexcessrate', type=>'percentage' } ,
+ { type=>'tablebreak-tr-title', value=>'Service based rates' },
+ { field=>'unittype', type=>'hidden' } ,
+ { field=>'unittype_name', type=>'fixed' } ,
+ { field=>'fee', type=>'money' } ,
+ { field=>'excessfee', type=>'money' } ,
+ { field=>'feebase', type=>'text' } ,
+ { field=>'feemax', type=>'text' } ,
+ { type=>'tablebreak-tr-title', value=>'Taxation rules' },
+ { field=>'maxtype', type=>'hidden' } ,
+ { field=>'maxtype_name', type=>'fixed' } ,
+ { field=>'taxauth', type=>'hidden' } ,
+ { field=>'taxauth_name', type=>'fixed' } ,
+ { field=>'basetype', type=>'hidden' } ,
+ { field=>'basetype_name', type=>'fixed' } ,
+ { field=>'passtype', type=>'hidden' } ,
+ { field=>'passtype_name', type=>'fixed' } ,
+ { field=>'passflag', type=>'fixed' } ,
+ { field=>'setuptax', type=>'checkbox', value=>'Y' } ,
+ { field=>'recurtax', type=>'checkbox', value=>'Y' } ,
+ { field=>'disabled', type=>'checkbox', value=>'Y' } ,
+ { field=>'manual', type=>'hidden', value=>'Y' } ,
+);
+
+</%init>
diff --git a/httemplate/edit/usage_class.html b/httemplate/edit/usage_class.html
new file mode 100644
index 000000000..ef4b1fff4
--- /dev/null
+++ b/httemplate/edit/usage_class.html
@@ -0,0 +1,25 @@
+<% include( 'elements/edit.html',
+ 'name_singular' => 'Usage Class',
+ 'table' => 'usage_class',
+ 'fields' => [
+ 'classname',
+ { field=>'disabled',
+ type=>'checkbox',
+ value=>'Y',
+ },
+ ],
+ 'labels' => {
+ 'classnum' => 'Class number',
+ 'classname' => 'Class name',
+ 'disabled' => 'Disable class',
+ },
+ 'viewall_dir' => 'browse',
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/elements/ajaxcontentmws.js b/httemplate/elements/ajaxcontentmws.js
new file mode 100644
index 000000000..917704902
--- /dev/null
+++ b/httemplate/elements/ajaxcontentmws.js
@@ -0,0 +1,185 @@
+/*
+ ajaxcontentmws.js - Foteos Macrides (author and Copyright holder)
+ Initial: June 22, 2006 - Last Revised: March 24, 2008
+ Wrapper function set for getting and using the responseText and / or
+ responseXML from a GET or POST XMLHttpRequest, which can be used to
+ generate dynamic content for overlib or overlib2 calls, or to modify
+ the content of a displayed STICKY popup dynamically.
+
+ For GET Use:
+ onmouseover="return OLgetAJAX(url, command, delay, css);"
+ onmouseout="OLclearAJAX();" (if delay > 0)
+ or:
+ onclick="OLgetAJAX(url, command, 0, css); return false;"
+ or:
+ onload="OLgetAJAX(url, command, 0, css);
+
+ Where:
+ url (required)
+ is a quoted string, or unquoted string variable name or array entry, with
+ the full, relative, or partial URL for a file or a server-side script (php,
+ asp, or cgi, e.g. perl), and may have a query string appended (e.g.,
+ 'http://my.domain.com/scripts/myScript.php?foo=bar&life=grand').
+ And:
+ command (required)
+ is the function reference (unquoted name without parens) of a function to
+ be called when the server's response has been received (it could instead be
+ an inline function, i.e., defined within the 2nd argument, or a quoted string
+ for a function with parens and any args)
+ And:
+ delay (may be omitted unless css is included)
+ is an unquoted number indicating the number of millisecs to wait before
+ initiating an XMLHttpRequest GET request. It should be 0 when using onclick
+ or onload, but may be a modest value such as 300 for onmouseover to avoid
+ any chatter of requests. When used with onmouseover, include:
+ onmouseout="OLclearAJAX();"
+ to clear the request if the user does not hover for at least that long. If
+ the popup is not STICKY, include an nd or nd2 call, e.g.,
+ onmouseout="OLclearAJAX(); nd();"
+ And:
+ css (may be omitted)
+ is a quoted string with the CSS class (e.g. 'ovfl510' for
+ .ovfl510 {width:510px; height:145px; overflow:auto; ...} ) for a div to
+ encase the responseText and set the width, height and scrollbars in the
+ main text area of the popup, or the unquoted number 0 if no encasing div
+ is to be used.
+
+ For POST substitute OLpostAJAX(url, qry, command, delay, css);
+ Where
+ qry (required)
+ is the string to be posted, typically a query string (without a lead ?)
+ and the other arguments are as above.
+
+ See http://www.macridesweb.com/oltest/AJAX.html for more information.
+*/
+
+// Initialize our global variables for this function set.
+var OLhttp=false,OLcommandAJAX=null,OLdelayidAJAX=0,OLclassAJAX='',
+OLresponseAJAX='',OLabortAJAX=0,OLdebugAJAX=0;
+
+// Create a series of wrapper functions (e.g. OLcmdT#() for ones which
+// use OLhttp.responseText via the OLresponseAJAX global, and OLcmdX#()
+// for ones which use OLhttp.responseXML) whose reference (unquoted name
+// without parens) is the 2nd argument in OLgetAJAX(url,command,delay,css)
+// calls. This one is for the first example in the AJAX.html support
+// document, to use the OLresponseAJAX global as the lead argument for an
+// overlib popup. Put your functions in the head, or in another imported
+// .js file, so that they will not be affected by updates of this .js file.
+//
+function OLcmdExT1() {
+ return overlib(OLresponseAJAX, TEXTPADDING,0, CAPTIONPADDING,4,
+ CAPTION,'Example with AJAX content via <span '
+ +'class="yellow">responseText</span>.&nbsp; Popup scrolls with the window.',
+ WRAP, BORDER,2, STICKY, CLOSECLICK, SCROLL,
+ MIDX,0, RELY,100,
+ STATUS,'Example with AJAX content via responseText of XMLHttpResponse');
+}
+
+// Alert for old browsers which lack XMLHttpRequest support.
+function OLsorryAJAX() {
+ alert('Sorry, AJAX is not supported by your browser.');
+ return false;
+}
+
+// Check 2nd arg for function
+function OLchkFuncAJAX(ar){
+ var t=typeof ar;return (((t=='function'))||((t=='string')&&(/.+\(.*\)/.test(ar))));
+}
+
+// Alert for bad 2nd argument
+function OLnotFuncAJAX(m) {
+ if(over)cClick();
+ alert('The 2nd arg of OL'+m+'AJAX is not a function reference, nor an inline function, '
+ +'nor a quoted string with a function indicated.');
+ return OLclearAJAX();
+}
+
+// Alert for indicating an XMLHttpRequest network error.
+function OLerrorAJAX() {
+ if(OLhttp.status&&OLhttp.status!=2147746065)alert('Network error '+OLhttp.status+'. Try again later.');
+ return false;
+}
+
+// Returns a new XMLHttpRequest object, or false for older browsers
+// which did not yet support it. Called as OLhttp=OLnewXMLHttp() via
+// the OLgetAJAX(url,command,delay,css) wrapper function.
+//
+function OLnewXMLHttp() {
+ var f=false,req=f;
+ if(window.XMLHttpRequest)eval(new Array('try{',
+ 'req=new XMLHttpRequest();','}catch(e){','req=f;','}').join('\n'));
+ /*@cc_on @if(@_jscript_version>=5)if(!req)
+ eval(new Array('try{','req=new ActiveXObject("Msxml2.XMLHTTP");',
+ '}catch(e){','try{','req=new ActiveXObject("Microsoft.XMLHTTP");',
+ '}catch(e){','req=f;','}}').join('\n')); @end @*/
+ return req;
+}
+
+// Handle the OLhttp.responseText string from the XMLHttpRequest object.
+function OLdoAJAX() {
+ if(OLhttp.readyState==4){
+ if(OLdebugAJAX)alert(
+ 'OLhttp.status = '+OLhttp.status+'\n'
+ +'OLhttp.statusText = '+OLhttp.statusText+'\n'
+ +'OLhttp.getAllResponseHeaders() = \n'
+ +OLhttp.getAllResponseHeaders()+'\n'
+ +'OLhttp.getResponseHeader("Content-Type") = '
+ +OLhttp.getResponseHeader("Content-Type")+'\n');
+ if(OLhttp.status==200||(OLhttp.status==0&&!OLabortAJAX&&!OLie55)){
+ OLresponseAJAX=OLclassAJAX?'<div class="'+OLclassAJAX+'">':'';
+ OLresponseAJAX += OLhttp.responseText;
+ OLresponseAJAX += OLclassAJAX?'</div>':'';
+ if(OLdebugAJAX)alert('OLresponseAJAX = \n'+OLresponseAJAX);
+ OLclassAJAX=0;
+ return (typeof OLcommandAJAX=='string')?eval(OLcommandAJAX):OLcommandAJAX();
+ }else{
+ OLclassAJAX=0;
+ OLabortAJAX=0;
+ return OLerrorAJAX();
+ }
+ }
+}
+
+// Actually make the request initiated via OLgetAJAX or OLpostAJAX, or
+// invoke a "permission denied" alert if a cross-domain URL was used.
+function OLsetAJAX(url,qry) {
+ if(window.location.protocol.indexOf('http')==0&&
+ (url.indexOf('file:')==0||url.indexOf('ftp:')==0)){
+ alert('[object Error]\n(Cross-domain access not permitted)');return false;}
+ qry=(qry||null);var s='',m=(qry)?'POST':'GET';OLabortAJAX=0;
+ OLdelayidAJAX=0;eval(new Array('try{','OLhttp.open(m,url,true);',
+ '}catch(e){','s=e','OLhttp=false;','}').join('\n'));if(!OLhttp){
+ alert(s+'\n(Cross-domain access not permitted)');return false;}if(qry)
+ OLhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
+ OLhttp.onreadystatechange=OLdoAJAX;
+ OLhttp.send(qry);
+}
+
+// Clear or abort any delayed OLsetAJAX call or pending request.
+function OLclearAJAX() {
+ if(OLdelayidAJAX){clearTimeout(OLdelayidAJAX);OLdelayidAJAX=0;}
+ if(OLhttp&&!OLdebugAJAX){OLabortAJAX=1;OLhttp.abort();}
+ return false;
+}
+
+// Load a new XMLHttpRequest object into the OLhttp global, load the
+// OLcommandAJAX and OLclassAJAX globals, and initiate a GET request
+// via OLsetAJAX(url) to populate OLhttp.
+function OLgetAJAX(url,command,delay,css) {
+ if(!OLchkFuncAJAX(command))return OLnotFuncAJAX('get');
+ OLclearAJAX();OLhttp=OLnewXMLHttp();if(!OLhttp)return OLsorryAJAX();
+ OLcommandAJAX=command;delay=(delay||0);css=(css||0);OLclassAJAX=css;
+ if(delay)OLdelayidAJAX=setTimeout("OLsetAJAX('"+url+"')",delay);
+ else OLsetAJAX(url);
+}
+
+// Load a new XMLHttpRequest object into the OLhttp global, load the
+// OLcommandAJAX and OLclassAJAX globals, and initiate a POST request
+// via OLsetAJAX(url,qry) to populate OLhttp.
+function OLpostAJAX(url,qry,command,delay,css) {
+ if(!OLchkFuncAJAX(command))return OLnotFuncAJAX('post');
+ OLclearAJAX();OLhttp=OLnewXMLHttp();if(!OLhttp)return OLsorryAJAX();
+ qry=(qry||0);OLcommandAJAX=command;delay=(delay||0);css=(css||0);OLclassAJAX=css;
+ if(delay)OLdelayidAJAX=setTimeout("OLsetAJAX('"+url+"','"+qry+"')",delay);
+ else OLsetAJAX(url,qry);
+}
diff --git a/httemplate/elements/calendar-en.js b/httemplate/elements/calendar-en.js
new file mode 100644
index 000000000..0dbde793d
--- /dev/null
+++ b/httemplate/elements/calendar-en.js
@@ -0,0 +1,127 @@
+// ** I18N
+
+// Calendar EN language
+// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
+// Encoding: any
+// Distributed under the same terms as the calendar itself.
+
+// For translators: please use UTF-8 if possible. We strongly believe that
+// Unicode is the answer to a real internationalized world. Also please
+// include your contact information in the header, as can be seen above.
+
+// full day names
+Calendar._DN = new Array
+("Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ "Sunday");
+
+// Please note that the following array of short day names (and the same goes
+// for short month names, _SMN) isn't absolutely necessary. We give it here
+// for exemplification on how one can customize the short day names, but if
+// they are simply the first N letters of the full name you can simply say:
+//
+// Calendar._SDN_len = N; // short day name length
+// Calendar._SMN_len = N; // short month name length
+//
+// If N = 3 then this is not needed either since we assume a value of 3 if not
+// present, to be compatible with translation files that were written before
+// this feature.
+
+// short day names
+Calendar._SDN = new Array
+("Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ "Sun");
+
+// First day of the week. "0" means display Sunday first, "1" means display
+// Monday first, etc.
+Calendar._FD = 0;
+
+// full month names
+Calendar._MN = new Array
+("January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December");
+
+// short month names
+Calendar._SMN = new Array
+("Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "About the calendar";
+
+Calendar._TT["ABOUT"] =
+"DHTML Date/Time Selector\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
+"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." +
+"\n\n" +
+"Date selection:\n" +
+"- Use the \xab, \xbb buttons to select year\n" +
+"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
+"- Hold mouse button on any of the above buttons for faster selection.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"Time selection:\n" +
+"- Click on any of the time parts to increase it\n" +
+"- or Shift-click to decrease it\n" +
+"- or click and drag for faster selection.";
+
+Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)";
+Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)";
+Calendar._TT["GO_TODAY"] = "Go Today";
+Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)";
+Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)";
+Calendar._TT["SEL_DATE"] = "Select date";
+Calendar._TT["DRAG_TO_MOVE"] = "Drag to move";
+Calendar._TT["PART_TODAY"] = " (today)";
+
+// the following is to inform that "%s" is to be the first day of week
+// %s will be replaced with the day name.
+Calendar._TT["DAY_FIRST"] = "Display %s first";
+
+// This may be locale-dependent. It specifies the week-end days, as an array
+// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1
+// means Monday, etc.
+Calendar._TT["WEEKEND"] = "0,6";
+
+Calendar._TT["CLOSE"] = "Close";
+Calendar._TT["TODAY"] = "Today";
+Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
+
+Calendar._TT["WK"] = "wk";
+Calendar._TT["TIME"] = "Time:";
diff --git a/httemplate/elements/calendar-setup.js b/httemplate/elements/calendar-setup.js
new file mode 100644
index 000000000..b27d9bed0
--- /dev/null
+++ b/httemplate/elements/calendar-setup.js
@@ -0,0 +1,200 @@
+/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/
+ * ---------------------------------------------------------------------------
+ *
+ * The DHTML Calendar
+ *
+ * Details and latest version at:
+ * http://dynarch.com/mishoo/calendar.epl
+ *
+ * This script is distributed under the GNU Lesser General Public License.
+ * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
+ *
+ * This file defines helper functions for setting up the calendar. They are
+ * intended to help non-programmers get a working calendar on their site
+ * quickly. This script should not be seen as part of the calendar. It just
+ * shows you what one can do with the calendar, while in the same time
+ * providing a quick and simple method for setting it up. If you need
+ * exhaustive customization of the calendar creation process feel free to
+ * modify this code to suit your needs (this is recommended and much better
+ * than modifying calendar.js itself).
+ */
+
+// $Id: calendar-setup.js,v 1.5 2006-02-09 07:18:08 ivan Exp $
+
+/**
+ * This function "patches" an input field (or other element) to use a calendar
+ * widget for date selection.
+ *
+ * The "params" is a single object that can have the following properties:
+ *
+ * prop. name | description
+ * -------------------------------------------------------------------------------------------------
+ * inputField | the ID of an input field to store the date
+ * displayArea | the ID of a DIV or other element to show the date
+ * button | ID of a button or other element that will trigger the calendar
+ * eventName | event that will trigger the calendar, without the "on" prefix (default: "click")
+ * ifFormat | date format that will be stored in the input field
+ * daFormat | the date format that will be used to display the date in displayArea
+ * singleClick | (true/false) wether the calendar is in single click mode or not (default: true)
+ * firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc.
+ * align | alignment (default: "Br"); if you don't know what's this see the calendar documentation
+ * range | array with 2 elements. Default: [1900, 2999] -- the range of years available
+ * weekNumbers | (true/false) if it's true (default) the calendar will display week numbers
+ * flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
+ * flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
+ * disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
+ * onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay)
+ * onClose | function that gets called when the calendar is closed. [default]
+ * onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar.
+ * date | the date that the calendar will be initially displayed to
+ * showsTime | default: false; if true the calendar will include a time selector
+ * timeFormat | the time format; can be "12" or "24", default is "12"
+ * electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close
+ * step | configures the step of the years in drop-down boxes; default: 2
+ * position | configures the calendar absolute position; default: null
+ * cache | if "true" (but default: "false") it will reuse the same calendar object, where possible
+ * showOthers | if "true" (but default: "false") it will show days from other months too
+ *
+ * None of them is required, they all have default values. However, if you
+ * pass none of "inputField", "displayArea" or "button" you'll get a warning
+ * saying "nothing to setup".
+ */
+Calendar.setup = function (params) {
+ function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
+
+ param_default("inputField", null);
+ param_default("displayArea", null);
+ param_default("button", null);
+ param_default("eventName", "click");
+ param_default("ifFormat", "%Y/%m/%d");
+ param_default("daFormat", "%Y/%m/%d");
+ param_default("singleClick", true);
+ param_default("disableFunc", null);
+ param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined
+ param_default("dateText", null);
+ param_default("firstDay", null);
+ param_default("align", "Br");
+ param_default("range", [1900, 2999]);
+ param_default("weekNumbers", true);
+ param_default("flat", null);
+ param_default("flatCallback", null);
+ param_default("onSelect", null);
+ param_default("onClose", null);
+ param_default("onUpdate", null);
+ param_default("date", null);
+ param_default("showsTime", false);
+ param_default("timeFormat", "24");
+ param_default("electric", true);
+ param_default("step", 2);
+ param_default("position", null);
+ param_default("cache", false);
+ param_default("showOthers", false);
+ param_default("multiple", null);
+
+ var tmp = ["inputField", "displayArea", "button"];
+ for (var i in tmp) {
+ if (typeof params[tmp[i]] == "string") {
+ params[tmp[i]] = document.getElementById(params[tmp[i]]);
+ }
+ }
+ if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
+ alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code");
+ return false;
+ }
+
+ function onSelect(cal) {
+ var p = cal.params;
+ var update = (cal.dateClicked || p.electric);
+ if (update && p.inputField) {
+ p.inputField.value = cal.date.print(p.ifFormat);
+ if (typeof p.inputField.onchange == "function")
+ p.inputField.onchange();
+ }
+ if (update && p.displayArea)
+ p.displayArea.innerHTML = cal.date.print(p.daFormat);
+ if (update && typeof p.onUpdate == "function")
+ p.onUpdate(cal);
+ if (update && p.flat) {
+ if (typeof p.flatCallback == "function")
+ p.flatCallback(cal);
+ }
+ if (update && p.singleClick && cal.dateClicked)
+ cal.callCloseHandler();
+ };
+
+ if (params.flat != null) {
+ if (typeof params.flat == "string")
+ params.flat = document.getElementById(params.flat);
+ if (!params.flat) {
+ alert("Calendar.setup:\n Flat specified but can't find parent.");
+ return false;
+ }
+ var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
+ cal.showsOtherMonths = params.showOthers;
+ cal.showsTime = params.showsTime;
+ cal.time24 = (params.timeFormat == "24");
+ cal.params = params;
+ cal.weekNumbers = params.weekNumbers;
+ cal.setRange(params.range[0], params.range[1]);
+ cal.setDateStatusHandler(params.dateStatusFunc);
+ cal.getDateText = params.dateText;
+ if (params.ifFormat) {
+ cal.setDateFormat(params.ifFormat);
+ }
+ if (params.inputField && typeof params.inputField.value == "string") {
+ cal.parseDate(params.inputField.value);
+ }
+ cal.create(params.flat);
+ cal.show();
+ return false;
+ }
+
+ var triggerEl = params.button || params.displayArea || params.inputField;
+ triggerEl["on" + params.eventName] = function() {
+ var dateEl = params.inputField || params.displayArea;
+ var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
+ var mustCreate = false;
+ var cal = window.calendar;
+ if (dateEl)
+ params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
+ if (!(cal && params.cache)) {
+ window.calendar = cal = new Calendar(params.firstDay,
+ params.date,
+ params.onSelect || onSelect,
+ params.onClose || function(cal) { cal.hide(); });
+ cal.showsTime = params.showsTime;
+ cal.time24 = (params.timeFormat == "24");
+ cal.weekNumbers = params.weekNumbers;
+ mustCreate = true;
+ } else {
+ if (params.date)
+ cal.setDate(params.date);
+ cal.hide();
+ }
+ if (params.multiple) {
+ cal.multiple = {};
+ for (var i = params.multiple.length; --i >= 0;) {
+ var d = params.multiple[i];
+ var ds = d.print("%Y%m%d");
+ cal.multiple[ds] = d;
+ }
+ }
+ cal.showsOtherMonths = params.showOthers;
+ cal.yearStep = params.step;
+ cal.setRange(params.range[0], params.range[1]);
+ cal.params = params;
+ cal.setDateStatusHandler(params.dateStatusFunc);
+ cal.getDateText = params.dateText;
+ cal.setDateFormat(dateFmt);
+ if (mustCreate)
+ cal.create();
+ cal.refresh();
+ if (!params.position)
+ cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
+ else
+ cal.showAt(params.position[0], params.position[1]);
+ return false;
+ };
+
+ return cal;
+};
diff --git a/httemplate/elements/calendar-win2k-2.css b/httemplate/elements/calendar-win2k-2.css
new file mode 100644
index 000000000..6f37b7dcd
--- /dev/null
+++ b/httemplate/elements/calendar-win2k-2.css
@@ -0,0 +1,271 @@
+/* The main calendar widget. DIV containing a table. */
+
+.calendar {
+ position: relative;
+ display: none;
+ border-top: 2px solid #fff;
+ border-right: 2px solid #000;
+ border-bottom: 2px solid #000;
+ border-left: 2px solid #fff;
+ font-size: 11px;
+ color: #000;
+ cursor: default;
+ background: #d4c8d0;
+ font-family: tahoma,verdana,sans-serif;
+}
+
+.calendar table {
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+ font-size: 11px;
+ color: #000;
+ cursor: default;
+ background: #d4c8d0;
+ font-family: tahoma,verdana,sans-serif;
+}
+
+/* Header part -- contains navigation buttons and day names. */
+
+.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */
+ text-align: center;
+ padding: 1px;
+ border-top: 1px solid #fff;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+ border-left: 1px solid #fff;
+}
+
+.calendar .nav {
+ background: transparent url(menuarrow.gif) no-repeat 100% 100%;
+}
+
+.calendar thead .title { /* This holds the current "month, year" */
+ font-weight: bold;
+ padding: 1px;
+ border: 1px solid #000;
+ background: #847880;
+ color: #fff;
+ text-align: center;
+}
+
+.calendar thead .headrow { /* Row <TR> containing navigation buttons */
+}
+
+.calendar thead .daynames { /* Row <TR> containing the day names */
+}
+
+.calendar thead .name { /* Cells <TD> containing the day names */
+ border-bottom: 1px solid #000;
+ padding: 2px;
+ text-align: center;
+ background: #f4e8f0;
+}
+
+.calendar thead .weekend { /* How a weekend day name shows in header */
+ color: #f00;
+}
+
+.calendar thead .hilite { /* How do the buttons in header appear when hover */
+ border-top: 2px solid #fff;
+ border-right: 2px solid #000;
+ border-bottom: 2px solid #000;
+ border-left: 2px solid #fff;
+ padding: 0px;
+ background-color: #e4d8e0;
+}
+
+.calendar thead .active { /* Active (pressed) buttons in header */
+ padding: 2px 0px 0px 2px;
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+ background-color: #c4b8c0;
+}
+
+/* The body part -- contains all the days in month. */
+
+.calendar tbody .day { /* Cells <TD> containing month days dates */
+ width: 2em;
+ text-align: right;
+ padding: 2px 4px 2px 2px;
+}
+.calendar tbody .day.othermonth {
+ font-size: 80%;
+ color: #aaa;
+}
+.calendar tbody .day.othermonth.oweekend {
+ color: #faa;
+}
+
+.calendar table .wn {
+ padding: 2px 3px 2px 2px;
+ border-right: 1px solid #000;
+ background: #f4e8f0;
+}
+
+.calendar tbody .rowhilite td {
+ background: #e4d8e0;
+}
+
+.calendar tbody .rowhilite td.wn {
+ background: #d4c8d0;
+}
+
+.calendar tbody td.hilite { /* Hovered cells <TD> */
+ padding: 1px 3px 1px 1px;
+ border-top: 1px solid #fff;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+ border-left: 1px solid #fff;
+}
+
+.calendar tbody td.active { /* Active (pressed) cells <TD> */
+ padding: 2px 2px 0px 2px;
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+}
+
+.calendar tbody td.selected { /* Cell showing selected date */
+ font-weight: bold;
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+ padding: 2px 2px 0px 2px;
+ background: #e4d8e0;
+}
+
+.calendar tbody td.weekend { /* Cells showing weekend days */
+ color: #f00;
+}
+
+.calendar tbody td.today { /* Cell showing today date */
+ font-weight: bold;
+ color: #00f;
+}
+
+.calendar tbody .disabled { color: #999; }
+
+.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */
+ visibility: hidden;
+}
+
+.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */
+ display: none;
+}
+
+/* The footer part -- status bar and "Close" button */
+
+.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */
+}
+
+.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */
+ background: #f4e8f0;
+ padding: 1px;
+ border: 1px solid #000;
+ background: #847880;
+ color: #fff;
+ text-align: center;
+}
+
+.calendar tfoot .hilite { /* Hover style for buttons in footer */
+ border-top: 1px solid #fff;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+ border-left: 1px solid #fff;
+ padding: 1px;
+ background: #e4d8e0;
+}
+
+.calendar tfoot .active { /* Active (pressed) style for buttons in footer */
+ padding: 2px 0px 0px 2px;
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+}
+
+/* Combo boxes (menus that display months/years for direct selection) */
+
+.calendar .combo {
+ position: absolute;
+ display: none;
+ width: 4em;
+ top: 0px;
+ left: 0px;
+ cursor: default;
+ border-top: 1px solid #fff;
+ border-right: 1px solid #000;
+ border-bottom: 1px solid #000;
+ border-left: 1px solid #fff;
+ background: #e4d8e0;
+ font-size: 90%;
+ padding: 1px;
+ z-index: 100;
+}
+
+.calendar .combo .label,
+.calendar .combo .label-IEfix {
+ text-align: center;
+ padding: 1px;
+}
+
+.calendar .combo .label-IEfix {
+ width: 4em;
+}
+
+.calendar .combo .active {
+ background: #d4c8d0;
+ padding: 0px;
+ border-top: 1px solid #000;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ border-left: 1px solid #000;
+}
+
+.calendar .combo .hilite {
+ background: #408;
+ color: #fea;
+}
+
+.calendar td.time {
+ border-top: 1px solid #000;
+ padding: 1px 0px;
+ text-align: center;
+ background-color: #f4f0e8;
+}
+
+.calendar td.time .hour,
+.calendar td.time .minute,
+.calendar td.time .ampm {
+ padding: 0px 3px 0px 4px;
+ border: 1px solid #889;
+ font-weight: bold;
+ background-color: #fff;
+}
+
+.calendar td.time .ampm {
+ text-align: center;
+}
+
+.calendar td.time .colon {
+ padding: 0px 2px 0px 3px;
+ font-weight: bold;
+}
+
+.calendar td.time span.hilite {
+ border-color: #000;
+ background-color: #766;
+ color: #fff;
+}
+
+.calendar td.time span.active {
+ border-color: #f00;
+ background-color: #000;
+ color: #0f0;
+}
diff --git a/httemplate/elements/calendar.js b/httemplate/elements/calendar.js
new file mode 100644
index 000000000..f5c74f608
--- /dev/null
+++ b/httemplate/elements/calendar.js
@@ -0,0 +1,1806 @@
+/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
+ * -----------------------------------------------------------
+ *
+ * The DHTML Calendar, version 1.0 "It is happening again"
+ *
+ * Details and latest version at:
+ * www.dynarch.com/projects/calendar
+ *
+ * This script is developed by Dynarch.com. Visit us at www.dynarch.com.
+ *
+ * This script is distributed under the GNU Lesser General Public License.
+ * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
+ */
+
+// $Id: calendar.js,v 1.5 2006-02-09 07:18:08 ivan Exp $
+
+/** The Calendar object constructor. */
+Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
+ // member variables
+ this.activeDiv = null;
+ this.currentDateEl = null;
+ this.getDateStatus = null;
+ this.getDateToolTip = null;
+ this.getDateText = null;
+ this.timeout = null;
+ this.onSelected = onSelected || null;
+ this.onClose = onClose || null;
+ this.dragging = false;
+ this.hidden = false;
+ this.minYear = 1970;
+ this.maxYear = 2050;
+ this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
+ this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
+ this.isPopup = true;
+ this.weekNumbers = true;
+ this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
+ this.showsOtherMonths = false;
+ this.dateStr = dateStr;
+ this.ar_days = null;
+ this.showsTime = false;
+ this.time24 = true;
+ this.yearStep = 2;
+ this.hiliteToday = true;
+ this.multiple = null;
+ // HTML elements
+ this.table = null;
+ this.element = null;
+ this.tbody = null;
+ this.firstdayname = null;
+ // Combo boxes
+ this.monthsCombo = null;
+ this.yearsCombo = null;
+ this.hilitedMonth = null;
+ this.activeMonth = null;
+ this.hilitedYear = null;
+ this.activeYear = null;
+ // Information
+ this.dateClicked = false;
+
+ // one-time initializations
+ if (typeof Calendar._SDN == "undefined") {
+ // table of short day names
+ if (typeof Calendar._SDN_len == "undefined")
+ Calendar._SDN_len = 3;
+ var ar = new Array();
+ for (var i = 8; i > 0;) {
+ ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
+ }
+ Calendar._SDN = ar;
+ // table of short month names
+ if (typeof Calendar._SMN_len == "undefined")
+ Calendar._SMN_len = 3;
+ ar = new Array();
+ for (var i = 12; i > 0;) {
+ ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
+ }
+ Calendar._SMN = ar;
+ }
+};
+
+// ** constants
+
+/// "static", needed for event handlers.
+Calendar._C = null;
+
+/// detect a special case of "web browser"
+Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
+ !/opera/i.test(navigator.userAgent) );
+
+Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
+
+/// detect Opera browser
+Calendar.is_opera = /opera/i.test(navigator.userAgent);
+
+/// detect KHTML-based browsers
+Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
+
+// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
+// library, at some point.
+
+Calendar.getAbsolutePos = function(el) {
+ var SL = 0, ST = 0;
+ var is_div = /^div$/i.test(el.tagName);
+ if (is_div && el.scrollLeft)
+ SL = el.scrollLeft;
+ if (is_div && el.scrollTop)
+ ST = el.scrollTop;
+ var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
+ if (el.offsetParent) {
+ var tmp = this.getAbsolutePos(el.offsetParent);
+ r.x += tmp.x;
+ r.y += tmp.y;
+ }
+ return r;
+};
+
+Calendar.isRelated = function (el, evt) {
+ var related = evt.relatedTarget;
+ if (!related) {
+ var type = evt.type;
+ if (type == "mouseover") {
+ related = evt.fromElement;
+ } else if (type == "mouseout") {
+ related = evt.toElement;
+ }
+ }
+ while (related) {
+ if (related == el) {
+ return true;
+ }
+ related = related.parentNode;
+ }
+ return false;
+};
+
+Calendar.removeClass = function(el, className) {
+ if (!(el && el.className)) {
+ return;
+ }
+ var cls = el.className.split(" ");
+ var ar = new Array();
+ for (var i = cls.length; i > 0;) {
+ if (cls[--i] != className) {
+ ar[ar.length] = cls[i];
+ }
+ }
+ el.className = ar.join(" ");
+};
+
+Calendar.addClass = function(el, className) {
+ Calendar.removeClass(el, className);
+ el.className += " " + className;
+};
+
+// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
+Calendar.getElement = function(ev) {
+ var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
+ while (f.nodeType != 1 || /^div$/i.test(f.tagName))
+ f = f.parentNode;
+ return f;
+};
+
+Calendar.getTargetElement = function(ev) {
+ var f = Calendar.is_ie ? window.event.srcElement : ev.target;
+ while (f.nodeType != 1)
+ f = f.parentNode;
+ return f;
+};
+
+Calendar.stopEvent = function(ev) {
+ ev || (ev = window.event);
+ if (Calendar.is_ie) {
+ ev.cancelBubble = true;
+ ev.returnValue = false;
+ } else {
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ return false;
+};
+
+Calendar.addEvent = function(el, evname, func) {
+ if (el.attachEvent) { // IE
+ el.attachEvent("on" + evname, func);
+ } else if (el.addEventListener) { // Gecko / W3C
+ el.addEventListener(evname, func, true);
+ } else {
+ el["on" + evname] = func;
+ }
+};
+
+Calendar.removeEvent = function(el, evname, func) {
+ if (el.detachEvent) { // IE
+ el.detachEvent("on" + evname, func);
+ } else if (el.removeEventListener) { // Gecko / W3C
+ el.removeEventListener(evname, func, true);
+ } else {
+ el["on" + evname] = null;
+ }
+};
+
+Calendar.createElement = function(type, parent) {
+ var el = null;
+ if (document.createElementNS) {
+ // use the XHTML namespace; IE won't normally get here unless
+ // _they_ "fix" the DOM2 implementation.
+ el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
+ } else {
+ el = document.createElement(type);
+ }
+ if (typeof parent != "undefined") {
+ parent.appendChild(el);
+ }
+ return el;
+};
+
+// END: UTILITY FUNCTIONS
+
+// BEGIN: CALENDAR STATIC FUNCTIONS
+
+/** Internal -- adds a set of events to make some element behave like a button. */
+Calendar._add_evs = function(el) {
+ with (Calendar) {
+ addEvent(el, "mouseover", dayMouseOver);
+ addEvent(el, "mousedown", dayMouseDown);
+ addEvent(el, "mouseout", dayMouseOut);
+ if (is_ie) {
+ addEvent(el, "dblclick", dayMouseDblClick);
+ el.setAttribute("unselectable", true);
+ }
+ }
+};
+
+Calendar.findMonth = function(el) {
+ if (typeof el.month != "undefined") {
+ return el;
+ } else if (typeof el.parentNode.month != "undefined") {
+ return el.parentNode;
+ }
+ return null;
+};
+
+Calendar.findYear = function(el) {
+ if (typeof el.year != "undefined") {
+ return el;
+ } else if (typeof el.parentNode.year != "undefined") {
+ return el.parentNode;
+ }
+ return null;
+};
+
+Calendar.showMonthsCombo = function () {
+ var cal = Calendar._C;
+ if (!cal) {
+ return false;
+ }
+ var cal = cal;
+ var cd = cal.activeDiv;
+ var mc = cal.monthsCombo;
+ if (cal.hilitedMonth) {
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
+ }
+ if (cal.activeMonth) {
+ Calendar.removeClass(cal.activeMonth, "active");
+ }
+ var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
+ Calendar.addClass(mon, "active");
+ cal.activeMonth = mon;
+ var s = mc.style;
+ s.display = "block";
+ if (cd.navtype < 0)
+ s.left = cd.offsetLeft + "px";
+ else {
+ var mcw = mc.offsetWidth;
+ if (typeof mcw == "undefined")
+ // Konqueror brain-dead techniques
+ mcw = 50;
+ s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
+ }
+ s.top = (cd.offsetTop + cd.offsetHeight) + "px";
+};
+
+Calendar.showYearsCombo = function (fwd) {
+ var cal = Calendar._C;
+ if (!cal) {
+ return false;
+ }
+ var cal = cal;
+ var cd = cal.activeDiv;
+ var yc = cal.yearsCombo;
+ if (cal.hilitedYear) {
+ Calendar.removeClass(cal.hilitedYear, "hilite");
+ }
+ if (cal.activeYear) {
+ Calendar.removeClass(cal.activeYear, "active");
+ }
+ cal.activeYear = null;
+ var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
+ var yr = yc.firstChild;
+ var show = false;
+ for (var i = 12; i > 0; --i) {
+ if (Y >= cal.minYear && Y <= cal.maxYear) {
+ yr.innerHTML = Y;
+ yr.year = Y;
+ yr.style.display = "block";
+ show = true;
+ } else {
+ yr.style.display = "none";
+ }
+ yr = yr.nextSibling;
+ Y += fwd ? cal.yearStep : -cal.yearStep;
+ }
+ if (show) {
+ var s = yc.style;
+ s.display = "block";
+ if (cd.navtype < 0)
+ s.left = cd.offsetLeft + "px";
+ else {
+ var ycw = yc.offsetWidth;
+ if (typeof ycw == "undefined")
+ // Konqueror brain-dead techniques
+ ycw = 50;
+ s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
+ }
+ s.top = (cd.offsetTop + cd.offsetHeight) + "px";
+ }
+};
+
+// event handlers
+
+Calendar.tableMouseUp = function(ev) {
+ var cal = Calendar._C;
+ if (!cal) {
+ return false;
+ }
+ if (cal.timeout) {
+ clearTimeout(cal.timeout);
+ }
+ var el = cal.activeDiv;
+ if (!el) {
+ return false;
+ }
+ var target = Calendar.getTargetElement(ev);
+ ev || (ev = window.event);
+ Calendar.removeClass(el, "active");
+ if (target == el || target.parentNode == el) {
+ Calendar.cellClick(el, ev);
+ }
+ var mon = Calendar.findMonth(target);
+ var date = null;
+ if (mon) {
+ date = new Date(cal.date);
+ if (mon.month != date.getMonth()) {
+ date.setMonth(mon.month);
+ cal.setDate(date);
+ cal.dateClicked = false;
+ cal.callHandler();
+ }
+ } else {
+ var year = Calendar.findYear(target);
+ if (year) {
+ date = new Date(cal.date);
+ if (year.year != date.getFullYear()) {
+ date.setFullYear(year.year);
+ cal.setDate(date);
+ cal.dateClicked = false;
+ cal.callHandler();
+ }
+ }
+ }
+ with (Calendar) {
+ removeEvent(document, "mouseup", tableMouseUp);
+ removeEvent(document, "mouseover", tableMouseOver);
+ removeEvent(document, "mousemove", tableMouseOver);
+ cal._hideCombos();
+ _C = null;
+ return stopEvent(ev);
+ }
+};
+
+Calendar.tableMouseOver = function (ev) {
+ var cal = Calendar._C;
+ if (!cal) {
+ return;
+ }
+ var el = cal.activeDiv;
+ var target = Calendar.getTargetElement(ev);
+ if (target == el || target.parentNode == el) {
+ Calendar.addClass(el, "hilite active");
+ Calendar.addClass(el.parentNode, "rowhilite");
+ } else {
+ if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
+ Calendar.removeClass(el, "active");
+ Calendar.removeClass(el, "hilite");
+ Calendar.removeClass(el.parentNode, "rowhilite");
+ }
+ ev || (ev = window.event);
+ if (el.navtype == 50 && target != el) {
+ var pos = Calendar.getAbsolutePos(el);
+ var w = el.offsetWidth;
+ var x = ev.clientX;
+ var dx;
+ var decrease = true;
+ if (x > pos.x + w) {
+ dx = x - pos.x - w;
+ decrease = false;
+ } else
+ dx = pos.x - x;
+
+ if (dx < 0) dx = 0;
+ var range = el._range;
+ var current = el._current;
+ var count = Math.floor(dx / 10) % range.length;
+ for (var i = range.length; --i >= 0;)
+ if (range[i] == current)
+ break;
+ while (count-- > 0)
+ if (decrease) {
+ if (--i < 0)
+ i = range.length - 1;
+ } else if ( ++i >= range.length )
+ i = 0;
+ var newval = range[i];
+ el.innerHTML = newval;
+
+ cal.onUpdateTime();
+ }
+ var mon = Calendar.findMonth(target);
+ if (mon) {
+ if (mon.month != cal.date.getMonth()) {
+ if (cal.hilitedMonth) {
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
+ }
+ Calendar.addClass(mon, "hilite");
+ cal.hilitedMonth = mon;
+ } else if (cal.hilitedMonth) {
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
+ }
+ } else {
+ if (cal.hilitedMonth) {
+ Calendar.removeClass(cal.hilitedMonth, "hilite");
+ }
+ var year = Calendar.findYear(target);
+ if (year) {
+ if (year.year != cal.date.getFullYear()) {
+ if (cal.hilitedYear) {
+ Calendar.removeClass(cal.hilitedYear, "hilite");
+ }
+ Calendar.addClass(year, "hilite");
+ cal.hilitedYear = year;
+ } else if (cal.hilitedYear) {
+ Calendar.removeClass(cal.hilitedYear, "hilite");
+ }
+ } else if (cal.hilitedYear) {
+ Calendar.removeClass(cal.hilitedYear, "hilite");
+ }
+ }
+ return Calendar.stopEvent(ev);
+};
+
+Calendar.tableMouseDown = function (ev) {
+ if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
+ return Calendar.stopEvent(ev);
+ }
+};
+
+Calendar.calDragIt = function (ev) {
+ var cal = Calendar._C;
+ if (!(cal && cal.dragging)) {
+ return false;
+ }
+ var posX;
+ var posY;
+ if (Calendar.is_ie) {
+ posY = window.event.clientY + document.body.scrollTop;
+ posX = window.event.clientX + document.body.scrollLeft;
+ } else {
+ posX = ev.pageX;
+ posY = ev.pageY;
+ }
+ cal.hideShowCovered();
+ var st = cal.element.style;
+ st.left = (posX - cal.xOffs) + "px";
+ st.top = (posY - cal.yOffs) + "px";
+ return Calendar.stopEvent(ev);
+};
+
+Calendar.calDragEnd = function (ev) {
+ var cal = Calendar._C;
+ if (!cal) {
+ return false;
+ }
+ cal.dragging = false;
+ with (Calendar) {
+ removeEvent(document, "mousemove", calDragIt);
+ removeEvent(document, "mouseup", calDragEnd);
+ tableMouseUp(ev);
+ }
+ cal.hideShowCovered();
+};
+
+Calendar.dayMouseDown = function(ev) {
+ var el = Calendar.getElement(ev);
+ if (el.disabled) {
+ return false;
+ }
+ var cal = el.calendar;
+ cal.activeDiv = el;
+ Calendar._C = cal;
+ if (el.navtype != 300) with (Calendar) {
+ if (el.navtype == 50) {
+ el._current = el.innerHTML;
+ addEvent(document, "mousemove", tableMouseOver);
+ } else
+ addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
+ addClass(el, "hilite active");
+ addEvent(document, "mouseup", tableMouseUp);
+ } else if (cal.isPopup) {
+ cal._dragStart(ev);
+ }
+ if (el.navtype == -1 || el.navtype == 1) {
+ if (cal.timeout) clearTimeout(cal.timeout);
+ cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
+ } else if (el.navtype == -2 || el.navtype == 2) {
+ if (cal.timeout) clearTimeout(cal.timeout);
+ cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
+ } else {
+ cal.timeout = null;
+ }
+ return Calendar.stopEvent(ev);
+};
+
+Calendar.dayMouseDblClick = function(ev) {
+ Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
+ if (Calendar.is_ie) {
+ document.selection.empty();
+ }
+};
+
+Calendar.dayMouseOver = function(ev) {
+ var el = Calendar.getElement(ev);
+ if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
+ return false;
+ }
+ if (el.ttip) {
+ if (el.ttip.substr(0, 1) == "_") {
+ el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
+ }
+ el.calendar.tooltips.innerHTML = el.ttip;
+ }
+ if (el.navtype != 300) {
+ Calendar.addClass(el, "hilite");
+ if (el.caldate) {
+ Calendar.addClass(el.parentNode, "rowhilite");
+ }
+ }
+ return Calendar.stopEvent(ev);
+};
+
+Calendar.dayMouseOut = function(ev) {
+ with (Calendar) {
+ var el = getElement(ev);
+ if (isRelated(el, ev) || _C || el.disabled)
+ return false;
+ removeClass(el, "hilite");
+ if (el.caldate)
+ removeClass(el.parentNode, "rowhilite");
+ if (el.calendar)
+ el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
+ return stopEvent(ev);
+ }
+};
+
+/**
+ * A generic "click" handler :) handles all types of buttons defined in this
+ * calendar.
+ */
+Calendar.cellClick = function(el, ev) {
+ var cal = el.calendar;
+ var closing = false;
+ var newdate = false;
+ var date = null;
+ if (typeof el.navtype == "undefined") {
+ if (cal.currentDateEl) {
+ Calendar.removeClass(cal.currentDateEl, "selected");
+ Calendar.addClass(el, "selected");
+ closing = (cal.currentDateEl == el);
+ if (!closing) {
+ cal.currentDateEl = el;
+ }
+ }
+ cal.date.setDateOnly(el.caldate);
+ date = cal.date;
+ var other_month = !(cal.dateClicked = !el.otherMonth);
+ if (!other_month && !cal.currentDateEl)
+ cal._toggleMultipleDate(new Date(date));
+ else
+ newdate = !el.disabled;
+ // a date was clicked
+ if (other_month)
+ cal._init(cal.firstDayOfWeek, date);
+ } else {
+ if (el.navtype == 200) {
+ Calendar.removeClass(el, "hilite");
+ cal.callCloseHandler();
+ return;
+ }
+ date = new Date(cal.date);
+ if (el.navtype == 0)
+ date.setDateOnly(new Date()); // TODAY
+ // unless "today" was clicked, we assume no date was clicked so
+ // the selected handler will know not to close the calenar when
+ // in single-click mode.
+ // cal.dateClicked = (el.navtype == 0);
+ cal.dateClicked = false;
+ var year = date.getFullYear();
+ var mon = date.getMonth();
+ function setMonth(m) {
+ var day = date.getDate();
+ var max = date.getMonthDays(m);
+ if (day > max) {
+ date.setDate(max);
+ }
+ date.setMonth(m);
+ };
+ switch (el.navtype) {
+ case 400:
+ Calendar.removeClass(el, "hilite");
+ var text = Calendar._TT["ABOUT"];
+ if (typeof text != "undefined") {
+ text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
+ } else {
+ // FIXME: this should be removed as soon as lang files get updated!
+ text = "Help and about box text is not translated into this language.\n" +
+ "If you know this language and you feel generous please update\n" +
+ "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
+ "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n" +
+ "Thank you!\n" +
+ "http://dynarch.com/mishoo/calendar.epl\n";
+ }
+ alert(text);
+ return;
+ case -2:
+ if (year > cal.minYear) {
+ date.setFullYear(year - 1);
+ }
+ break;
+ case -1:
+ if (mon > 0) {
+ setMonth(mon - 1);
+ } else if (year-- > cal.minYear) {
+ date.setFullYear(year);
+ setMonth(11);
+ }
+ break;
+ case 1:
+ if (mon < 11) {
+ setMonth(mon + 1);
+ } else if (year < cal.maxYear) {
+ date.setFullYear(year + 1);
+ setMonth(0);
+ }
+ break;
+ case 2:
+ if (year < cal.maxYear) {
+ date.setFullYear(year + 1);
+ }
+ break;
+ case 100:
+ cal.setFirstDayOfWeek(el.fdow);
+ return;
+ case 50:
+ var range = el._range;
+ var current = el.innerHTML;
+ for (var i = range.length; --i >= 0;)
+ if (range[i] == current)
+ break;
+ if (ev && ev.shiftKey) {
+ if (--i < 0)
+ i = range.length - 1;
+ } else if ( ++i >= range.length )
+ i = 0;
+ var newval = range[i];
+ el.innerHTML = newval;
+ cal.onUpdateTime();
+ return;
+ case 0:
+ // TODAY will bring us here
+ if ((typeof cal.getDateStatus == "function") &&
+ cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
+ return false;
+ }
+ break;
+ }
+ if (!date.equalsTo(cal.date)) {
+ cal.setDate(date);
+ newdate = true;
+ } else if (el.navtype == 0)
+ newdate = closing = true;
+ }
+ if (newdate) {
+ ev && cal.callHandler();
+ }
+ if (closing) {
+ Calendar.removeClass(el, "hilite");
+ ev && cal.callCloseHandler();
+ }
+};
+
+// END: CALENDAR STATIC FUNCTIONS
+
+// BEGIN: CALENDAR OBJECT FUNCTIONS
+
+/**
+ * This function creates the calendar inside the given parent. If _par is
+ * null than it creates a popup calendar inside the BODY element. If _par is
+ * an element, be it BODY, then it creates a non-popup calendar (still
+ * hidden). Some properties need to be set before calling this function.
+ */
+Calendar.prototype.create = function (_par) {
+ var parent = null;
+ if (! _par) {
+ // default parent is the document body, in which case we create
+ // a popup calendar.
+ parent = document.getElementsByTagName("body")[0];
+ this.isPopup = true;
+ } else {
+ parent = _par;
+ this.isPopup = false;
+ }
+ this.date = this.dateStr ? new Date(this.dateStr) : new Date();
+
+ var table = Calendar.createElement("table");
+ this.table = table;
+ table.cellSpacing = 0;
+ table.cellPadding = 0;
+ table.calendar = this;
+ Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
+
+ var div = Calendar.createElement("div");
+ this.element = div;
+ div.className = "calendar";
+ if (this.isPopup) {
+ div.style.position = "absolute";
+ div.style.display = "none";
+ }
+ div.appendChild(table);
+
+ var thead = Calendar.createElement("thead", table);
+ var cell = null;
+ var row = null;
+
+ var cal = this;
+ var hh = function (text, cs, navtype) {
+ cell = Calendar.createElement("td", row);
+ cell.colSpan = cs;
+ cell.className = "button";
+ if (navtype != 0 && Math.abs(navtype) <= 2)
+ cell.className += " nav";
+ Calendar._add_evs(cell);
+ cell.calendar = cal;
+ cell.navtype = navtype;
+ cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
+ return cell;
+ };
+
+ row = Calendar.createElement("tr", thead);
+ var title_length = 6;
+ (this.isPopup) && --title_length;
+ (this.weekNumbers) && ++title_length;
+
+ hh("?", 1, 400).ttip = Calendar._TT["INFO"];
+ this.title = hh("", title_length, 300);
+ this.title.className = "title";
+ if (this.isPopup) {
+ this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
+ this.title.style.cursor = "move";
+ hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
+ }
+
+ row = Calendar.createElement("tr", thead);
+ row.className = "headrow";
+
+ this._nav_py = hh("&#x00ab;", 1, -2);
+ this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
+
+ this._nav_pm = hh("&#x2039;", 1, -1);
+ this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
+
+ this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
+ this._nav_now.ttip = Calendar._TT["GO_TODAY"];
+
+ this._nav_nm = hh("&#x203a;", 1, 1);
+ this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
+
+ this._nav_ny = hh("&#x00bb;", 1, 2);
+ this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
+
+ // day names
+ row = Calendar.createElement("tr", thead);
+ row.className = "daynames";
+ if (this.weekNumbers) {
+ cell = Calendar.createElement("td", row);
+ cell.className = "name wn";
+ cell.innerHTML = Calendar._TT["WK"];
+ }
+ for (var i = 7; i > 0; --i) {
+ cell = Calendar.createElement("td", row);
+ if (!i) {
+ cell.navtype = 100;
+ cell.calendar = this;
+ Calendar._add_evs(cell);
+ }
+ }
+ this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
+ this._displayWeekdays();
+
+ var tbody = Calendar.createElement("tbody", table);
+ this.tbody = tbody;
+
+ for (i = 6; i > 0; --i) {
+ row = Calendar.createElement("tr", tbody);
+ if (this.weekNumbers) {
+ cell = Calendar.createElement("td", row);
+ }
+ for (var j = 7; j > 0; --j) {
+ cell = Calendar.createElement("td", row);
+ cell.calendar = this;
+ Calendar._add_evs(cell);
+ }
+ }
+
+ if (this.showsTime) {
+ row = Calendar.createElement("tr", tbody);
+ row.className = "time";
+
+ cell = Calendar.createElement("td", row);
+ cell.className = "time";
+ cell.colSpan = 2;
+ cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
+
+ cell = Calendar.createElement("td", row);
+ cell.className = "time";
+ cell.colSpan = this.weekNumbers ? 4 : 3;
+
+ (function(){
+ function makeTimePart(className, init, range_start, range_end) {
+ var part = Calendar.createElement("span", cell);
+ part.className = className;
+ part.innerHTML = init;
+ part.calendar = cal;
+ part.ttip = Calendar._TT["TIME_PART"];
+ part.navtype = 50;
+ part._range = [];
+ if (typeof range_start != "number")
+ part._range = range_start;
+ else {
+ for (var i = range_start; i <= range_end; ++i) {
+ var txt;
+ if (i < 10 && range_end >= 10) txt = '0' + i;
+ else txt = '' + i;
+ part._range[part._range.length] = txt;
+ }
+ }
+ Calendar._add_evs(part);
+ return part;
+ };
+ var hrs = cal.date.getHours();
+ var mins = cal.date.getMinutes();
+ var t12 = !cal.time24;
+ var pm = (hrs > 12);
+ if (t12 && pm) hrs -= 12;
+ var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
+ var span = Calendar.createElement("span", cell);
+ span.innerHTML = ":";
+ span.className = "colon";
+ var M = makeTimePart("minute", mins, 0, 59);
+ var AP = null;
+ cell = Calendar.createElement("td", row);
+ cell.className = "time";
+ cell.colSpan = 2;
+ if (t12)
+ AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
+ else
+ cell.innerHTML = "&nbsp;";
+
+ cal.onSetTime = function() {
+ var pm, hrs = this.date.getHours(),
+ mins = this.date.getMinutes();
+ if (t12) {
+ pm = (hrs >= 12);
+ if (pm) hrs -= 12;
+ if (hrs == 0) hrs = 12;
+ AP.innerHTML = pm ? "pm" : "am";
+ }
+ H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
+ M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
+ };
+
+ cal.onUpdateTime = function() {
+ var date = this.date;
+ var h = parseInt(H.innerHTML, 10);
+ if (t12) {
+ if (/pm/i.test(AP.innerHTML) && h < 12)
+ h += 12;
+ else if (/am/i.test(AP.innerHTML) && h == 12)
+ h = 0;
+ }
+ var d = date.getDate();
+ var m = date.getMonth();
+ var y = date.getFullYear();
+ date.setHours(h);
+ date.setMinutes(parseInt(M.innerHTML, 10));
+ date.setFullYear(y);
+ date.setMonth(m);
+ date.setDate(d);
+ this.dateClicked = false;
+ this.callHandler();
+ };
+ })();
+ } else {
+ this.onSetTime = this.onUpdateTime = function() {};
+ }
+
+ var tfoot = Calendar.createElement("tfoot", table);
+
+ row = Calendar.createElement("tr", tfoot);
+ row.className = "footrow";
+
+ cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
+ cell.className = "ttip";
+ if (this.isPopup) {
+ cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
+ cell.style.cursor = "move";
+ }
+ this.tooltips = cell;
+
+ div = Calendar.createElement("div", this.element);
+ this.monthsCombo = div;
+ div.className = "combo";
+ for (i = 0; i < Calendar._MN.length; ++i) {
+ var mn = Calendar.createElement("div");
+ mn.className = Calendar.is_ie ? "label-IEfix" : "label";
+ mn.month = i;
+ mn.innerHTML = Calendar._SMN[i];
+ div.appendChild(mn);
+ }
+
+ div = Calendar.createElement("div", this.element);
+ this.yearsCombo = div;
+ div.className = "combo";
+ for (i = 12; i > 0; --i) {
+ var yr = Calendar.createElement("div");
+ yr.className = Calendar.is_ie ? "label-IEfix" : "label";
+ div.appendChild(yr);
+ }
+
+ this._init(this.firstDayOfWeek, this.date);
+ parent.appendChild(this.element);
+};
+
+/** keyboard navigation, only for popup calendars */
+Calendar._keyEvent = function(ev) {
+ var cal = window._dynarch_popupCalendar;
+ if (!cal || cal.multiple)
+ return false;
+ (Calendar.is_ie) && (ev = window.event);
+ var act = (Calendar.is_ie || ev.type == "keypress"),
+ K = ev.keyCode;
+ if (ev.ctrlKey) {
+ switch (K) {
+ case 37: // KEY left
+ act && Calendar.cellClick(cal._nav_pm);
+ break;
+ case 38: // KEY up
+ act && Calendar.cellClick(cal._nav_py);
+ break;
+ case 39: // KEY right
+ act && Calendar.cellClick(cal._nav_nm);
+ break;
+ case 40: // KEY down
+ act && Calendar.cellClick(cal._nav_ny);
+ break;
+ default:
+ return false;
+ }
+ } else switch (K) {
+ case 32: // KEY space (now)
+ Calendar.cellClick(cal._nav_now);
+ break;
+ case 27: // KEY esc
+ act && cal.callCloseHandler();
+ break;
+ case 37: // KEY left
+ case 38: // KEY up
+ case 39: // KEY right
+ case 40: // KEY down
+ if (act) {
+ var prev, x, y, ne, el, step;
+ prev = K == 37 || K == 38;
+ step = (K == 37 || K == 39) ? 1 : 7;
+ function setVars() {
+ el = cal.currentDateEl;
+ var p = el.pos;
+ x = p & 15;
+ y = p >> 4;
+ ne = cal.ar_days[y][x];
+ };setVars();
+ function prevMonth() {
+ var date = new Date(cal.date);
+ date.setDate(date.getDate() - step);
+ cal.setDate(date);
+ };
+ function nextMonth() {
+ var date = new Date(cal.date);
+ date.setDate(date.getDate() + step);
+ cal.setDate(date);
+ };
+ while (1) {
+ switch (K) {
+ case 37: // KEY left
+ if (--x >= 0)
+ ne = cal.ar_days[y][x];
+ else {
+ x = 6;
+ K = 38;
+ continue;
+ }
+ break;
+ case 38: // KEY up
+ if (--y >= 0)
+ ne = cal.ar_days[y][x];
+ else {
+ prevMonth();
+ setVars();
+ }
+ break;
+ case 39: // KEY right
+ if (++x < 7)
+ ne = cal.ar_days[y][x];
+ else {
+ x = 0;
+ K = 40;
+ continue;
+ }
+ break;
+ case 40: // KEY down
+ if (++y < cal.ar_days.length)
+ ne = cal.ar_days[y][x];
+ else {
+ nextMonth();
+ setVars();
+ }
+ break;
+ }
+ break;
+ }
+ if (ne) {
+ if (!ne.disabled)
+ Calendar.cellClick(ne);
+ else if (prev)
+ prevMonth();
+ else
+ nextMonth();
+ }
+ }
+ break;
+ case 13: // KEY enter
+ if (act)
+ Calendar.cellClick(cal.currentDateEl, ev);
+ break;
+ default:
+ return false;
+ }
+ return Calendar.stopEvent(ev);
+};
+
+/**
+ * (RE)Initializes the calendar to the given date and firstDayOfWeek
+ */
+Calendar.prototype._init = function (firstDayOfWeek, date) {
+ var today = new Date(),
+ TY = today.getFullYear(),
+ TM = today.getMonth(),
+ TD = today.getDate();
+ this.table.style.visibility = "hidden";
+ var year = date.getFullYear();
+ if (year < this.minYear) {
+ year = this.minYear;
+ date.setFullYear(year);
+ } else if (year > this.maxYear) {
+ year = this.maxYear;
+ date.setFullYear(year);
+ }
+ this.firstDayOfWeek = firstDayOfWeek;
+ this.date = new Date(date);
+ var month = date.getMonth();
+ var mday = date.getDate();
+ var no_days = date.getMonthDays();
+
+ // calendar voodoo for computing the first day that would actually be
+ // displayed in the calendar, even if it's from the previous month.
+ // WARNING: this is magic. ;-)
+ date.setDate(1);
+ var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
+ if (day1 < 0)
+ day1 += 7;
+ date.setDate(-day1);
+ date.setDate(date.getDate() + 1);
+
+ var row = this.tbody.firstChild;
+ var MN = Calendar._SMN[month];
+ var ar_days = this.ar_days = new Array();
+ var weekend = Calendar._TT["WEEKEND"];
+ var dates = this.multiple ? (this.datesCells = {}) : null;
+ for (var i = 0; i < 6; ++i, row = row.nextSibling) {
+ var cell = row.firstChild;
+ if (this.weekNumbers) {
+ cell.className = "day wn";
+ cell.innerHTML = date.getWeekNumber();
+ cell = cell.nextSibling;
+ }
+ row.className = "daysrow";
+ var hasdays = false, iday, dpos = ar_days[i] = [];
+ for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
+ iday = date.getDate();
+ var wday = date.getDay();
+ cell.className = "day";
+ cell.pos = i << 4 | j;
+ dpos[j] = cell;
+ var current_month = (date.getMonth() == month);
+ if (!current_month) {
+ if (this.showsOtherMonths) {
+ cell.className += " othermonth";
+ cell.otherMonth = true;
+ } else {
+ cell.className = "emptycell";
+ cell.innerHTML = "&nbsp;";
+ cell.disabled = true;
+ continue;
+ }
+ } else {
+ cell.otherMonth = false;
+ hasdays = true;
+ }
+ cell.disabled = false;
+ cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
+ if (dates)
+ dates[date.print("%Y%m%d")] = cell;
+ if (this.getDateStatus) {
+ var status = this.getDateStatus(date, year, month, iday);
+ if (this.getDateToolTip) {
+ var toolTip = this.getDateToolTip(date, year, month, iday);
+ if (toolTip)
+ cell.title = toolTip;
+ }
+ if (status === true) {
+ cell.className += " disabled";
+ cell.disabled = true;
+ } else {
+ if (/disabled/i.test(status))
+ cell.disabled = true;
+ cell.className += " " + status;
+ }
+ }
+ if (!cell.disabled) {
+ cell.caldate = new Date(date);
+ cell.ttip = "_";
+ if (!this.multiple && current_month
+ && iday == mday && this.hiliteToday) {
+ cell.className += " selected";
+ this.currentDateEl = cell;
+ }
+ if (date.getFullYear() == TY &&
+ date.getMonth() == TM &&
+ iday == TD) {
+ cell.className += " today";
+ cell.ttip += Calendar._TT["PART_TODAY"];
+ }
+ if (weekend.indexOf(wday.toString()) != -1)
+ cell.className += cell.otherMonth ? " oweekend" : " weekend";
+ }
+ }
+ if (!(hasdays || this.showsOtherMonths))
+ row.className = "emptyrow";
+ }
+ this.title.innerHTML = Calendar._MN[month] + ", " + year;
+ this.onSetTime();
+ this.table.style.visibility = "visible";
+ this._initMultipleDates();
+ // PROFILE
+ // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
+};
+
+Calendar.prototype._initMultipleDates = function() {
+ if (this.multiple) {
+ for (var i in this.multiple) {
+ var cell = this.datesCells[i];
+ var d = this.multiple[i];
+ if (!d)
+ continue;
+ if (cell)
+ cell.className += " selected";
+ }
+ }
+};
+
+Calendar.prototype._toggleMultipleDate = function(date) {
+ if (this.multiple) {
+ var ds = date.print("%Y%m%d");
+ var cell = this.datesCells[ds];
+ if (cell) {
+ var d = this.multiple[ds];
+ if (!d) {
+ Calendar.addClass(cell, "selected");
+ this.multiple[ds] = date;
+ } else {
+ Calendar.removeClass(cell, "selected");
+ delete this.multiple[ds];
+ }
+ }
+ }
+};
+
+Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
+ this.getDateToolTip = unaryFunction;
+};
+
+/**
+ * Calls _init function above for going to a certain date (but only if the
+ * date is different than the currently selected one).
+ */
+Calendar.prototype.setDate = function (date) {
+ if (!date.equalsTo(this.date)) {
+ this._init(this.firstDayOfWeek, date);
+ }
+};
+
+/**
+ * Refreshes the calendar. Useful if the "disabledHandler" function is
+ * dynamic, meaning that the list of disabled date can change at runtime.
+ * Just * call this function if you think that the list of disabled dates
+ * should * change.
+ */
+Calendar.prototype.refresh = function () {
+ this._init(this.firstDayOfWeek, this.date);
+};
+
+/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
+Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
+ this._init(firstDayOfWeek, this.date);
+ this._displayWeekdays();
+};
+
+/**
+ * Allows customization of what dates are enabled. The "unaryFunction"
+ * parameter must be a function object that receives the date (as a JS Date
+ * object) and returns a boolean value. If the returned value is true then
+ * the passed date will be marked as disabled.
+ */
+Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
+ this.getDateStatus = unaryFunction;
+};
+
+/** Customization of allowed year range for the calendar. */
+Calendar.prototype.setRange = function (a, z) {
+ this.minYear = a;
+ this.maxYear = z;
+};
+
+/** Calls the first user handler (selectedHandler). */
+Calendar.prototype.callHandler = function () {
+ if (this.onSelected) {
+ this.onSelected(this, this.date.print(this.dateFormat));
+ }
+};
+
+/** Calls the second user handler (closeHandler). */
+Calendar.prototype.callCloseHandler = function () {
+ if (this.onClose) {
+ this.onClose(this);
+ }
+ this.hideShowCovered();
+};
+
+/** Removes the calendar object from the DOM tree and destroys it. */
+Calendar.prototype.destroy = function () {
+ var el = this.element.parentNode;
+ el.removeChild(this.element);
+ Calendar._C = null;
+ window._dynarch_popupCalendar = null;
+};
+
+/**
+ * Moves the calendar element to a different section in the DOM tree (changes
+ * its parent).
+ */
+Calendar.prototype.reparent = function (new_parent) {
+ var el = this.element;
+ el.parentNode.removeChild(el);
+ new_parent.appendChild(el);
+};
+
+// This gets called when the user presses a mouse button anywhere in the
+// document, if the calendar is shown. If the click was outside the open
+// calendar this function closes it.
+Calendar._checkCalendar = function(ev) {
+ var calendar = window._dynarch_popupCalendar;
+ if (!calendar) {
+ return false;
+ }
+ var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
+ for (; el != null && el != calendar.element; el = el.parentNode);
+ if (el == null) {
+ // calls closeHandler which should hide the calendar.
+ window._dynarch_popupCalendar.callCloseHandler();
+ return Calendar.stopEvent(ev);
+ }
+};
+
+/** Shows the calendar. */
+Calendar.prototype.show = function () {
+ var rows = this.table.getElementsByTagName("tr");
+ for (var i = rows.length; i > 0;) {
+ var row = rows[--i];
+ Calendar.removeClass(row, "rowhilite");
+ var cells = row.getElementsByTagName("td");
+ for (var j = cells.length; j > 0;) {
+ var cell = cells[--j];
+ Calendar.removeClass(cell, "hilite");
+ Calendar.removeClass(cell, "active");
+ }
+ }
+ this.element.style.display = "block";
+ this.hidden = false;
+ if (this.isPopup) {
+ window._dynarch_popupCalendar = this;
+ Calendar.addEvent(document, "keydown", Calendar._keyEvent);
+ Calendar.addEvent(document, "keypress", Calendar._keyEvent);
+ Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
+ }
+ this.hideShowCovered();
+};
+
+/**
+ * Hides the calendar. Also removes any "hilite" from the class of any TD
+ * element.
+ */
+Calendar.prototype.hide = function () {
+ if (this.isPopup) {
+ Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
+ Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
+ Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
+ }
+ this.element.style.display = "none";
+ this.hidden = true;
+ this.hideShowCovered();
+};
+
+/**
+ * Shows the calendar at a given absolute position (beware that, depending on
+ * the calendar element style -- position property -- this might be relative
+ * to the parent's containing rectangle).
+ */
+Calendar.prototype.showAt = function (x, y) {
+ var s = this.element.style;
+ s.left = x + "px";
+ s.top = y + "px";
+ this.show();
+};
+
+/** Shows the calendar near a given element. */
+Calendar.prototype.showAtElement = function (el, opts) {
+ var self = this;
+ var p = Calendar.getAbsolutePos(el);
+ if (!opts || typeof opts != "string") {
+ this.showAt(p.x, p.y + el.offsetHeight);
+ return true;
+ }
+ function fixPosition(box) {
+ if (box.x < 0)
+ box.x = 0;
+ if (box.y < 0)
+ box.y = 0;
+ var cp = document.createElement("div");
+ var s = cp.style;
+ s.position = "absolute";
+ s.right = s.bottom = s.width = s.height = "0px";
+ document.body.appendChild(cp);
+ var br = Calendar.getAbsolutePos(cp);
+ document.body.removeChild(cp);
+ if (Calendar.is_ie) {
+ br.y += document.body.scrollTop;
+ br.x += document.body.scrollLeft;
+ } else {
+ br.y += window.scrollY;
+ br.x += window.scrollX;
+ }
+ var tmp = box.x + box.width - br.x;
+ if (tmp > 0) box.x -= tmp;
+ tmp = box.y + box.height - br.y;
+ if (tmp > 0) box.y -= tmp;
+ };
+ this.element.style.display = "block";
+ Calendar.continuation_for_the_fucking_khtml_browser = function() {
+ var w = self.element.offsetWidth;
+ var h = self.element.offsetHeight;
+ self.element.style.display = "none";
+ var valign = opts.substr(0, 1);
+ var halign = "l";
+ if (opts.length > 1) {
+ halign = opts.substr(1, 1);
+ }
+ // vertical alignment
+ switch (valign) {
+ case "T": p.y -= h; break;
+ case "B": p.y += el.offsetHeight; break;
+ case "C": p.y += (el.offsetHeight - h) / 2; break;
+ case "t": p.y += el.offsetHeight - h; break;
+ case "b": break; // already there
+ }
+ // horizontal alignment
+ switch (halign) {
+ case "L": p.x -= w; break;
+ case "R": p.x += el.offsetWidth; break;
+ case "C": p.x += (el.offsetWidth - w) / 2; break;
+ case "l": p.x += el.offsetWidth - w; break;
+ case "r": break; // already there
+ }
+ p.width = w;
+ p.height = h + 40;
+ self.monthsCombo.style.display = "none";
+ fixPosition(p);
+ self.showAt(p.x, p.y);
+ };
+ if (Calendar.is_khtml)
+ setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
+ else
+ Calendar.continuation_for_the_fucking_khtml_browser();
+};
+
+/** Customizes the date format. */
+Calendar.prototype.setDateFormat = function (str) {
+ this.dateFormat = str;
+};
+
+/** Customizes the tooltip date format. */
+Calendar.prototype.setTtDateFormat = function (str) {
+ this.ttDateFormat = str;
+};
+
+/**
+ * Tries to identify the date represented in a string. If successful it also
+ * calls this.setDate which moves the calendar to the given date.
+ */
+Calendar.prototype.parseDate = function(str, fmt) {
+ if (!fmt)
+ fmt = this.dateFormat;
+ this.setDate(Date.parseDate(str, fmt));
+};
+
+Calendar.prototype.hideShowCovered = function () {
+ if (!Calendar.is_ie && !Calendar.is_opera)
+ return;
+ function getVisib(obj){
+ var value = obj.style.visibility;
+ if (!value) {
+ if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
+ if (!Calendar.is_khtml)
+ value = document.defaultView.
+ getComputedStyle(obj, "").getPropertyValue("visibility");
+ else
+ value = '';
+ } else if (obj.currentStyle) { // IE
+ value = obj.currentStyle.visibility;
+ } else
+ value = '';
+ }
+ return value;
+ };
+
+ var tags = new Array("applet", "iframe", "select");
+ var el = this.element;
+
+ var p = Calendar.getAbsolutePos(el);
+ var EX1 = p.x;
+ var EX2 = el.offsetWidth + EX1;
+ var EY1 = p.y;
+ var EY2 = el.offsetHeight + EY1;
+
+ for (var k = tags.length; k > 0; ) {
+ var ar = document.getElementsByTagName(tags[--k]);
+ var cc = null;
+
+ for (var i = ar.length; i > 0;) {
+ cc = ar[--i];
+
+ p = Calendar.getAbsolutePos(cc);
+ var CX1 = p.x;
+ var CX2 = cc.offsetWidth + CX1;
+ var CY1 = p.y;
+ var CY2 = cc.offsetHeight + CY1;
+
+ if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
+ if (!cc.__msh_save_visibility) {
+ cc.__msh_save_visibility = getVisib(cc);
+ }
+ cc.style.visibility = cc.__msh_save_visibility;
+ } else {
+ if (!cc.__msh_save_visibility) {
+ cc.__msh_save_visibility = getVisib(cc);
+ }
+ cc.style.visibility = "hidden";
+ }
+ }
+ }
+};
+
+/** Internal function; it displays the bar with the names of the weekday. */
+Calendar.prototype._displayWeekdays = function () {
+ var fdow = this.firstDayOfWeek;
+ var cell = this.firstdayname;
+ var weekend = Calendar._TT["WEEKEND"];
+ for (var i = 0; i < 7; ++i) {
+ cell.className = "day name";
+ var realday = (i + fdow) % 7;
+ if (i) {
+ cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
+ cell.navtype = 100;
+ cell.calendar = this;
+ cell.fdow = realday;
+ Calendar._add_evs(cell);
+ }
+ if (weekend.indexOf(realday.toString()) != -1) {
+ Calendar.addClass(cell, "weekend");
+ }
+ cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
+ cell = cell.nextSibling;
+ }
+};
+
+/** Internal function. Hides all combo boxes that might be displayed. */
+Calendar.prototype._hideCombos = function () {
+ this.monthsCombo.style.display = "none";
+ this.yearsCombo.style.display = "none";
+};
+
+/** Internal function. Starts dragging the element. */
+Calendar.prototype._dragStart = function (ev) {
+ if (this.dragging) {
+ return;
+ }
+ this.dragging = true;
+ var posX;
+ var posY;
+ if (Calendar.is_ie) {
+ posY = window.event.clientY + document.body.scrollTop;
+ posX = window.event.clientX + document.body.scrollLeft;
+ } else {
+ posY = ev.clientY + window.scrollY;
+ posX = ev.clientX + window.scrollX;
+ }
+ var st = this.element.style;
+ this.xOffs = posX - parseInt(st.left);
+ this.yOffs = posY - parseInt(st.top);
+ with (Calendar) {
+ addEvent(document, "mousemove", calDragIt);
+ addEvent(document, "mouseup", calDragEnd);
+ }
+};
+
+// BEGIN: DATE OBJECT PATCHES
+
+/** Adds the number of days array to the Date object. */
+Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
+
+/** Constants used for time computations */
+Date.SECOND = 1000 /* milliseconds */;
+Date.MINUTE = 60 * Date.SECOND;
+Date.HOUR = 60 * Date.MINUTE;
+Date.DAY = 24 * Date.HOUR;
+Date.WEEK = 7 * Date.DAY;
+
+Date.parseDate = function(str, fmt) {
+ var today = new Date();
+ var y = 0;
+ var m = -1;
+ var d = 0;
+ var a = str.split(/\W+/);
+ var b = fmt.match(/%./g);
+ var i = 0, j = 0;
+ var hr = 0;
+ var min = 0;
+ for (i = 0; i < a.length; ++i) {
+ if (!a[i])
+ continue;
+ switch (b[i]) {
+ case "%d":
+ case "%e":
+ d = parseInt(a[i], 10);
+ break;
+
+ case "%m":
+ m = parseInt(a[i], 10) - 1;
+ break;
+
+ case "%Y":
+ case "%y":
+ y = parseInt(a[i], 10);
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
+ break;
+
+ case "%b":
+ case "%B":
+ for (j = 0; j < 12; ++j) {
+ if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
+ }
+ break;
+
+ case "%H":
+ case "%I":
+ case "%k":
+ case "%l":
+ hr = parseInt(a[i], 10);
+ break;
+
+ case "%P":
+ case "%p":
+ if (/pm/i.test(a[i]) && hr < 12)
+ hr += 12;
+ else if (/am/i.test(a[i]) && hr >= 12)
+ hr -= 12;
+ break;
+
+ case "%M":
+ min = parseInt(a[i], 10);
+ break;
+ }
+ }
+ if (isNaN(y)) y = today.getFullYear();
+ if (isNaN(m)) m = today.getMonth();
+ if (isNaN(d)) d = today.getDate();
+ if (isNaN(hr)) hr = today.getHours();
+ if (isNaN(min)) min = today.getMinutes();
+ if (y != 0 && m != -1 && d != 0)
+ return new Date(y, m, d, hr, min, 0);
+ y = 0; m = -1; d = 0;
+ for (i = 0; i < a.length; ++i) {
+ if (a[i].search(/[a-zA-Z]+/) != -1) {
+ var t = -1;
+ for (j = 0; j < 12; ++j) {
+ if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
+ }
+ if (t != -1) {
+ if (m != -1) {
+ d = m+1;
+ }
+ m = t;
+ }
+ } else if (parseInt(a[i], 10) <= 12 && m == -1) {
+ m = a[i]-1;
+ } else if (parseInt(a[i], 10) > 31 && y == 0) {
+ y = parseInt(a[i], 10);
+ (y < 100) && (y += (y > 29) ? 1900 : 2000);
+ } else if (d == 0) {
+ d = a[i];
+ }
+ }
+ if (y == 0)
+ y = today.getFullYear();
+ if (m != -1 && d != 0)
+ return new Date(y, m, d, hr, min, 0);
+ return today;
+};
+
+/** Returns the number of days in the current month */
+Date.prototype.getMonthDays = function(month) {
+ var year = this.getFullYear();
+ if (typeof month == "undefined") {
+ month = this.getMonth();
+ }
+ if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
+ return 29;
+ } else {
+ return Date._MD[month];
+ }
+};
+
+/** Returns the number of day in the year. */
+Date.prototype.getDayOfYear = function() {
+ var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
+ var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
+ var time = now - then;
+ return Math.floor(time / Date.DAY);
+};
+
+/** Returns the number of the week in year, as defined in ISO 8601. */
+Date.prototype.getWeekNumber = function() {
+ var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
+ var DoW = d.getDay();
+ d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
+ var ms = d.valueOf(); // GMT
+ d.setMonth(0);
+ d.setDate(4); // Thu in Week 1
+ return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
+};
+
+/** Checks date and time equality */
+Date.prototype.equalsTo = function(date) {
+ return ((this.getFullYear() == date.getFullYear()) &&
+ (this.getMonth() == date.getMonth()) &&
+ (this.getDate() == date.getDate()) &&
+ (this.getHours() == date.getHours()) &&
+ (this.getMinutes() == date.getMinutes()));
+};
+
+/** Set only the year, month, date parts (keep existing time) */
+Date.prototype.setDateOnly = function(date) {
+ var tmp = new Date(date);
+ this.setDate(1);
+ this.setFullYear(tmp.getFullYear());
+ this.setMonth(tmp.getMonth());
+ this.setDate(tmp.getDate());
+};
+
+/** Prints the date in a string according to the given format. */
+Date.prototype.print = function (str) {
+ var m = this.getMonth();
+ var d = this.getDate();
+ var y = this.getFullYear();
+ var wn = this.getWeekNumber();
+ var w = this.getDay();
+ var s = {};
+ var hr = this.getHours();
+ var pm = (hr >= 12);
+ var ir = (pm) ? (hr - 12) : hr;
+ var dy = this.getDayOfYear();
+ if (ir == 0)
+ ir = 12;
+ var min = this.getMinutes();
+ var sec = this.getSeconds();
+ s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
+ s["%A"] = Calendar._DN[w]; // full weekday name
+ s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
+ s["%B"] = Calendar._MN[m]; // full month name
+ // FIXME: %c : preferred date and time representation for the current locale
+ s["%C"] = 1 + Math.floor(y / 100); // the century number
+ s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
+ s["%e"] = d; // the day of the month (range 1 to 31)
+ // FIXME: %D : american date style: %m/%d/%y
+ // FIXME: %E, %F, %G, %g, %h (man strftime)
+ s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
+ s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
+ s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
+ s["%k"] = hr; // hour, range 0 to 23 (24h format)
+ s["%l"] = ir; // hour, range 1 to 12 (12h format)
+ s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
+ s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
+ s["%n"] = "\n"; // a newline character
+ s["%p"] = pm ? "PM" : "AM";
+ s["%P"] = pm ? "pm" : "am";
+ // FIXME: %r : the time in am/pm notation %I:%M:%S %p
+ // FIXME: %R : the time in 24-hour notation %H:%M
+ s["%s"] = Math.floor(this.getTime() / 1000);
+ s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
+ s["%t"] = "\t"; // a tab character
+ // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
+ s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
+ s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
+ s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN)
+ // FIXME: %x : preferred date representation for the current locale without the time
+ // FIXME: %X : preferred time representation for the current locale without the date
+ s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
+ s["%Y"] = y; // year with the century
+ s["%%"] = "%"; // a literal '%' character
+
+ var re = /%./g;
+ if (!Calendar.is_ie5 && !Calendar.is_khtml)
+ return str.replace(re, function (par) { return s[par] || par; });
+
+ var a = str.match(re);
+ for (var i = 0; i < a.length; i++) {
+ var tmp = s[a[i]];
+ if (tmp) {
+ re = new RegExp(a[i], 'g');
+ str = str.replace(re, tmp);
+ }
+ }
+
+ return str;
+};
+
+Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
+Date.prototype.setFullYear = function(y) {
+ var d = new Date(this);
+ d.__msh_oldSetFullYear(y);
+ if (d.getMonth() != this.getMonth())
+ this.setDate(28);
+ this.__msh_oldSetFullYear(y);
+};
+
+// END: DATE OBJECT PATCHES
+
+
+// global object that remembers the calendar
+window._dynarch_popupCalendar = null;
diff --git a/httemplate/elements/calendar_stripped.js b/httemplate/elements/calendar_stripped.js
new file mode 100644
index 000000000..4fe03f1ea
--- /dev/null
+++ b/httemplate/elements/calendar_stripped.js
@@ -0,0 +1,14 @@
+/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
+ * -----------------------------------------------------------
+ *
+ * The DHTML Calendar, version 1.0 "It is happening again"
+ *
+ * Details and latest version at:
+ * www.dynarch.com/projects/calendar
+ *
+ * This script is developed by Dynarch.com. Visit us at www.dynarch.com.
+ *
+ * This script is distributed under the GNU Lesser General Public License.
+ * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
+ */
+ Calendar=function(firstDayOfWeek,dateStr,onSelected,onClose){this.activeDiv=null;this.currentDateEl=null;this.getDateStatus=null;this.getDateToolTip=null;this.getDateText=null;this.timeout=null;this.onSelected=onSelected||null;this.onClose=onClose||null;this.dragging=false;this.hidden=false;this.minYear=1970;this.maxYear=2050;this.dateFormat=Calendar._TT["DEF_DATE_FORMAT"];this.ttDateFormat=Calendar._TT["TT_DATE_FORMAT"];this.isPopup=true;this.weekNumbers=true;this.firstDayOfWeek=typeof firstDayOfWeek=="number"?firstDayOfWeek:Calendar._FD;this.showsOtherMonths=false;this.dateStr=dateStr;this.ar_days=null;this.showsTime=false;this.time24=true;this.yearStep=2;this.hiliteToday=true;this.multiple=null;this.table=null;this.element=null;this.tbody=null;this.firstdayname=null;this.monthsCombo=null;this.yearsCombo=null;this.hilitedMonth=null;this.activeMonth=null;this.hilitedYear=null;this.activeYear=null;this.dateClicked=false;if(typeof Calendar._SDN=="undefined"){if(typeof Calendar._SDN_len=="undefined")Calendar._SDN_len=3;var ar=new Array();for(var i=8;i>0;){ar[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len);}Calendar._SDN=ar;if(typeof Calendar._SMN_len=="undefined")Calendar._SMN_len=3;ar=new Array();for(var i=12;i>0;){ar[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len);}Calendar._SMN=ar;}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(el){var SL=0,ST=0;var is_div=/^div$/i.test(el.tagName);if(is_div&&el.scrollLeft)SL=el.scrollLeft;if(is_div&&el.scrollTop)ST=el.scrollTop;var r={x:el.offsetLeft-SL,y:el.offsetTop-ST};if(el.offsetParent){var tmp=this.getAbsolutePos(el.offsetParent);r.x+=tmp.x;r.y+=tmp.y;}return r;};Calendar.isRelated=function(el,evt){var related=evt.relatedTarget;if(!related){var type=evt.type;if(type=="mouseover"){related=evt.fromElement;}else if(type=="mouseout"){related=evt.toElement;}}while(related){if(related==el){return true;}related=related.parentNode;}return false;};Calendar.removeClass=function(el,className){if(!(el&&el.className)){return;}var cls=el.className.split(" ");var ar=new Array();for(var i=cls.length;i>0;){if(cls[--i]!=className){ar[ar.length]=cls[i];}}el.className=ar.join(" ");};Calendar.addClass=function(el,className){Calendar.removeClass(el,className);el.className+=" "+className;};Calendar.getElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.currentTarget;while(f.nodeType!=1||/^div$/i.test(f.tagName))f=f.parentNode;return f;};Calendar.getTargetElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.target;while(f.nodeType!=1)f=f.parentNode;return f;};Calendar.stopEvent=function(ev){ev||(ev=window.event);if(Calendar.is_ie){ev.cancelBubble=true;ev.returnValue=false;}else{ev.preventDefault();ev.stopPropagation();}return false;};Calendar.addEvent=function(el,evname,func){if(el.attachEvent){el.attachEvent("on"+evname,func);}else if(el.addEventListener){el.addEventListener(evname,func,true);}else{el["on"+evname]=func;}};Calendar.removeEvent=function(el,evname,func){if(el.detachEvent){el.detachEvent("on"+evname,func);}else if(el.removeEventListener){el.removeEventListener(evname,func,true);}else{el["on"+evname]=null;}};Calendar.createElement=function(type,parent){var el=null;if(document.createElementNS){el=document.createElementNS("http://www.w3.org/1999/xhtml",type);}else{el=document.createElement(type);}if(typeof parent!="undefined"){parent.appendChild(el);}return el;};Calendar._add_evs=function(el){with(Calendar){addEvent(el,"mouseover",dayMouseOver);addEvent(el,"mousedown",dayMouseDown);addEvent(el,"mouseout",dayMouseOut);if(is_ie){addEvent(el,"dblclick",dayMouseDblClick);el.setAttribute("unselectable",true);}}};Calendar.findMonth=function(el){if(typeof el.month!="undefined"){return el;}else if(typeof el.parentNode.month!="undefined"){return el.parentNode;}return null;};Calendar.findYear=function(el){if(typeof el.year!="undefined"){return el;}else if(typeof el.parentNode.year!="undefined"){return el.parentNode;}return null;};Calendar.showMonthsCombo=function(){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var mc=cal.monthsCombo;if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}if(cal.activeMonth){Calendar.removeClass(cal.activeMonth,"active");}var mon=cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];Calendar.addClass(mon,"active");cal.activeMonth=mon;var s=mc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var mcw=mc.offsetWidth;if(typeof mcw=="undefined")mcw=50;s.left=(cd.offsetLeft+cd.offsetWidth-mcw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";};Calendar.showYearsCombo=function(fwd){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var yc=cal.yearsCombo;if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}if(cal.activeYear){Calendar.removeClass(cal.activeYear,"active");}cal.activeYear=null;var Y=cal.date.getFullYear()+(fwd?1:-1);var yr=yc.firstChild;var show=false;for(var i=12;i>0;--i){if(Y>=cal.minYear&&Y<=cal.maxYear){yr.innerHTML=Y;yr.year=Y;yr.style.display="block";show=true;}else{yr.style.display="none";}yr=yr.nextSibling;Y+=fwd?cal.yearStep:-cal.yearStep;}if(show){var s=yc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var ycw=yc.offsetWidth;if(typeof ycw=="undefined")ycw=50;s.left=(cd.offsetLeft+cd.offsetWidth-ycw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";}};Calendar.tableMouseUp=function(ev){var cal=Calendar._C;if(!cal){return false;}if(cal.timeout){clearTimeout(cal.timeout);}var el=cal.activeDiv;if(!el){return false;}var target=Calendar.getTargetElement(ev);ev||(ev=window.event);Calendar.removeClass(el,"active");if(target==el||target.parentNode==el){Calendar.cellClick(el,ev);}var mon=Calendar.findMonth(target);var date=null;if(mon){date=new Date(cal.date);if(mon.month!=date.getMonth()){date.setMonth(mon.month);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}else{var year=Calendar.findYear(target);if(year){date=new Date(cal.date);if(year.year!=date.getFullYear()){date.setFullYear(year.year);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}}with(Calendar){removeEvent(document,"mouseup",tableMouseUp);removeEvent(document,"mouseover",tableMouseOver);removeEvent(document,"mousemove",tableMouseOver);cal._hideCombos();_C=null;return stopEvent(ev);}};Calendar.tableMouseOver=function(ev){var cal=Calendar._C;if(!cal){return;}var el=cal.activeDiv;var target=Calendar.getTargetElement(ev);if(target==el||target.parentNode==el){Calendar.addClass(el,"hilite active");Calendar.addClass(el.parentNode,"rowhilite");}else{if(typeof el.navtype=="undefined"||(el.navtype!=50&&(el.navtype==0||Math.abs(el.navtype)>2)))Calendar.removeClass(el,"active");Calendar.removeClass(el,"hilite");Calendar.removeClass(el.parentNode,"rowhilite");}ev||(ev=window.event);if(el.navtype==50&&target!=el){var pos=Calendar.getAbsolutePos(el);var w=el.offsetWidth;var x=ev.clientX;var dx;var decrease=true;if(x>pos.x+w){dx=x-pos.x-w;decrease=false;}else dx=pos.x-x;if(dx<0)dx=0;var range=el._range;var current=el._current;var count=Math.floor(dx/10)%range.length;for(var i=range.length;--i>=0;)if(range[i]==current)break;while(count-->0)if(decrease){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();}var mon=Calendar.findMonth(target);if(mon){if(mon.month!=cal.date.getMonth()){if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}Calendar.addClass(mon,"hilite");cal.hilitedMonth=mon;}else if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}}else{if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}var year=Calendar.findYear(target);if(year){if(year.year!=cal.date.getFullYear()){if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}Calendar.addClass(year,"hilite");cal.hilitedYear=year;}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}return Calendar.stopEvent(ev);};Calendar.tableMouseDown=function(ev){if(Calendar.getTargetElement(ev)==Calendar.getElement(ev)){return Calendar.stopEvent(ev);}};Calendar.calDragIt=function(ev){var cal=Calendar._C;if(!(cal&&cal.dragging)){return false;}var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posX=ev.pageX;posY=ev.pageY;}cal.hideShowCovered();var st=cal.element.style;st.left=(posX-cal.xOffs)+"px";st.top=(posY-cal.yOffs)+"px";return Calendar.stopEvent(ev);};Calendar.calDragEnd=function(ev){var cal=Calendar._C;if(!cal){return false;}cal.dragging=false;with(Calendar){removeEvent(document,"mousemove",calDragIt);removeEvent(document,"mouseup",calDragEnd);tableMouseUp(ev);}cal.hideShowCovered();};Calendar.dayMouseDown=function(ev){var el=Calendar.getElement(ev);if(el.disabled){return false;}var cal=el.calendar;cal.activeDiv=el;Calendar._C=cal;if(el.navtype!=300)with(Calendar){if(el.navtype==50){el._current=el.innerHTML;addEvent(document,"mousemove",tableMouseOver);}else addEvent(document,Calendar.is_ie5?"mousemove":"mouseover",tableMouseOver);addClass(el,"hilite active");addEvent(document,"mouseup",tableMouseUp);}else if(cal.isPopup){cal._dragStart(ev);}if(el.navtype==-1||el.navtype==1){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout("Calendar.showMonthsCombo()",250);}else if(el.navtype==-2||el.navtype==2){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout((el.navtype>0)?"Calendar.showYearsCombo(true)":"Calendar.showYearsCombo(false)",250);}else{cal.timeout=null;}return Calendar.stopEvent(ev);};Calendar.dayMouseDblClick=function(ev){Calendar.cellClick(Calendar.getElement(ev),ev||window.event);if(Calendar.is_ie){document.selection.empty();}};Calendar.dayMouseOver=function(ev){var el=Calendar.getElement(ev);if(Calendar.isRelated(el,ev)||Calendar._C||el.disabled){return false;}if(el.ttip){if(el.ttip.substr(0,1)=="_"){el.ttip=el.caldate.print(el.calendar.ttDateFormat)+el.ttip.substr(1);}el.calendar.tooltips.innerHTML=el.ttip;}if(el.navtype!=300){Calendar.addClass(el,"hilite");if(el.caldate){Calendar.addClass(el.parentNode,"rowhilite");}}return Calendar.stopEvent(ev);};Calendar.dayMouseOut=function(ev){with(Calendar){var el=getElement(ev);if(isRelated(el,ev)||_C||el.disabled)return false;removeClass(el,"hilite");if(el.caldate)removeClass(el.parentNode,"rowhilite");if(el.calendar)el.calendar.tooltips.innerHTML=_TT["SEL_DATE"];return stopEvent(ev);}};Calendar.cellClick=function(el,ev){var cal=el.calendar;var closing=false;var newdate=false;var date=null;if(typeof el.navtype=="undefined"){if(cal.currentDateEl){Calendar.removeClass(cal.currentDateEl,"selected");Calendar.addClass(el,"selected");closing=(cal.currentDateEl==el);if(!closing){cal.currentDateEl=el;}}cal.date.setDateOnly(el.caldate);date=cal.date;var other_month=!(cal.dateClicked=!el.otherMonth);if(!other_month&&!cal.currentDateEl)cal._toggleMultipleDate(new Date(date));else newdate=!el.disabled;if(other_month)cal._init(cal.firstDayOfWeek,date);}else{if(el.navtype==200){Calendar.removeClass(el,"hilite");cal.callCloseHandler();return;}date=new Date(cal.date);if(el.navtype==0)date.setDateOnly(new Date());cal.dateClicked=false;var year=date.getFullYear();var mon=date.getMonth();function setMonth(m){var day=date.getDate();var max=date.getMonthDays(m);if(day>max){date.setDate(max);}date.setMonth(m);};switch(el.navtype){case 400:Calendar.removeClass(el,"hilite");var text=Calendar._TT["ABOUT"];if(typeof text!="undefined"){text+=cal.showsTime?Calendar._TT["ABOUT_TIME"]:"";}else{text="Help and about box text is not translated into this language.\n"+"If you know this language and you feel generous please update\n"+"the corresponding file in \"lang\" subdir to match calendar-en.js\n"+"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n"+"Thank you!\n"+"http://dynarch.com/mishoo/calendar.epl\n";}alert(text);return;case-2:if(year>cal.minYear){date.setFullYear(year-1);}break;case-1:if(mon>0){setMonth(mon-1);}else if(year-->cal.minYear){date.setFullYear(year);setMonth(11);}break;case 1:if(mon<11){setMonth(mon+1);}else if(year<cal.maxYear){date.setFullYear(year+1);setMonth(0);}break;case 2:if(year<cal.maxYear){date.setFullYear(year+1);}break;case 100:cal.setFirstDayOfWeek(el.fdow);return;case 50:var range=el._range;var current=el.innerHTML;for(var i=range.length;--i>=0;)if(range[i]==current)break;if(ev&&ev.shiftKey){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();return;case 0:if((typeof cal.getDateStatus=="function")&&cal.getDateStatus(date,date.getFullYear(),date.getMonth(),date.getDate())){return false;}break;}if(!date.equalsTo(cal.date)){cal.setDate(date);newdate=true;}else if(el.navtype==0)newdate=closing=true;}if(newdate){ev&&cal.callHandler();}if(closing){Calendar.removeClass(el,"hilite");ev&&cal.callCloseHandler();}};Calendar.prototype.create=function(_par){var parent=null;if(!_par){parent=document.getElementsByTagName("body")[0];this.isPopup=true;}else{parent=_par;this.isPopup=false;}this.date=this.dateStr?new Date(this.dateStr):new Date();var table=Calendar.createElement("table");this.table=table;table.cellSpacing=0;table.cellPadding=0;table.calendar=this;Calendar.addEvent(table,"mousedown",Calendar.tableMouseDown);var div=Calendar.createElement("div");this.element=div;div.className="calendar";if(this.isPopup){div.style.position="absolute";div.style.display="none";}div.appendChild(table);var thead=Calendar.createElement("thead",table);var cell=null;var row=null;var cal=this;var hh=function(text,cs,navtype){cell=Calendar.createElement("td",row);cell.colSpan=cs;cell.className="button";if(navtype!=0&&Math.abs(navtype)<=2)cell.className+=" nav";Calendar._add_evs(cell);cell.calendar=cal;cell.navtype=navtype;cell.innerHTML="<div unselectable='on'>"+text+"</div>";return cell;};row=Calendar.createElement("tr",thead);var title_length=6;(this.isPopup)&&--title_length;(this.weekNumbers)&&++title_length;hh("?",1,400).ttip=Calendar._TT["INFO"];this.title=hh("",title_length,300);this.title.className="title";if(this.isPopup){this.title.ttip=Calendar._TT["DRAG_TO_MOVE"];this.title.style.cursor="move";hh("&#x00d7;",1,200).ttip=Calendar._TT["CLOSE"];}row=Calendar.createElement("tr",thead);row.className="headrow";this._nav_py=hh("&#x00ab;",1,-2);this._nav_py.ttip=Calendar._TT["PREV_YEAR"];this._nav_pm=hh("&#x2039;",1,-1);this._nav_pm.ttip=Calendar._TT["PREV_MONTH"];this._nav_now=hh(Calendar._TT["TODAY"],this.weekNumbers?4:3,0);this._nav_now.ttip=Calendar._TT["GO_TODAY"];this._nav_nm=hh("&#x203a;",1,1);this._nav_nm.ttip=Calendar._TT["NEXT_MONTH"];this._nav_ny=hh("&#x00bb;",1,2);this._nav_ny.ttip=Calendar._TT["NEXT_YEAR"];row=Calendar.createElement("tr",thead);row.className="daynames";if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.className="name wn";cell.innerHTML=Calendar._TT["WK"];}for(var i=7;i>0;--i){cell=Calendar.createElement("td",row);if(!i){cell.navtype=100;cell.calendar=this;Calendar._add_evs(cell);}}this.firstdayname=(this.weekNumbers)?row.firstChild.nextSibling:row.firstChild;this._displayWeekdays();var tbody=Calendar.createElement("tbody",table);this.tbody=tbody;for(i=6;i>0;--i){row=Calendar.createElement("tr",tbody);if(this.weekNumbers){cell=Calendar.createElement("td",row);}for(var j=7;j>0;--j){cell=Calendar.createElement("td",row);cell.calendar=this;Calendar._add_evs(cell);}}if(this.showsTime){row=Calendar.createElement("tr",tbody);row.className="time";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;cell.innerHTML=Calendar._TT["TIME"]||"&nbsp;";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(className,init,range_start,range_end){var part=Calendar.createElement("span",cell);part.className=className;part.innerHTML=init;part.calendar=cal;part.ttip=Calendar._TT["TIME_PART"];part.navtype=50;part._range=[];if(typeof range_start!="number")part._range=range_start;else{for(var i=range_start;i<=range_end;++i){var txt;if(i<10&&range_end>=10)txt='0'+i;else txt=''+i;part._range[part._range.length]=txt;}}Calendar._add_evs(part);return part;};var hrs=cal.date.getHours();var mins=cal.date.getMinutes();var t12=!cal.time24;var pm=(hrs>12);if(t12&&pm)hrs-=12;var H=makeTimePart("hour",hrs,t12?1:0,t12?12:23);var span=Calendar.createElement("span",cell);span.innerHTML=":";span.className="colon";var M=makeTimePart("minute",mins,0,59);var AP=null;cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;if(t12)AP=makeTimePart("ampm",pm?"pm":"am",["am","pm"]);else cell.innerHTML="&nbsp;";cal.onSetTime=function(){var pm,hrs=this.date.getHours(),mins=this.date.getMinutes();if(t12){pm=(hrs>=12);if(pm)hrs-=12;if(hrs==0)hrs=12;AP.innerHTML=pm?"pm":"am";}H.innerHTML=(hrs<10)?("0"+hrs):hrs;M.innerHTML=(mins<10)?("0"+mins):mins;};cal.onUpdateTime=function(){var date=this.date;var h=parseInt(H.innerHTML,10);if(t12){if(/pm/i.test(AP.innerHTML)&&h<12)h+=12;else if(/am/i.test(AP.innerHTML)&&h==12)h=0;}var d=date.getDate();var m=date.getMonth();var y=date.getFullYear();date.setHours(h);date.setMinutes(parseInt(M.innerHTML,10));date.setFullYear(y);date.setMonth(m);date.setDate(d);this.dateClicked=false;this.callHandler();};})();}else{this.onSetTime=this.onUpdateTime=function(){};}var tfoot=Calendar.createElement("tfoot",table);row=Calendar.createElement("tr",tfoot);row.className="footrow";cell=hh(Calendar._TT["SEL_DATE"],this.weekNumbers?8:7,300);cell.className="ttip";if(this.isPopup){cell.ttip=Calendar._TT["DRAG_TO_MOVE"];cell.style.cursor="move";}this.tooltips=cell;div=Calendar.createElement("div",this.element);this.monthsCombo=div;div.className="combo";for(i=0;i<Calendar._MN.length;++i){var mn=Calendar.createElement("div");mn.className=Calendar.is_ie?"label-IEfix":"label";mn.month=i;mn.innerHTML=Calendar._SMN[i];div.appendChild(mn);}div=Calendar.createElement("div",this.element);this.yearsCombo=div;div.className="combo";for(i=12;i>0;--i){var yr=Calendar.createElement("div");yr.className=Calendar.is_ie?"label-IEfix":"label";div.appendChild(yr);}this._init(this.firstDayOfWeek,this.date);parent.appendChild(this.element);};Calendar._keyEvent=function(ev){var cal=window._dynarch_popupCalendar;if(!cal||cal.multiple)return false;(Calendar.is_ie)&&(ev=window.event);var act=(Calendar.is_ie||ev.type=="keypress"),K=ev.keyCode;if(ev.ctrlKey){switch(K){case 37:act&&Calendar.cellClick(cal._nav_pm);break;case 38:act&&Calendar.cellClick(cal._nav_py);break;case 39:act&&Calendar.cellClick(cal._nav_nm);break;case 40:act&&Calendar.cellClick(cal._nav_ny);break;default:return false;}}else switch(K){case 32:Calendar.cellClick(cal._nav_now);break;case 27:act&&cal.callCloseHandler();break;case 37:case 38:case 39:case 40:if(act){var prev,x,y,ne,el,step;prev=K==37||K==38;step=(K==37||K==39)?1:7;function setVars(){el=cal.currentDateEl;var p=el.pos;x=p&15;y=p>>4;ne=cal.ar_days[y][x];};setVars();function prevMonth(){var date=new Date(cal.date);date.setDate(date.getDate()-step);cal.setDate(date);};function nextMonth(){var date=new Date(cal.date);date.setDate(date.getDate()+step);cal.setDate(date);};while(1){switch(K){case 37:if(--x>=0)ne=cal.ar_days[y][x];else{x=6;K=38;continue;}break;case 38:if(--y>=0)ne=cal.ar_days[y][x];else{prevMonth();setVars();}break;case 39:if(++x<7)ne=cal.ar_days[y][x];else{x=0;K=40;continue;}break;case 40:if(++y<cal.ar_days.length)ne=cal.ar_days[y][x];else{nextMonth();setVars();}break;}break;}if(ne){if(!ne.disabled)Calendar.cellClick(ne);else if(prev)prevMonth();else nextMonth();}}break;case 13:if(act)Calendar.cellClick(cal.currentDateEl,ev);break;default:return false;}return Calendar.stopEvent(ev);};Calendar.prototype._init=function(firstDayOfWeek,date){var today=new Date(),TY=today.getFullYear(),TM=today.getMonth(),TD=today.getDate();this.table.style.visibility="hidden";var year=date.getFullYear();if(year<this.minYear){year=this.minYear;date.setFullYear(year);}else if(year>this.maxYear){year=this.maxYear;date.setFullYear(year);}this.firstDayOfWeek=firstDayOfWeek;this.date=new Date(date);var month=date.getMonth();var mday=date.getDate();var no_days=date.getMonthDays();date.setDate(1);var day1=(date.getDay()-this.firstDayOfWeek)%7;if(day1<0)day1+=7;date.setDate(-day1);date.setDate(date.getDate()+1);var row=this.tbody.firstChild;var MN=Calendar._SMN[month];var ar_days=this.ar_days=new Array();var weekend=Calendar._TT["WEEKEND"];var dates=this.multiple?(this.datesCells={}):null;for(var i=0;i<6;++i,row=row.nextSibling){var cell=row.firstChild;if(this.weekNumbers){cell.className="day wn";cell.innerHTML=date.getWeekNumber();cell=cell.nextSibling;}row.className="daysrow";var hasdays=false,iday,dpos=ar_days[i]=[];for(var j=0;j<7;++j,cell=cell.nextSibling,date.setDate(iday+1)){iday=date.getDate();var wday=date.getDay();cell.className="day";cell.pos=i<<4|j;dpos[j]=cell;var current_month=(date.getMonth()==month);if(!current_month){if(this.showsOtherMonths){cell.className+=" othermonth";cell.otherMonth=true;}else{cell.className="emptycell";cell.innerHTML="&nbsp;";cell.disabled=true;continue;}}else{cell.otherMonth=false;hasdays=true;}cell.disabled=false;cell.innerHTML=this.getDateText?this.getDateText(date,iday):iday;if(dates)dates[date.print("%Y%m%d")]=cell;if(this.getDateStatus){var status=this.getDateStatus(date,year,month,iday);if(this.getDateToolTip){var toolTip=this.getDateToolTip(date,year,month,iday);if(toolTip)cell.title=toolTip;}if(status===true){cell.className+=" disabled";cell.disabled=true;}else{if(/disabled/i.test(status))cell.disabled=true;cell.className+=" "+status;}}if(!cell.disabled){cell.caldate=new Date(date);cell.ttip="_";if(!this.multiple&&current_month&&iday==mday&&this.hiliteToday){cell.className+=" selected";this.currentDateEl=cell;}if(date.getFullYear()==TY&&date.getMonth()==TM&&iday==TD){cell.className+=" today";cell.ttip+=Calendar._TT["PART_TODAY"];}if(weekend.indexOf(wday.toString())!=-1)cell.className+=cell.otherMonth?" oweekend":" weekend";}}if(!(hasdays||this.showsOtherMonths))row.className="emptyrow";}this.title.innerHTML=Calendar._MN[month]+", "+year;this.onSetTime();this.table.style.visibility="visible";this._initMultipleDates();};Calendar.prototype._initMultipleDates=function(){if(this.multiple){for(var i in this.multiple){var cell=this.datesCells[i];var d=this.multiple[i];if(!d)continue;if(cell)cell.className+=" selected";}}};Calendar.prototype._toggleMultipleDate=function(date){if(this.multiple){var ds=date.print("%Y%m%d");var cell=this.datesCells[ds];if(cell){var d=this.multiple[ds];if(!d){Calendar.addClass(cell,"selected");this.multiple[ds]=date;}else{Calendar.removeClass(cell,"selected");delete this.multiple[ds];}}}};Calendar.prototype.setDateToolTipHandler=function(unaryFunction){this.getDateToolTip=unaryFunction;};Calendar.prototype.setDate=function(date){if(!date.equalsTo(this.date)){this._init(this.firstDayOfWeek,date);}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date);};Calendar.prototype.setFirstDayOfWeek=function(firstDayOfWeek){this._init(firstDayOfWeek,this.date);this._displayWeekdays();};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(unaryFunction){this.getDateStatus=unaryFunction;};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z;};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat));}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this);}this.hideShowCovered();};Calendar.prototype.destroy=function(){var el=this.element.parentNode;el.removeChild(this.element);Calendar._C=null;window._dynarch_popupCalendar=null;};Calendar.prototype.reparent=function(new_parent){var el=this.element;el.parentNode.removeChild(el);new_parent.appendChild(el);};Calendar._checkCalendar=function(ev){var calendar=window._dynarch_popupCalendar;if(!calendar){return false;}var el=Calendar.is_ie?Calendar.getElement(ev):Calendar.getTargetElement(ev);for(;el!=null&&el!=calendar.element;el=el.parentNode);if(el==null){window._dynarch_popupCalendar.callCloseHandler();return Calendar.stopEvent(ev);}};Calendar.prototype.show=function(){var rows=this.table.getElementsByTagName("tr");for(var i=rows.length;i>0;){var row=rows[--i];Calendar.removeClass(row,"rowhilite");var cells=row.getElementsByTagName("td");for(var j=cells.length;j>0;){var cell=cells[--j];Calendar.removeClass(cell,"hilite");Calendar.removeClass(cell,"active");}}this.element.style.display="block";this.hidden=false;if(this.isPopup){window._dynarch_popupCalendar=this;Calendar.addEvent(document,"keydown",Calendar._keyEvent);Calendar.addEvent(document,"keypress",Calendar._keyEvent);Calendar.addEvent(document,"mousedown",Calendar._checkCalendar);}this.hideShowCovered();};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,"keydown",Calendar._keyEvent);Calendar.removeEvent(document,"keypress",Calendar._keyEvent);Calendar.removeEvent(document,"mousedown",Calendar._checkCalendar);}this.element.style.display="none";this.hidden=true;this.hideShowCovered();};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+"px";s.top=y+"px";this.show();};Calendar.prototype.showAtElement=function(el,opts){var self=this;var p=Calendar.getAbsolutePos(el);if(!opts||typeof opts!="string"){this.showAt(p.x,p.y+el.offsetHeight);return true;}function fixPosition(box){if(box.x<0)box.x=0;if(box.y<0)box.y=0;var cp=document.createElement("div");var s=cp.style;s.position="absolute";s.right=s.bottom=s.width=s.height="0px";document.body.appendChild(cp);var br=Calendar.getAbsolutePos(cp);document.body.removeChild(cp);if(Calendar.is_ie){br.y+=document.body.scrollTop;br.x+=document.body.scrollLeft;}else{br.y+=window.scrollY;br.x+=window.scrollX;}var tmp=box.x+box.width-br.x;if(tmp>0)box.x-=tmp;tmp=box.y+box.height-br.y;if(tmp>0)box.y-=tmp;};this.element.style.display="block";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=self.element.offsetWidth;var h=self.element.offsetHeight;self.element.style.display="none";var valign=opts.substr(0,1);var halign="l";if(opts.length>1){halign=opts.substr(1,1);}switch(valign){case "T":p.y-=h;break;case "B":p.y+=el.offsetHeight;break;case "C":p.y+=(el.offsetHeight-h)/2;break;case "t":p.y+=el.offsetHeight-h;break;case "b":break;}switch(halign){case "L":p.x-=w;break;case "R":p.x+=el.offsetWidth;break;case "C":p.x+=(el.offsetWidth-w)/2;break;case "l":p.x+=el.offsetWidth-w;break;case "r":break;}p.width=w;p.height=h+40;self.monthsCombo.style.display="none";fixPosition(p);self.showAt(p.x,p.y);};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype.setDateFormat=function(str){this.dateFormat=str;};Calendar.prototype.setTtDateFormat=function(str){this.ttDateFormat=str;};Calendar.prototype.parseDate=function(str,fmt){if(!fmt)fmt=this.dateFormat;this.setDate(Date.parseDate(str,fmt));};Calendar.prototype.hideShowCovered=function(){if(!Calendar.is_ie&&!Calendar.is_opera)return;function getVisib(obj){var value=obj.style.visibility;if(!value){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)=="function"){if(!Calendar.is_khtml)value=document.defaultView. getComputedStyle(obj,"").getPropertyValue("visibility");else value='';}else if(obj.currentStyle){value=obj.currentStyle.visibility;}else value='';}return value;};var tags=new Array("applet","iframe","select");var el=this.element;var p=Calendar.getAbsolutePos(el);var EX1=p.x;var EX2=el.offsetWidth+EX1;var EY1=p.y;var EY2=el.offsetHeight+EY1;for(var k=tags.length;k>0;){var ar=document.getElementsByTagName(tags[--k]);var cc=null;for(var i=ar.length;i>0;){cc=ar[--i];p=Calendar.getAbsolutePos(cc);var CX1=p.x;var CX2=cc.offsetWidth+CX1;var CY1=p.y;var CY2=cc.offsetHeight+CY1;if(this.hidden||(CX1>EX2)||(CX2<EX1)||(CY1>EY2)||(CY2<EY1)){if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility=cc.__msh_save_visibility;}else{if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility="hidden";}}}};Calendar.prototype._displayWeekdays=function(){var fdow=this.firstDayOfWeek;var cell=this.firstdayname;var weekend=Calendar._TT["WEEKEND"];for(var i=0;i<7;++i){cell.className="day name";var realday=(i+fdow)%7;if(i){cell.ttip=Calendar._TT["DAY_FIRST"].replace("%s",Calendar._DN[realday]);cell.navtype=100;cell.calendar=this;cell.fdow=realday;Calendar._add_evs(cell);}if(weekend.indexOf(realday.toString())!=-1){Calendar.addClass(cell,"weekend");}cell.innerHTML=Calendar._SDN[(i+fdow)%7];cell=cell.nextSibling;}};Calendar.prototype._hideCombos=function(){this.monthsCombo.style.display="none";this.yearsCombo.style.display="none";};Calendar.prototype._dragStart=function(ev){if(this.dragging){return;}this.dragging=true;var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posY=ev.clientY+window.scrollY;posX=ev.clientX+window.scrollX;}var st=this.element.style;this.xOffs=posX-parseInt(st.left);this.yOffs=posY-parseInt(st.top);with(Calendar){addEvent(document,"mousemove",calDragIt);addEvent(document,"mouseup",calDragEnd);}};Date._MD=new Array(31,28,31,30,31,30,31,31,30,31,30,31);Date.SECOND=1000;Date.MINUTE=60*Date.SECOND;Date.HOUR=60*Date.MINUTE;Date.DAY=24*Date.HOUR;Date.WEEK=7*Date.DAY;Date.parseDate=function(str,fmt){var today=new Date();var y=0;var m=-1;var d=0;var a=str.split(/\W+/);var b=fmt.match(/%./g);var i=0,j=0;var hr=0;var min=0;for(i=0;i<a.length;++i){if(!a[i])continue;switch(b[i]){case "%d":case "%e":d=parseInt(a[i],10);break;case "%m":m=parseInt(a[i],10)-1;break;case "%Y":case "%y":y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);break;case "%b":case "%B":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break;}}break;case "%H":case "%I":case "%k":case "%l":hr=parseInt(a[i],10);break;case "%P":case "%p":if(/pm/i.test(a[i])&&hr<12)hr+=12;else if(/am/i.test(a[i])&&hr>=12)hr-=12;break;case "%M":min=parseInt(a[i],10);break;}}if(isNaN(y))y=today.getFullYear();if(isNaN(m))m=today.getMonth();if(isNaN(d))d=today.getDate();if(isNaN(hr))hr=today.getHours();if(isNaN(min))min=today.getMinutes();if(y!=0&&m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);y=0;m=-1;d=0;for(i=0;i<a.length;++i){if(a[i].search(/[a-zA-Z]+/)!=-1){var t=-1;for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){t=j;break;}}if(t!=-1){if(m!=-1){d=m+1;}m=t;}}else if(parseInt(a[i],10)<=12&&m==-1){m=a[i]-1;}else if(parseInt(a[i],10)>31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);}else if(d==0){d=a[i];}}if(y==0)y=today.getFullYear();if(m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);return today;};Date.prototype.getMonthDays=function(month){var year=this.getFullYear();if(typeof month=="undefined"){month=this.getMonth();}if(((0==(year%4))&&((0!=(year%100))||(0==(year%400))))&&month==1){return 29;}else{return Date._MD[month];}};Date.prototype.getDayOfYear=function(){var now=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var then=new Date(this.getFullYear(),0,0,0,0,0);var time=now-then;return Math.floor(time/Date.DAY);};Date.prototype.getWeekNumber=function(){var d=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var DoW=d.getDay();d.setDate(d.getDate()-(DoW+6)%7+3);var ms=d.valueOf();d.setMonth(0);d.setDate(4);return Math.round((ms-d.valueOf())/(7*864e5))+1;};Date.prototype.equalsTo=function(date){return((this.getFullYear()==date.getFullYear())&&(this.getMonth()==date.getMonth())&&(this.getDate()==date.getDate())&&(this.getHours()==date.getHours())&&(this.getMinutes()==date.getMinutes()));};Date.prototype.setDateOnly=function(date){var tmp=new Date(date);this.setDate(1);this.setFullYear(tmp.getFullYear());this.setMonth(tmp.getMonth());this.setDate(tmp.getDate());};Date.prototype.print=function(str){var m=this.getMonth();var d=this.getDate();var y=this.getFullYear();var wn=this.getWeekNumber();var w=this.getDay();var s={};var hr=this.getHours();var pm=(hr>=12);var ir=(pm)?(hr-12):hr;var dy=this.getDayOfYear();if(ir==0)ir=12;var min=this.getMinutes();var sec=this.getSeconds();s["%a"]=Calendar._SDN[w];s["%A"]=Calendar._DN[w];s["%b"]=Calendar._SMN[m];s["%B"]=Calendar._MN[m];s["%C"]=1+Math.floor(y/100);s["%d"]=(d<10)?("0"+d):d;s["%e"]=d;s["%H"]=(hr<10)?("0"+hr):hr;s["%I"]=(ir<10)?("0"+ir):ir;s["%j"]=(dy<100)?((dy<10)?("00"+dy):("0"+dy)):dy;s["%k"]=hr;s["%l"]=ir;s["%m"]=(m<9)?("0"+(1+m)):(1+m);s["%M"]=(min<10)?("0"+min):min;s["%n"]="\n";s["%p"]=pm?"PM":"AM";s["%P"]=pm?"pm":"am";s["%s"]=Math.floor(this.getTime()/1000);s["%S"]=(sec<10)?("0"+sec):sec;s["%t"]="\t";s["%U"]=s["%W"]=s["%V"]=(wn<10)?("0"+wn):wn;s["%u"]=w+1;s["%w"]=w;s["%y"]=(''+y).substr(2,2);s["%Y"]=y;s["%%"]="%";var re=/%./g;if(!Calendar.is_ie5&&!Calendar.is_khtml)return str.replace(re,function(par){return s[par]||par;});var a=str.match(re);for(var i=0;i<a.length;i++){var tmp=s[a[i]];if(tmp){re=new RegExp(a[i],'g');str=str.replace(re,tmp);}}return str;};Date.prototype.__msh_oldSetFullYear=Date.prototype.setFullYear;Date.prototype.setFullYear=function(y){var d=new Date(this);d.__msh_oldSetFullYear(y);if(d.getMonth()!=this.getMonth())this.setDate(28);this.__msh_oldSetFullYear(y);};window._dynarch_popupCalendar=null; \ No newline at end of file
diff --git a/httemplate/elements/checkboxes-table-name.html b/httemplate/elements/checkboxes-table-name.html
new file mode 100644
index 000000000..31652f330
--- /dev/null
+++ b/httemplate/elements/checkboxes-table-name.html
@@ -0,0 +1,90 @@
+<%doc>
+
+Example:
+
+ include( '/elements/checkboxes-table-name.html',
+
+ ###
+ # required
+ ###
+ 'link_table' => 'table_name',
+
+ 'name_col' => 'name_column',
+ #or
+ 'name_callback' => sub { },
+
+ 'names_list' => [ 'value',
+ 'other value',
+ [ 'complex value' => { 'desc' => "Add'l description",
+ 'note' => '&nbsp;*',
+ }
+ ],
+ ],
+
+ ###
+ # recommended (required?)
+ ###
+ 'source_obj' => $obj,
+ #or?
+ #'source_table' => 'table_name',
+ #'sourcenum' => '4', #current value of primary key in source_table
+ # # (none is okay, just pass it if you have it)
+
+ ###
+ # optional
+ ###
+ 'num_col' => 'col_name' #if column name is different in link_table than
+ #source_table
+ 'link_static' => { 'column' => 'value' },
+
+ )
+
+</%doc>
+
+<% include('checkboxes.html',
+ 'names_list' => $opt{'names_list'},
+ 'checked_callback' => $checked_callback,
+ 'element_name_prefix' => $opt{'link_table'}. '.',
+ )
+%>
+
+<%init>
+
+my( %opt ) = @_;
+
+my @pset = ( 'a'..'z', 'A'..'Z', '0'..'9' );
+
+my $prefix = $opt{prefix}
+ || join('', map $pset[ int(rand $#pset) ], (0..20) );
+
+my( $source_pkey, $sourcenum, $source_obj );
+if ( $opt{'source_obj'} ) {
+
+ $source_obj = $opt{'source_obj'};
+ #$source_table = $source_obj->dbdef_table->table;
+ $source_pkey = $source_obj->dbdef_table->primary_key;
+ $sourcenum = $source_obj->$source_pkey();
+
+} else {
+
+ #$source_obj?
+ $source_pkey = $opt{'source_table'}
+ ? dbdef->table($opt{'source_table'})->primary_key
+ : '';
+ $sourcenum = $opt{'sourcenum'};
+}
+
+$source_pkey = $opt{'num_col'} || $source_pkey;
+
+my $link_static = $opt{'link_static'} || {};
+
+my $checked_callback = sub {
+ my( $cgi, $name ) = @_;
+ qsearchs( $opt{'link_table'}, {
+ $source_pkey => $sourcenum,
+ $opt{'name_col'} => $name,
+ %$link_static,
+ });
+};
+
+</%init>
diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html
new file mode 100644
index 000000000..b6b04d111
--- /dev/null
+++ b/httemplate/elements/checkboxes-table.html
@@ -0,0 +1,129 @@
+%
+%
+% ##
+% # required
+% ##
+% # 'target_table' => 'table_name',
+% # 'link_table' => 'table_name',
+% #
+% # 'name_col' => 'name_column',
+% # #or
+% # 'name_callback' => sub { },
+% #
+% ##
+% # recommended (required?)
+% ##
+% # 'source_obj' => $obj,
+% # #or?
+% # #'source_table' => 'table_name',
+% # #'sourcenum' => '4', #current value of primary key in source_table
+% # # # (none is okay, just pass it if you have it)
+% ##
+% # optional
+% ##
+% # 'disable-able' => 1,
+%
+% my( %opt ) = @_;
+%
+% my $target_pkey = dbdef->table($opt{'target_table'})->primary_key;
+%
+% my( $source_pkey, $sourcenum, $source_obj );
+% if ( $opt{'source_obj'} || $opt{'object'} ) {
+%
+% $source_obj = $opt{'source_obj'} || $opt{'object'};
+% #$source_table = $source_obj->dbdef_table->table;
+% $source_pkey = $source_obj->dbdef_table->primary_key;
+% $sourcenum = $source_obj->$source_pkey();
+%
+% } else {
+%
+% #$source_obj?
+% $source_pkey = $opt{'source_table'}
+% ? dbdef->table($opt{'source_table'})->primary_key
+% : '';
+% $sourcenum = $opt{'sourcenum'};
+% }
+%
+% my $hashref = $opt{'hashref'} || {};
+%
+% my $extra_sql = '';
+%
+% if ( $opt{'agent_virt'} ) {
+% $extra_sql .= ' AND' . $FS::CurrentUser::CurrentUser->agentnums_sql(
+% 'null_right' => $opt{'agent_null_right'}
+% );
+% }
+%
+% if ( $opt{'disable-able'} ) {
+% $hashref->{'disabled'} = '';
+%
+% $extra_sql .= ( $sourcenum && $source_pkey )
+% ? " OR $source_pkey = $sourcenum"
+% : '';
+% }
+%
+%
+% foreach my $target_obj (
+% qsearch({ 'table' => $opt{'target_table'},
+% 'hashref' => $hashref,
+% 'select' => $opt{'target_table'}. '.*',
+% 'addl_from' => "LEFT JOIN $opt{'link_table'} USING ( $target_pkey )",
+% 'extra_sql' => $extra_sql,
+% })
+% ) {
+%
+% my $targetnum = $target_obj->$target_pkey();
+%
+% my $checked;
+% if ( $cgi->param('error') ) {
+%
+% $checked = $cgi->param($target_pkey.$targetnum)
+% ? 'CHECKED'
+% : '';
+%
+% } else {
+%
+% $checked = qsearchs( $opt{'link_table'}, {
+% $source_pkey => $sourcenum,
+% $target_pkey => $targetnum,
+% } )
+% ? 'CHECKED'
+% : ''
+%
+% }
+%
+%
+
+
+ <INPUT TYPE="checkbox" NAME="<% $target_pkey. $targetnum %>" <% $checked %> VALUE="ON">
+% if ( $opt{'target_link'} ) {
+
+
+ <A HREF="<% $opt{'target_link'} %><% $targetnum %>">
+%
+%
+% }
+%
+<% $targetnum %>:
+% if ( $opt{'name_callback'} ) {
+
+
+ <% &{ $opt{'name_callback'} }( $target_obj ) %><% $opt{'target_link'} ? '</A>' : '' %>
+% } else {
+% my $name_col = $opt{'name_col'};
+%
+
+
+ <% $target_obj->$name_col() %><% $opt{'target_link'} ? '</A>' : '' %>
+% }
+% if ( $opt{'disable-able'} ) {
+
+
+ <% $target_obj->disabled =~ /^Y/i ? ' (DISABLED)' : '' %>
+% }
+
+
+ <BR>
+% }
+
+
diff --git a/httemplate/elements/checkboxes.html b/httemplate/elements/checkboxes.html
new file mode 100644
index 000000000..126224538
--- /dev/null
+++ b/httemplate/elements/checkboxes.html
@@ -0,0 +1,103 @@
+<%doc>
+
+Example:
+
+ include( '/elements/checkboxes.html',
+
+ # required
+
+ #? 'name_callback' => sub { },
+
+ 'names_list' => [ 'value',
+ 'other value',
+ [ 'complex value' => { 'desc' => "Add'l description",
+ 'note' => '&nbsp;*',
+ }
+ ],
+ ],
+
+ 'element_name_prefix' => "$link_table.",
+
+ #recommended
+
+ 'checked_callback' => sub { my( $cgi, $name ) = @_; },
+
+ )
+
+</%doc>
+
+<TABLE CELLSPACING=0 CELLPADDING=0>
+
+<TR>
+ <TD COLSPAN=2 ALIGN="center"><FONT SIZE="-1">(
+ <A HREF="javascript:setAll<%$prefix%>(true)">select all</A> |
+ <A HREF="javascript:setAll<%$prefix%>(false)">unselect all</A> |
+ <A HREF="javascript:toggleAll<%$prefix%>()">toggle all</A>
+ )</FONT></TD>
+</TR>
+
+% my $num=0;
+% foreach my $item ( @{ $opt{'names_list'} } ) {
+%
+% my $name = ref($item) ? $item->[0] : $item;
+% ( my $display = $name ) =~ s/ /&nbsp;/g;
+% $display .= $item->[1]{note} if ref($item) && $item->[1]{note};
+% my $desc = ref($item) && $item->[1]{desc} ? $item->[1]{desc} : '';
+%
+% my $callback =
+% ( $cgi->param('error') ? 'error_' : '' ). 'checked_callback';
+% my $checked = &{ $opt{$callback} }( $cgi, $name ) ? 'CHECKED' : '';
+
+ <TR>
+ <TD VALIGN="top">
+ <INPUT TYPE="checkbox" NAME="<% $opt{'element_name_prefix'}. $name %>" <% $checked %> ID="<%$prefix.$num++%>" VALUE="ON">
+ </TD>
+ <TD><% $display %>
+% if ( $desc ) {
+ <BR><FONT SIZE="-2"><% $desc %></FONT>
+% }
+ </TD>
+ </TR>
+
+% }
+
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+
+ function setAll<%$prefix%>(setTo) {
+% for ( 0 .. ($num-1) ) {
+ document.getElementById('<%$prefix.$_%>').checked = setTo;
+% }
+ }
+
+ function toggleAll<%$prefix%>(setTo) {
+% for ( 0 .. ($num-1) ) {
+ var element = document.getElementById('<%$prefix.$_%>');
+ if ( element.checked == true ) {
+ element.checked = false;
+ } else {
+ element.checked = true;
+ }
+% }
+ }
+
+</SCRIPT>
+
+<%init>
+
+my( %opt ) = @_;
+
+my @pset = ( 'a'..'z', 'A'..'Z', '0'..'9' );
+
+my $prefix = $opt{prefix}
+ || join('', map $pset[ int(rand $#pset) ], (0..20) );
+
+$opt{checked_callback} ||= sub {};
+
+$opt{'error_checked_callback'} ||= sub {
+ my( $cgi, $name ) = @_;
+ $cgi->param($opt{'element_name_prefix'}. $name );
+};
+
+</%init>
diff --git a/httemplate/elements/columnend.html b/httemplate/elements/columnend.html
new file mode 100644
index 000000000..021a328e8
--- /dev/null
+++ b/httemplate/elements/columnend.html
@@ -0,0 +1,6 @@
+ </TABLE>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+</TR>
diff --git a/httemplate/elements/columnnext.html b/httemplate/elements/columnnext.html
new file mode 100644
index 000000000..4dfe82fd8
--- /dev/null
+++ b/httemplate/elements/columnnext.html
@@ -0,0 +1,4 @@
+ </TABLE>
+ </TD>
+ <TD VALIGN="top" STYLE="padding-left:12px">
+ <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
diff --git a/httemplate/elements/columnstart.html b/httemplate/elements/columnstart.html
new file mode 100644
index 000000000..0341b274f
--- /dev/null
+++ b/httemplate/elements/columnstart.html
@@ -0,0 +1,6 @@
+<TR>
+ <TD BGCOLOR="#e8e8e8" COLSPAN=99>
+ <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD VALIGN="top">
+ <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
diff --git a/httemplate/elements/cssexpr.js b/httemplate/elements/cssexpr.js
new file mode 100644
index 000000000..c434d8da0
--- /dev/null
+++ b/httemplate/elements/cssexpr.js
@@ -0,0 +1,66 @@
+function constExpression(x) {
+ return x;
+}
+
+function simplifyCSSExpression() {
+ try {
+ var ss,sl, rs, rl;
+ ss = document.styleSheets;
+ sl = ss.length
+
+ for (var i = 0; i < sl; i++) {
+ simplifyCSSBlock(ss[i]);
+ }
+ }
+ catch (exc) {
+ //alert("Got an error while processing css. The page should still work but might be a bit slower");
+ throw exc;
+ }
+}
+
+function simplifyCSSBlock(ss) {
+ var rs, rl;
+
+ for (var i = 0; i < ss.imports.length; i++)
+ simplifyCSSBlock(ss.imports[i]);
+
+ if (ss.cssText.indexOf("expression(constExpression(") == -1)
+ return;
+
+ rs = ss.rules;
+ rl = rs.length;
+ for (var j = 0; j < rl; j++)
+ simplifyCSSRule(rs[j]);
+
+}
+
+function simplifyCSSRule(r) {
+ var str = r.style.cssText;
+ var str2 = str;
+ var lastStr;
+ do {
+ lastStr = str2;
+ str2 = simplifyCSSRuleHelper(lastStr);
+ } while (str2 != lastStr)
+
+ if (str2 != str)
+ r.style.cssText = str2;
+}
+
+function simplifyCSSRuleHelper(str) {
+ var i, i2;
+ i = str.indexOf("expression(constExpression(");
+ if (i == -1) return str;
+ i2 = str.indexOf("))", i);
+ var hd = str.substring(0, i);
+ var tl = str.substring(i2 + 2);
+ var exp = str.substring(i + 27, i2);
+ var val = eval(exp)
+ return hd + val + tl;
+}
+
+if (/msie/i.test(navigator.userAgent) && window.attachEvent != null) {
+ window.attachEvent("onload", function () {
+ simplifyCSSExpression();
+ });
+}
diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html
new file mode 100644
index 000000000..f00419f9c
--- /dev/null
+++ b/httemplate/elements/customer-table.html
@@ -0,0 +1,524 @@
+<%doc>
+
+Example:
+
+ include( '/elements/customer-table.html',
+
+ ###
+ # required
+ ###
+
+ #listrefs...
+ 'header' => [ '#', 'Item' ],
+ 'fields' => [
+ 'column',
+ sub { my ($row,$param) = @_;
+ $param->{"column$row"};
+ },
+ ],
+
+ ###
+ # optional
+ ###
+
+ 'name_singular' => 'customer', #label
+
+ #listrefs
+ 'types' => ['immutable', ''], # immutable or ''/text
+ 'align' => [ 'c', 'l', 'r', '' ],
+ 'size' => [], # sizes ignored for immutable
+ 'color' => [],
+ 'footer' => ['string', '_TOTAL'], # strings or the special
+ #value _TOTAL
+ 'footer_align' => [ 'c', 'l', 'r', '' ],
+
+ 'param' => { column0 => 1 }, # preset column of row 0 to 1
+
+ )
+
+</%doc>
+
+<SCRIPT TYPE="text/javascript">
+
+ function clearhint_custnum() {
+
+ if ( this.value == 'Not found' || this.value == 'Multiple' ) {
+ this.value = '';
+ this.style.color = '#000000';
+ }
+
+ }
+
+ function clearhint_customer() {
+
+ this.style.color = '#000000';
+
+ if ( this.value == '(last name or company)' || this.value == 'Not found' )
+ this.value = '';
+
+ }
+
+ function <% $opt{prefix} %>search_custnum() {
+
+ this.style.color = '#000000'
+
+ var custnum_obj = this;
+ var searchrow = this.getAttribute('rownum');
+ var custnum = this.value;
+
+ if ( custnum == 'searching...' || custnum == 'Not found' || custnum == '' )
+ return;
+
+ if ( this.getAttribute('magic') == 'nosearch' ) {
+ this.setAttribute('magic', '');
+ return;
+ }
+
+ if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) {
+ <% $opt{prefix} %>addRow();
+ }
+ var customer = document.getElementById('customer'+searchrow);
+ customer.value = 'searching...';
+ customer.disabled = true;
+ customer.style.color = '#000000';
+ customer.style.backgroundColor = '#dddddd';
+
+ var customer_select = document.getElementById('cust_select'+searchrow);
+
+ customer.style.display = '';
+ customer_select.style.display = 'none';
+
+ function search_custnum_update(name) {
+
+ var name = eval('(' + name + ')' );
+
+ customer.disabled = false;
+ customer.style.backgroundColor = '#ffffff';
+
+ if ( name.length > 0 ) {
+ customer.value = name;
+ customer.setAttribute('magic', 'nosearch');
+ } else {
+ customer.value = 'Not found';
+ customer.style.color = '#ff0000';
+ custnum_obj.style.color = '#ff0000';
+
+ }
+
+ }
+
+ custnum_search( custnum, search_custnum_update );
+
+ }
+
+ function <% $opt{prefix} %>search_customer() {
+
+ var customer_obj = this;
+ var searchrow = this.getAttribute('rownum');
+ var customer = this.value;
+
+ if ( customer == 'searching...' || customer == 'Not found' || customer == '' )
+ return;
+
+ if ( this.getAttribute('magic') == 'nosearch' ) {
+ this.setAttribute('magic', '');
+ return;
+ }
+
+ if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) {
+ <% $opt{prefix} %>addRow();
+ }
+
+ var custnum_obj = document.getElementById('custnum'+searchrow);
+ custnum_obj.value = 'searching...';
+ custnum_obj.disabled = true;
+ custnum_obj.style.color = '#000000';
+ custnum_obj.style.backgroundColor = '#dddddd';
+
+ var customer_select = document.getElementById('cust_select'+searchrow);
+
+ function search_customer_update(customers) {
+
+ var customerArray = eval('(' + customers + ')');
+
+ custnum_obj.disabled = false;
+ custnum_obj.style.backgroundColor = '#ffffff';
+
+ if ( customerArray.length == 0 ) {
+
+ custnum_obj.value = 'Not found';
+ custnum_obj.style.color = '#ff0000';
+ customer_obj.style.color = '#ff0000';
+
+ customer_obj.style.display = '';
+ customer_select.style.display = 'none';
+
+
+ } else if ( customerArray.length == 1 ) {
+
+ custnum_obj.value = customerArray[0][0];
+ customer_obj.value = customerArray[0][1];
+
+ customer_obj.style.display = '';
+ customer_select.style.display = 'none';
+
+
+ } else {
+
+ custnum_obj.value = 'Multiple'; // or something
+ custnum_obj.style.color = '#ff0000';
+
+ //blank the current list
+ for ( var i = customer_select.length; i >= 0; i-- )
+ customer_select.options[i] = null;
+
+ opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000');
+
+ //add the multiple customers
+ for ( var s = 0; s < customerArray.length; s++ )
+ opt(customer_select, customerArray[s][0], customerArray[s][1], '#000000');
+
+ opt(customer_select, 'cancel', '(Edit search string)', '#000000');
+
+ customer_obj.style.display = 'none';
+
+ customer_select.style.display = '';
+
+ }
+
+ }
+
+ smart_search( customer, search_customer_update );
+
+ }
+
+ function select_customer() {
+
+ var custnum = this.options[this.selectedIndex].value;
+ var customer = this.options[this.selectedIndex].text;
+
+ var searchrow = this.getAttribute('rownum');
+ var custnum_obj = document.getElementById('custnum'+searchrow);
+ var customer_obj = document.getElementById('customer'+searchrow);
+
+ if ( custnum == '' ) {
+
+ } else if ( custnum == 'cancel' ) {
+
+ custnum_obj.value = '';
+ custnum_obj.style.color = '#000000';
+
+ this.style.display = 'none';
+ customer_obj.style.display = '';
+ customer_obj.focus();
+
+ } else {
+
+ custnum_obj.value = custnum;
+ custnum_obj.style.color = '#000000';
+
+ customer_obj.value = customer;
+ customer_obj.style.color = '#000000';
+
+ this.style.display = 'none';
+ customer_obj.style.display = '';
+
+ }
+
+ }
+
+ function opt(what,value,text,color) {
+ var optionName = new Option(text, value, false, false);
+ optionName.style.color = color;
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+</SCRIPT>
+
+<TABLE ID="<% $opt{prefix} %>OneTrueTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+<TR>
+ <TH>Cust #</TH>
+ <TH>Customer</TH>
+% foreach my $header ( @{$opt{header}} ) {
+ <TH><% $header %></TH>
+% }
+</TR>
+% my $row = 0;
+% for ( $row = 0; exists($param->{"custnum$row"}); $row++ ) {
+
+ <TR>
+
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "custnum<% $row %>"
+ ID = "custnum<% $row %>"
+ SIZE = 8
+ MAXLENGTH = 12
+ STYLE = "text-align:right;"
+ VALUE = "<% $param->{"custnum$row"} %>"
+ rownum = "<% $row %>"
+ >
+ <SCRIPT TYPE="text/javascript">
+ var custnum_input<% $row %> = document.getElementById("custnum<% $row %>");
+ custnum_input<% $row %>.onfocus = clearhint_custnum;
+ custnum_input<% $row %>.onchange = <% $opt{prefix} %>search_custnum;
+ </SCRIPT>
+ </TD>
+
+ <TD>
+ <INPUT TYPE="text" NAME="customer<% $row %>" ID="customer<% $row %>" SIZE=64 VALUE="<% $param->{"customer$row"} %>" rownum="<% $row %>">
+ <SCRIPT TYPE="text/javascript">
+ var customer_input<% $row %> = document.getElementById("customer<% $row %>");
+ customer_input<% $row %>.onfocus = clearhint_customer;
+ customer_input<% $row %>.onclick = clearhint_customer;
+ customer_input<% $row %>.onchange = <% $opt{prefix} %>search_customer;
+ </SCRIPT>
+ <SELECT NAME="cust_select<% $row %>" ID="cust_select<% $row %>" rownum="<% $row %>" STYLE="color:#ff0000; display:none">
+ </SELECT>
+ <SCRIPT TYPE="text/javascript">
+ var customer_select<% $row %> = document.getElementById("cust_select<% $row %>");
+ customer_select<% $row %>.onchange = select_customer;
+ </SCRIPT>
+ </TD>
+
+% my $col = 0;
+% foreach my $field ( @{$opt{fields}} ) {
+% my $value;
+% if ( ref($field) eq 'CODE' ) {
+% $value = &{$field}($row,$param);
+% } else {
+% $value = $param->{"$field$row"};
+% }
+% my $name = (ref($field) eq 'CODE') ? "column${col}_$row" : "$field$row";
+% my $align = $align{ $opt{align}->[$col] || 'l' };
+% my $size = $sizes->[$col] || 10;
+% my $color = $opt{color}->[$col];
+% my $font = $color ? qq(<FONT COLOR="$color">) : '';
+% my $onchange = '';
+% if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+% $total[$col] += $value;
+% $onchange = $opt{prefix}. "calc_total$col();";
+% $onchange = qq(onchange="$onchange" onkeyup="$onchange");
+% }
+ <TD ALIGN="<% $align %>">
+% if (! $types->[$col] || $types->[$col] eq 'text') {
+ <INPUT TYPE = "text"
+ NAME = "<% $name %>"
+ ID = "<% $name %>"
+ SIZE = "<% $size %>"
+ STYLE = "text-align: <% $align %>;"
+ VALUE = "<% $value %>"
+ <% $onchange %>
+ >
+% } elsif ($types->[$col] eq 'immutable') {
+ <% $font %><% $value %><% $font ? '</FONT>' : '' %>
+ <INPUT TYPE="hidden" NAME="<% $name %>" VALUE="<% $value %>" >
+% } else {
+ Cannot represent unknown type: <% $types->[$col] %>
+% }
+ </TD>
+% $col++;
+% }
+
+ </TR>
+% }
+
+<TR>
+ <TH COLSPAN=2 ID="<% $opt{'prefix'} %>_TOTAL_TOTAL">
+ Total <% $row ? $row-1 : 0 %>
+ <% PL($opt{name_singular} || 'customer', ( $row ? $row-1 : 0 ) ) %>
+ </TH>
+% my $col = 0;
+% foreach my $footer ( @{$opt{footer}} ) {
+% my $align = $align{ $opt{'footer_align'}->[$col] || 'c' };
+% if ($footer eq '_TOTAL' ) {
+% my $id = $opt{'fields'}->[$col];
+% $id = ref($id) ? "column${col}_TOTAL" : "${id}_TOTAL";
+ <TH ALIGN="<% $align %>" ID="<% $id %>">&nbsp;<% sprintf('%.2f', $total[$col] ) %></TH>
+% } else {
+ <TH ALIGN="<% $align %>"><% $footer %></TH>
+% }
+% $col++;
+% }
+</TR>
+
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+% my $col = 0;
+% foreach my $footer ( @{$opt{footer}} ) {
+% if ($footer eq '_TOTAL' ) {
+% my $name = $opt{fields}->[$col];
+% $name = ref($name) ? "column$col" : $name;
+ var <% $opt{prefix}.$name %>_CACHE = new Array ();
+ var <% $opt{prefix} %>th_el = document.getElementById("<%$name%>_TOTAL");
+ function <% $opt{prefix} %>calc_total<% $col %>() {
+ var row = 0;
+ var total = 0;
+ for ( var row = 0;
+
+ ( <% $opt{prefix}.$name%>_CACHE[row] =
+ <% $opt{prefix}.$name%>_CACHE[row]
+ || document.getElementById("<%$name%>"+row)
+ ) != null;
+
+ row++
+ )
+ {
+ var value = <%$name%>_CACHE[row].value;
+ value = parseFloat(value);
+ if ( ! isNaN(value) ) {
+ total = total + value;
+ }
+ }
+ <% $opt{prefix} %>th_el.innerHTML = '&nbsp;' + total.toFixed(2);
+
+ }
+% }
+% $col++;
+% }
+</SCRIPT>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi',
+ 'subs' => [qw( custnum_search smart_search )],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ var <% $opt{prefix} %>total_el =
+ document.getElementById("<% $opt{'prefix'} %>_TOTAL_TOTAL");
+
+ var <% $opt{prefix} %>rownum = <% $row %>;
+
+ function <% $opt{prefix} %>addRow() {
+
+ var table = document.getElementById('<% $opt{prefix} %>OneTrueTable');
+ var tablebody = table.getElementsByTagName('tbody').item(0);
+
+ var row = table.insertRow(rownum+1);
+
+ var custnum_cell = document.createElement('TD');
+
+ var custnum_input = document.createElement('INPUT');
+ custnum_input.setAttribute('name', 'custnum'+<% $opt{prefix} %>rownum);
+ custnum_input.setAttribute('id', 'custnum'+<% $opt{prefix} %>rownum);
+ custnum_input.style.textAlign = 'right';
+ custnum_input.setAttribute('size', 8);
+ custnum_input.setAttribute('maxlength', 12);
+ custnum_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
+ custnum_input.onfocus = clearhint_custnum;
+ custnum_input.onchange = <% $opt{prefix} %>search_custnum;
+ custnum_cell.appendChild(custnum_input);
+
+ row.appendChild(custnum_cell);
+
+ var customer_cell = document.createElement('TD');
+
+ var customer_input = document.createElement('INPUT');
+ customer_input.setAttribute('name', 'customer'+<% $opt{prefix} %>rownum);
+ customer_input.setAttribute('id', 'customer'+<% $opt{prefix} %>rownum);
+ customer_input.setAttribute('size', 64);
+ customer_input.setAttribute('value', '(last name or company)' );
+ customer_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
+ customer_input.onfocus = clearhint_customer;
+ customer_input.onclick = clearhint_customer;
+ customer_input.onchange = <% $opt{prefix} %>search_customer;
+ customer_cell.appendChild(customer_input);
+
+ var customer_select = document.createElement('SELECT');
+ customer_select.setAttribute('name', 'cust_select'+<% $opt{prefix} %>rownum);
+ customer_select.setAttribute('id', 'cust_select'+<% $opt{prefix} %>rownum);
+ customer_select.setAttribute('rownum', <% $opt{prefix} %>rownum);
+ customer_select.style.color = '#ff0000';
+ customer_select.style.display = 'none';
+ customer_select.onchange = select_customer;
+ customer_cell.appendChild(customer_select);
+
+ row.appendChild(customer_cell);
+
+% my $col = 0;
+% foreach my $field ( @{$opt{fields}} ) {
+
+ var my_cell = document.createElement('TD');
+ my_cell.setAttribute('align', '<% $align{ $opt{align}->[$col] || 'l' } %>');
+
+% if ($types->[$col] eq 'immutable') {
+% my $value;
+% if ( ref($field) eq 'CODE' ) {
+% $value = &{$field}($row,$param);
+% } else {
+% $value = $param->{"$field$row"};
+% }
+ var my_text = document.createTextNode('<% $value %>');
+ my_cell.appendChild(my_text);
+% }
+
+ var my_input = document.createElement('INPUT');
+ my_input.setAttribute('name', '<% $field %>'+<% $opt{prefix} %>rownum);
+ my_input.setAttribute('id', '<% $field %>'+<% $opt{prefix} %>rownum);
+ my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>';
+ my_input.setAttribute('size', <% $sizes->[$col] || 10 %>);
+% if ($types->[$col] eq 'immutable') {
+ my_input.setAttribute('type', 'hidden');
+% }
+% if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+ my_input.onchange = <% $opt{prefix} %>calc_total<%$col%>;
+ my_input.onkeyup = <% $opt{prefix} %>calc_total<%$col%>;
+% }
+ my_cell.appendChild(my_input);
+
+ row.appendChild(my_cell);
+
+% $col++;
+% }
+
+ //update the total # of rows display
+ if ( <% $opt{prefix} %>rownum == 1 ) {
+ <% $opt{prefix} %>total_el.innerHTML =
+ 'Total '
+ + <% $opt{prefix} %>rownum
+ + ' <% $opt{name_singular} || 'customer' %>';
+ } else {
+ <% $opt{prefix} %>total_el.innerHTML =
+ 'Total '
+ + <% $opt{prefix} %>rownum
+ + ' <% PL($opt{name_singular} || 'customer') %>';
+ }
+
+ <% $opt{prefix} %>rownum++;
+
+ }
+
+% unless ($cgi->param('error')) {
+ <% $opt{prefix} %>addRow();
+% }
+</SCRIPT>
+
+<%init>
+
+my(%opt) = @_;
+
+$opt{prefix} = '' unless defined $opt{prefix};
+$opt{prefix} .= '_' if $opt{prefix};
+
+my $types = $opt{'types'} ? [ @{$opt{'types'}} ] : [];
+my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
+
+my $param = $opt{param};
+$param = $cgi->Vars if $cgi->param('error');
+
+$opt{$_} ||= [] foreach qw(align color footer footer_align);
+
+my @total = map 0, @{$opt{footer}};
+
+my %align = (
+ 'l' => 'left',
+ 'r' => 'right',
+ 'c' => 'center',
+);
+
+</%init>
diff --git a/httemplate/elements/dashboard-toplist.html b/httemplate/elements/dashboard-toplist.html
new file mode 100644
index 000000000..d8cd7f306
--- /dev/null
+++ b/httemplate/elements/dashboard-toplist.html
@@ -0,0 +1,113 @@
+% if ( $conf->exists('dashboard-toplist') ) {
+
+ <% include('/elements/table-grid.html') %>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = $bgcolor2;
+
+% foreach my $line ( $conf->config('dashboard-toplist') ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+% if ( $line =~ /^\s*cust_main:\s*(\d+)\s*$/ ) { #customer line
+% my $custnum = $1;
+% my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+% if ( $cust_main ) {
+
+ <TR>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF="view/cust_main.cgi?<% $custnum %>"><% $cust_main->name %></A>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% include('/elements/mcp_lint.html', 'cust_main'=>$cust_main) %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
+ <FONT SIZE="-1"><A HREF="<% FS::TicketSystem->href_new_ticket($cust_main, join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ) ) %>">(new ticket)</A></FONT>
+ </TD>
+
+% foreach my $priority ( @custom_priorities, '' ) {
+% my $num =
+% FS::TicketSystem->num_customer_tickets($custnum,$priority);
+% my $ahref = '';
+% $ahref= '<A HREF="'.
+% FS::TicketSystem->href_customer_tickets($custnum,$priority).
+% '">'
+% if $num;
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
+ <% $ahref.$num %></A>
+ </TD>
+% }
+ </TR>
+
+% } else {
+
+ <TR>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ Unknown customer number <% $custnum %>
+ </TD>
+ </TR>
+
+% }
+%
+% } elsif ( $line =~ /^\-\-+$/ ) { #divider
+%
+ <TR>
+ <TH CLASS="grid" COLSPAN="<% scalar(@custom_priorities) + 4 %>"></TH>
+ </TR>
+
+% next;
+%
+% } elsif ( $line =~ /^\s*$/ ) {
+
+ <TR>
+ <TD CLASS="grid" COLSPAN="<% scalar(@custom_priorities) + 4 %>" BGCOLOR="<% $bgcolor %>">&nbsp;</TD>
+ </TR>
+
+% } elsif ( $line =~ /^\S/ ) { #label line
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% $line %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Lint</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+% foreach my $priority ( @custom_priorities, '' ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <% $priority || '<i>(none)</i>'%>
+ </TH>
+% }
+ </TR>
+
+% } else { #regular line
+
+ <TR>
+ <TD CLASS="grid" COLSPAN="<% scalar(@custom_priorities) + 4 %>" BGCOLOR="<% $bgcolor %>"><% $line %></TD>
+ </TR>
+
+% }
+
+%
+% }
+
+ </TABLE>
+ <BR>
+
+% }
+<%init>
+
+my $conf = new FS::Conf;
+
+#false laziness w/httemplate/search/cust_main.cgi... care if
+# custom_priority_field becomes anything but a local hack...
+my @custom_priorities = ();
+if ( $conf->config('ticket_system-custom_priority_field')
+ && @{[ $conf->config('ticket_system-custom_priority_field-values') ]} ) {
+ @custom_priorities =
+ $conf->config('ticket_system-custom_priority_field-values');
+}
+
+</%init>
diff --git a/httemplate/elements/error.html b/httemplate/elements/error.html
new file mode 100644
index 000000000..f467de2a3
--- /dev/null
+++ b/httemplate/elements/error.html
@@ -0,0 +1,4 @@
+% if ( $cgi->param('error') ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $cgi->param('error') |h %></FONT>
+ <BR><BR>
+% }
diff --git a/httemplate/elements/errorpage.html b/httemplate/elements/errorpage.html
new file mode 100644
index 000000000..76a0bf32e
--- /dev/null
+++ b/httemplate/elements/errorpage.html
@@ -0,0 +1,11 @@
+<% include("/elements/header.html", "Error") %>
+
+% while (@_) {
+
+<P><FONT SIZE="+1" COLOR="#ff0000"><% shift |h %></FONT>
+
+%}
+
+% $m->flush_buffer();
+% $HTML::Mason::Commands::m->abort();
+% #die "shouldn't fall through to here (mason \$m->abort didn't)";
diff --git a/httemplate/elements/fckeditor/editor/css/behaviors/disablehandles.htc b/httemplate/elements/fckeditor/editor/css/behaviors/disablehandles.htc
new file mode 100644
index 000000000..8dfb661de
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/behaviors/disablehandles.htc
@@ -0,0 +1,15 @@
+<public:component lightweight="true">
+
+<script language="javascript">
+
+function CancelEvent()
+{
+ return false ;
+}
+
+this.onresizestart = CancelEvent ;
+this.onbeforeeditfocus = CancelEvent ;
+
+</script>
+
+</public:component>
diff --git a/httemplate/elements/fckeditor/editor/css/behaviors/showtableborders.htc b/httemplate/elements/fckeditor/editor/css/behaviors/showtableborders.htc
new file mode 100644
index 000000000..77418b9ec
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/behaviors/showtableborders.htc
@@ -0,0 +1,36 @@
+<public:component lightweight="true">
+
+<public:attach event="oncontentready" onevent="ShowBorders()" />
+<public:attach event="onpropertychange" onevent="OnPropertyChange()" />
+
+<script language="javascript">
+
+var oClassRegex = /\s*FCK__ShowTableBorders/ ;
+
+function ShowBorders()
+{
+ if ( this.border == 0 )
+ {
+ if ( !oClassRegex.test( this.className ) )
+ this.className += ' FCK__ShowTableBorders' ;
+ }
+ else
+ {
+ if ( oClassRegex.test( this.className ) )
+ {
+ this.className = this.className.replace( oClassRegex, '' ) ;
+ if ( this.className.length == 0 )
+ this.removeAttribute( 'className', 0 ) ;
+ }
+ }
+}
+
+function OnPropertyChange()
+{
+ if ( event.propertyName == 'border' || event.propertyName == 'className' )
+ ShowBorders.call(this) ;
+}
+
+</script>
+
+</public:component>
diff --git a/httemplate/elements/fckeditor/editor/css/fck_editorarea.css b/httemplate/elements/fckeditor/editor/css/fck_editorarea.css
new file mode 100644
index 000000000..8539aa414
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/fck_editorarea.css
@@ -0,0 +1,91 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the default CSS file used by the editor area. It defines the
+ * initial font of the editor and background color.
+ *
+ * A user can configure the editor to use another CSS file. Just change
+ * the value of the FCKConfig.EditorAreaCSS key in the configuration
+ * file.
+ */
+
+/*
+ The "body" styles should match your editor web site, mainly regarding
+ background color and font family and size.
+*/
+
+body
+{
+ background-color: #ffffff;
+ padding: 5px 5px 5px 5px;
+ margin: 0px;
+}
+
+body, td
+{
+ font-family: Arial, Verdana, Sans-Serif;
+ font-size: 12px;
+}
+
+a[href]
+{
+ color: #0000FF !important; /* For Firefox... mark as important, otherwise it becomes black */
+}
+
+/*
+ Just uncomment the following block if you want to avoid spaces between
+ paragraphs. Remember to apply the same style in your output front end page.
+*/
+
+/*
+p, ul, li
+{
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+*/
+
+/*
+ The following are some sample styles used in the "Styles" toolbar command.
+ You should instead remove them, and include the styles used by the site
+ you are using the editor in.
+*/
+
+.Bold
+{
+ font-weight: bold;
+}
+
+.Title
+{
+ font-weight: bold;
+ font-size: 18px;
+ color: #cc3300;
+}
+
+.Code
+{
+ border: #8b4513 1px solid;
+ padding-right: 5px;
+ padding-left: 5px;
+ color: #000066;
+ font-family: 'Courier New' , Monospace;
+ background-color: #ff9933;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/css/fck_internal.css b/httemplate/elements/fckeditor/editor/css/fck_internal.css
new file mode 100644
index 000000000..e6865602c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/fck_internal.css
@@ -0,0 +1,111 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This CSS Style Sheet defines rules used by the editor for its internal use.
+ */
+
+/* Fix to allow putting the caret at the end of the
+content in Firefox if clicking below the content */
+html
+{
+ min-height: 100%;
+}
+
+
+table.FCK__ShowTableBorders, table.FCK__ShowTableBorders td, table.FCK__ShowTableBorders th
+{
+ border: #d3d3d3 1px solid;
+}
+
+form
+{
+ border: 1px dotted #FF0000;
+ padding: 2px;
+}
+
+.FCK__Flash
+{
+ border: #a9a9a9 1px solid;
+ background-position: center center;
+ background-image: url(images/fck_flashlogo.gif);
+ background-repeat: no-repeat;
+ width: 80px;
+ height: 80px;
+}
+
+/* Empty anchors images */
+.FCK__Anchor
+{
+ border: 1px dotted #00F;
+ background-position: center center;
+ background-image: url(images/fck_anchor.gif);
+ background-repeat: no-repeat;
+ width: 16px;
+ height: 15px;
+ vertical-align: middle;
+}
+
+/* Anchors with content */
+.FCK__AnchorC
+{
+ border: 1px dotted #00F;
+ background-position: 1px center;
+ background-image: url(images/fck_anchor.gif);
+ background-repeat: no-repeat;
+ padding-left: 18px;
+}
+
+/* Any anchor for non-IE, if we combine it
+ with the previous rule IE ignores all. */
+a[name]
+{
+ border: 1px dotted #00F;
+ background-position: 0 center;
+ background-image: url(images/fck_anchor.gif);
+ background-repeat: no-repeat;
+ padding-left: 18px;
+}
+
+.FCK__PageBreak
+{
+ background-position: center center;
+ background-image: url(images/fck_pagebreak.gif);
+ background-repeat: no-repeat;
+ clear: both;
+ display: block;
+ float: none;
+ width: 100%;
+ border-top: #999999 1px dotted;
+ border-bottom: #999999 1px dotted;
+ border-right: 0px;
+ border-left: 0px;
+ height: 5px;
+}
+
+/* Hidden fields */
+.FCK__InputHidden
+{
+ width: 19px;
+ height: 18px;
+ background-image: url(images/fck_hiddenfield.gif);
+ background-repeat: no-repeat;
+ vertical-align: text-bottom;
+ background-position: center center;
+}
diff --git a/httemplate/elements/fckeditor/editor/css/fck_showtableborders_gecko.css b/httemplate/elements/fckeditor/editor/css/fck_showtableborders_gecko.css
new file mode 100644
index 000000000..5947114c9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/fck_showtableborders_gecko.css
@@ -0,0 +1,42 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This CSS Style Sheet defines the rules to show table borders on Gecko.
+ */
+
+/* For tables with the "border" attribute set to "0" */
+table[border="0"],
+table[border="0"] > tr > td, table[border="0"] > tr > th,
+table[border="0"] > tbody > tr > td, table[border="0"] > tbody > tr > th,
+table[border="0"] > thead > tr > td, table[border="0"] > thead > tr > th,
+table[border="0"] > tfoot > tr > td, table[border="0"] > tfoot > tr > th
+{
+ border: #d3d3d3 1px dotted ;
+}
+
+/* For tables with no "border" attribute set */
+table:not([border]),
+table:not([border]) > tr > td, table:not([border]) > tr > th,
+table:not([border]) > tbody > tr > td, table:not([border]) > tbody > tr > th,
+table:not([border]) > thead > tr > td, table:not([border]) > thead > tr > th,
+table:not([border]) > tfoot > tr > td, table:not([border]) > tfoot > tr > th
+{
+ border: #d3d3d3 1px dotted ;
+}
diff --git a/httemplate/elements/fckeditor/editor/css/images/fck_anchor.gif b/httemplate/elements/fckeditor/editor/css/images/fck_anchor.gif
new file mode 100644
index 000000000..5aa797b22
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/images/fck_anchor.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/css/images/fck_flashlogo.gif b/httemplate/elements/fckeditor/editor/css/images/fck_flashlogo.gif
new file mode 100644
index 000000000..141aac4ed
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/images/fck_flashlogo.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/css/images/fck_hiddenfield.gif b/httemplate/elements/fckeditor/editor/css/images/fck_hiddenfield.gif
new file mode 100644
index 000000000..953f643b6
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/images/fck_hiddenfield.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/css/images/fck_pagebreak.gif b/httemplate/elements/fckeditor/editor/css/images/fck_pagebreak.gif
new file mode 100644
index 000000000..8d1cffd64
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/css/images/fck_pagebreak.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.css b/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.css
new file mode 100644
index 000000000..c1db11468
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.css
@@ -0,0 +1,83 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the CSS file used for interface details in some dialog
+ * windows.
+ */
+
+.ImagePreviewArea
+{
+ border: #000000 1px solid;
+ overflow: auto;
+ width: 100%;
+ height: 170px;
+ background-color: #ffffff;
+}
+
+.FlashPreviewArea
+{
+ border: #000000 1px solid;
+ padding: 5px;
+ overflow: auto;
+ width: 100%;
+ height: 170px;
+ background-color: #ffffff;
+}
+
+.BtnReset
+{
+ float: left;
+ background-position: center center;
+ background-image: url(images/reset.gif);
+ width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ border: 1px none;
+ font-size: 1px ;
+}
+
+.BtnLocked, .BtnUnlocked
+{
+ float: left;
+ background-position: center center;
+ background-image: url(images/locked.gif);
+ width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ border: none 1px;
+ font-size: 1px ;
+}
+
+.BtnUnlocked
+{
+ background-image: url(images/unlocked.gif);
+}
+
+.BtnOver
+{
+ border: outset 1px;
+ cursor: pointer;
+ cursor: hand;
+}
+
+.FCK__FieldNumeric
+{
+ behavior: url(common/fcknumericfield.htc) ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.js b/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.js
new file mode 100644
index 000000000..26b562806
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/fck_dialog_common.js
@@ -0,0 +1,154 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Useful functions used by almost all dialog window pages.
+ */
+
+var GECKO_BOGUS = '<br type="_moz">' ;
+
+// Gets a element by its Id. Used for shorter coding.
+function GetE( elementId )
+{
+ return document.getElementById( elementId ) ;
+}
+
+function ShowE( element, isVisible )
+{
+ if ( typeof( element ) == 'string' )
+ element = GetE( element ) ;
+ element.style.display = isVisible ? '' : 'none' ;
+}
+
+function SetAttribute( element, attName, attValue )
+{
+ if ( attValue == null || attValue.length == 0 )
+ element.removeAttribute( attName, 0 ) ; // 0 : Case Insensitive
+ else
+ element.setAttribute( attName, attValue, 0 ) ; // 0 : Case Insensitive
+}
+
+function GetAttribute( element, attName, valueIfNull )
+{
+ var oAtt = element.attributes[attName] ;
+
+ if ( oAtt == null || !oAtt.specified )
+ return valueIfNull ? valueIfNull : '' ;
+
+ var oValue = element.getAttribute( attName, 2 ) ;
+
+ if ( oValue == null )
+ oValue = oAtt.nodeValue ;
+
+ return ( oValue == null ? valueIfNull : oValue ) ;
+}
+
+// Functions used by text fiels to accept numbers only.
+function IsDigit( e )
+{
+ if ( !e )
+ e = event ;
+
+ var iCode = ( e.keyCode || e.charCode ) ;
+
+ return (
+ ( iCode >= 48 && iCode <= 57 ) // Numbers
+ || (iCode >= 37 && iCode <= 40) // Arrows
+ || iCode == 8 // Backspace
+ || iCode == 46 // Delete
+ ) ;
+}
+
+String.prototype.Trim = function()
+{
+ return this.replace( /(^\s*)|(\s*$)/g, '' ) ;
+}
+
+String.prototype.StartsWith = function( value )
+{
+ return ( this.substr( 0, value.length ) == value ) ;
+}
+
+String.prototype.Remove = function( start, length )
+{
+ var s = '' ;
+
+ if ( start > 0 )
+ s = this.substring( 0, start ) ;
+
+ if ( start + length < this.length )
+ s += this.substring( start + length , this.length ) ;
+
+ return s ;
+}
+
+String.prototype.ReplaceAll = function( searchArray, replaceArray )
+{
+ var replaced = this ;
+
+ for ( var i = 0 ; i < searchArray.length ; i++ )
+ {
+ replaced = replaced.replace( searchArray[i], replaceArray[i] ) ;
+ }
+
+ return replaced ;
+}
+
+function OpenFileBrowser( url, width, height )
+{
+ // oEditor must be defined.
+
+ var iLeft = ( oEditor.FCKConfig.ScreenWidth - width ) / 2 ;
+ var iTop = ( oEditor.FCKConfig.ScreenHeight - height ) / 2 ;
+
+ var sOptions = "toolbar=no,status=no,resizable=yes,dependent=yes,scrollbars=yes" ;
+ sOptions += ",width=" + width ;
+ sOptions += ",height=" + height ;
+ sOptions += ",left=" + iLeft ;
+ sOptions += ",top=" + iTop ;
+
+ // The "PreserveSessionOnFileBrowser" because the above code could be
+ // blocked by popup blockers.
+ if ( oEditor.FCKConfig.PreserveSessionOnFileBrowser && oEditor.FCKBrowserInfo.IsIE )
+ {
+ // The following change has been made otherwise IE will open the file
+ // browser on a different server session (on some cases):
+ // http://support.microsoft.com/default.aspx?scid=kb;en-us;831678
+ // by Simone Chiaretta.
+ var oWindow = oEditor.window.open( url, 'FCKBrowseWindow', sOptions ) ;
+
+ if ( oWindow )
+ {
+ // Detect Yahoo popup blocker.
+ try
+ {
+ var sTest = oWindow.name ; // Yahoo returns "something", but we can't access it, so detect that and avoid strange errors for the user.
+ oWindow.opener = window ;
+ }
+ catch(e)
+ {
+ alert( oEditor.FCKLang.BrowseServerBlocked ) ;
+ }
+ }
+ else
+ alert( oEditor.FCKLang.BrowseServerBlocked ) ;
+ }
+ else
+ window.open( url, 'FCKBrowseWindow', sOptions ) ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/fcknumericfield.htc b/httemplate/elements/fckeditor/editor/dialog/common/fcknumericfield.htc
new file mode 100644
index 000000000..74f26d0d2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/fcknumericfield.htc
@@ -0,0 +1,24 @@
+<public:component lightweight="true">
+
+<script language="javascript">
+
+function CheckIsDigit()
+{
+ var iCode = event.keyCode ;
+
+ event.returnValue =
+ (
+ ( iCode >= 48 && iCode <= 57 ) // Numbers
+ || (iCode >= 37 && iCode <= 40) // Arrows
+ || iCode == 8 // Backspace
+ || iCode == 46 // Delete
+ ) ;
+
+ return event.returnValue ;
+}
+
+this.onkeypress = CheckIsDigit ;
+
+</script>
+
+</public:component>
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/images/locked.gif b/httemplate/elements/fckeditor/editor/dialog/common/images/locked.gif
new file mode 100644
index 000000000..ea0787002
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/images/locked.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/images/reset.gif b/httemplate/elements/fckeditor/editor/dialog/common/images/reset.gif
new file mode 100644
index 000000000..5e9a2fcb3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/images/reset.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/images/unlocked.gif b/httemplate/elements/fckeditor/editor/dialog/common/images/unlocked.gif
new file mode 100644
index 000000000..801e423c7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/images/unlocked.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/common/moz-bindings.xml b/httemplate/elements/fckeditor/editor/dialog/common/moz-bindings.xml
new file mode 100644
index 000000000..a45757730
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/common/moz-bindings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<bindings xmlns="http://www.mozilla.org/xbl">
+ <binding id="numericfield">
+ <implementation>
+ <constructor>
+ this.keypress = CheckIsDigit ;
+ </constructor>
+ <method name="CheckIsDigit">
+ <body>
+ <![CDATA[
+ var iCode = keyCode ;
+
+ var bAccepted =
+ (
+ ( iCode >= 48 && iCode <= 57 ) // Numbers
+ || (iCode >= 37 && iCode <= 40) // Arrows
+ || iCode == 8 // Backspace
+ || iCode == 46 // Delete
+ ) ;
+
+ return bAccepted ;
+ ]]>
+ </body>
+ </method>
+ </implementation>
+ <events>
+ <event type="keypress" value="CheckIsDigit()" />
+ </events>
+ </binding>
+</bindings> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_about.html b/httemplate/elements/fckeditor/editor/dialog/fck_about.html
new file mode 100644
index 000000000..a5825ce10
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_about.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * "About" dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCKLang = oEditor.FCKLang ;
+
+window.parent.AddTab( 'About', FCKLang.DlgAboutAboutTab ) ;
+window.parent.AddTab( 'License', FCKLang.DlgAboutLicenseTab ) ;
+window.parent.AddTab( 'BrowserInfo', FCKLang.DlgAboutBrowserInfoTab ) ;
+
+// Function called when a dialog tag is selected.
+function OnDialogTabChange( tabCode )
+{
+ ShowE('divAbout', ( tabCode == 'About' ) ) ;
+ ShowE('divLicense', ( tabCode == 'License' ) ) ;
+ ShowE('divInfo' , ( tabCode == 'BrowserInfo' ) ) ;
+}
+
+function SendEMail()
+{
+ var eMail = 'mailto:' ;
+ eMail += 'fredck' ;
+ eMail += '@' ;
+ eMail += 'fckeditor' ;
+ eMail += '.' ;
+ eMail += 'net' ;
+
+ window.location = eMail ;
+}
+
+window.onload = function()
+{
+ // Translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ window.parent.SetAutoSize( true ) ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <div id="divAbout">
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" style="height: 100%">
+ <tr>
+ <td>
+ <img alt="" src="fck_about/logo_fckeditor.gif" width="236" height="41" align="left" />
+ <table width="80" border="0" cellspacing="0" cellpadding="5" bgcolor="#ffffff" align="right">
+ <tr>
+ <td align="center" nowrap="nowrap" style="border-right: #000000 1px solid; border-top: #000000 1px solid;
+ border-left: #000000 1px solid; border-bottom: #000000 1px solid">
+ <span fcklang="DlgAboutVersion">version</span>
+ <br />
+ <b>2.4.3</b><br />
+ Build 15657</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr style="height: 100%">
+ <td align="center">
+ &nbsp;<br />
+ <span style="font-size: 14px" dir="ltr">
+ <br />
+ <b><a href="http://www.fckeditor.net/?about" target="_blank" title="Visit the FCKeditor web site">
+ Support <b>Open Source</b> Software</a></b> </span>
+ <br />
+ <br />
+ <br />
+ <span fcklang="DlgAboutInfo">For further information go to</span> <a href="http://www.fckeditor.net/?About"
+ target="_blank">http://www.fckeditor.net/</a>.
+ <br />
+ Copyright &copy; 2003-2007 <a href="#" onclick="SendEMail();">Frederico Caldeira Knabben</a>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">
+ <img alt="" src="fck_about/logo_fredck.gif" width="87" height="36" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divLicense" style="display: none">
+ <p>
+ Licensed under the terms of any of the following licenses at your
+ choice:
+ </p>
+ <ul>
+ <li style="margin-bottom:15px">
+ <b>GNU General Public License</b> Version 2 or later (the "GPL")<br />
+ <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">http://www.gnu.org/licenses/gpl.html</a>
+ </li>
+ <li style="margin-bottom:15px">
+ <b>GNU Lesser General Public License</b> Version 2.1 or later (the "LGPL")<br />
+ <a href="http://www.gnu.org/licenses/lgpl.html" target="_blank">http://www.gnu.org/licenses/lgpl.html</a>
+ </li>
+ <li>
+ <b>Mozilla Public License</b> Version 1.1 or later (the "MPL")<br />
+ <a href="http://www.mozilla.org/MPL/MPL-1.1.html" target="_blank">http://www.mozilla.org/MPL/MPL-1.1.html</a>
+ </li>
+ </ul>
+ </div>
+ <div id="divInfo" style="display: none" dir="ltr">
+ <table align="center" width="80%" border="0">
+ <tr>
+ <td>
+ <script type="text/javascript">
+<!--
+document.write( '<b>User Agent<\/b><br />' + window.navigator.userAgent + '<br /><br />' ) ;
+document.write( '<b>Browser<\/b><br />' + window.navigator.appName + ' ' + window.navigator.appVersion + '<br /><br />' ) ;
+document.write( '<b>Platform<\/b><br />' + window.navigator.platform + '<br /><br />' ) ;
+
+var sUserLang = '?' ;
+
+if ( window.navigator.language )
+ sUserLang = window.navigator.language.toLowerCase() ;
+else if ( window.navigator.userLanguage )
+ sUserLang = window.navigator.userLanguage.toLowerCase() ;
+
+document.write( '<b>User Language<\/b><br />' + sUserLang ) ;
+//-->
+ </script>
+ </td>
+ </tr>
+ </table>
+ </div>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif b/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif
new file mode 100644
index 000000000..b7d6bc6fe
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fredck.gif b/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fredck.gif
new file mode 100644
index 000000000..3108dd9ec
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_about/logo_fredck.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_anchor.html b/httemplate/elements/fckeditor/editor/dialog/fck_anchor.html
new file mode 100644
index 000000000..a9f2f5006
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_anchor.html
@@ -0,0 +1,236 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Anchor dialog window.
+-->
+<html>
+ <head>
+ <title>Anchor Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKBrowserInfo = oEditor.FCKBrowserInfo ;
+var FCKTools = oEditor.FCKTools ;
+var FCKRegexLib = oEditor.FCKRegexLib ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oFakeImage = FCK.Selection.GetSelectedElement() ;
+var oAnchor ;
+
+if ( oFakeImage )
+{
+ if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') )
+ oAnchor = FCK.GetRealElement( oFakeImage ) ;
+ else
+ oFakeImage = null ;
+}
+
+//Search for a real anchor
+if ( !oFakeImage )
+{
+ oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ;
+ if ( oAnchor )
+ FCK.Selection.SelectNode( oAnchor ) ;
+}
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oAnchor )
+ GetE('txtName').value = oAnchor.name ;
+ else
+ oAnchor = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ var sNewName = GetE('txtName').value ;
+
+ // Remove any illegal character in a name attribute:
+ // A name should start with a letter, but the validator passes anyway.
+ sNewName = sNewName.replace( /[^\w-_\.:]/g, '_' ) ;
+
+ if ( sNewName.length == 0 )
+ {
+ // Remove the anchor if the user leaves the name blank
+ if ( oAnchor )
+ {
+ RemoveAnchor() ;
+ return true ;
+ }
+
+ alert( oEditor.FCKLang.DlgAnchorErrorName ) ;
+ return false ;
+ }
+
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ if ( oAnchor ) // Modifying an existent anchor.
+ {
+ ReadjustLinksToAnchor( oAnchor.name, sNewName );
+
+ // Buggy explorer, bad bad browser. http://alt-tag.com/blog/archives/2006/02/ie-dom-bugs/
+ // Instead of just replacing the .name for the existing anchor (in order to preserve the content), we must remove the .name
+ // and assign .name, although it won't appear until it's specially processed in fckxhtml.js
+
+ // We remove the previous name
+ oAnchor.removeAttribute( 'name' ) ;
+ // Now we set it, but later we must process it specially
+ oAnchor.name = sNewName ;
+
+ return true ;
+ }
+
+ // Create a new anchor preserving the current selection
+ var aNewAnchors = oEditor.FCK.CreateLink( '#' ) ;
+
+ if ( aNewAnchors.length == 0 )
+ {
+ // Nothing was selected, so now just create a normal A
+ aNewAnchors.push( oEditor.FCK.CreateElement( 'a' ) ) ;
+ }
+ else
+ {
+ // Remove the fake href
+ for ( var i = 0 ; i < aNewAnchors.length ; i++ )
+ aNewAnchors[i].removeAttribute( 'href' ) ;
+ }
+
+ // More than one anchors may have been created, so interact through all of them (see #220).
+ for ( var i = 0 ; i < aNewAnchors.length ; i++ )
+ {
+ oAnchor = aNewAnchors[i] ;
+
+ // Set the name
+ oAnchor.name = sNewName ;
+
+ // IE does require special processing to show the Anchor's image
+ // Opera doesn't allow to select empty anchors
+ if ( FCKBrowserInfo.IsIE || FCKBrowserInfo.IsOpera )
+ {
+ if ( oAnchor.innerHTML != '' )
+ {
+ if ( FCKBrowserInfo.IsIE )
+ oAnchor.className += ' FCK__AnchorC' ;
+ }
+ else
+ {
+ // Create a fake image for both IE and Opera
+ var oImg = oEditor.FCKDocumentProcessor_CreateFakeImage( 'FCK__Anchor', oAnchor.cloneNode(true) ) ;
+ oImg.setAttribute( '_fckanchor', 'true', 0 ) ;
+
+ oAnchor.parentNode.insertBefore( oImg, oAnchor ) ;
+ oAnchor.parentNode.removeChild( oAnchor ) ;
+ }
+
+ }
+ }
+
+ return true ;
+}
+
+// Removes the current anchor from the document
+function RemoveAnchor()
+{
+ // If it's also a link, then just remove the name and exit
+ if ( oAnchor.href.length != 0 )
+ {
+ oAnchor.removeAttribute( 'name' ) ;
+ // Remove temporary class for IE
+ if ( FCKBrowserInfo.IsIE )
+ oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ;
+ return ;
+ }
+
+ // We need to remove the anchor
+ // If we got a fake image, then just remove it and we're done
+ if ( oFakeImage )
+ {
+ oFakeImage.parentNode.removeChild( oFakeImage ) ;
+ return ;
+ }
+ // Empty anchor, so just remove it
+ if ( oAnchor.innerHTML.length == 0 )
+ {
+ oAnchor.parentNode.removeChild( oAnchor ) ;
+ return ;
+ }
+ // Anchor with content, leave the content
+ FCKTools.RemoveOuterTags( oAnchor ) ;
+}
+
+// Checks all the links in the current page pointing to the current name and changes them to the new name
+function ReadjustLinksToAnchor( sCurrent, sNew )
+{
+ var oDoc = FCK.EditorDocument ;
+
+ var aLinks = oDoc.getElementsByTagName( 'A' ) ;
+
+ var sReference = '#' + sCurrent ;
+ // The url of the document, so we check absolute and partial references.
+ var sFullReference = oDoc.location.href.replace( /(#.*$)/, '') ;
+ sFullReference += sReference ;
+
+ var oLink ;
+ var i = aLinks.length - 1 ;
+ while ( i >= 0 && ( oLink = aLinks[i--] ) )
+ {
+ var sHRef = oLink.getAttribute( '_fcksavedurl' ) ;
+ if ( sHRef == null )
+ sHRef = oLink.getAttribute( 'href' , 2 ) || '' ;
+
+ if ( sHRef == sReference || sHRef == sFullReference )
+ {
+ oLink.href = '#' + sNew ;
+ SetAttribute( oLink, '_fcksavedurl', '#' + sNew ) ;
+ }
+ }
+}
+
+ </script>
+ </head>
+ <body style="OVERFLOW: hidden" scroll="no">
+ <table height="100%" width="100%">
+ <tr>
+ <td align="center">
+ <table border="0" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td>
+ <span fckLang="DlgAnchorName">Anchor Name</span><BR>
+ <input id="txtName" style="WIDTH: 100%" type="text">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_button.html b/httemplate/elements/fckeditor/editor/dialog/fck_button.html
new file mode 100644
index 000000000..6e5c2bb19
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_button.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Button dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Button Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl && oActiveEl.tagName.toUpperCase() == "INPUT" && ( oActiveEl.type == "button" || oActiveEl.type == "submit" || oActiveEl.type == "reset" ) )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtValue').value = oActiveEl.value ;
+ GetE('txtType').value = oActiveEl.type ;
+
+ GetE('txtType').disabled = true ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oActiveEl.type = GetE('txtType').value ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ oActiveEl.name = GetE('txtName').value ;
+ SetAttribute( oActiveEl, 'value', GetE('txtValue').value ) ;
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table width="100%" style="height: 100%">
+ <tr>
+ <td align="center">
+ <table border="0" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td colspan="">
+ <span fcklang="DlgCheckboxName">Name</span><br />
+ <input type="text" size="20" id="txtName" style="width: 100%" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgButtonText">Text (Value)</span><br />
+ <input type="text" id="txtValue" style="width: 100%" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgButtonType">Type</span><br />
+ <select id="txtType">
+ <option fcklang="DlgButtonTypeBtn" value="button" selected="selected">Button</option>
+ <option fcklang="DlgButtonTypeSbm" value="submit">Submit</option>
+ <option fcklang="DlgButtonTypeRst" value="reset">Reset</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_checkbox.html b/httemplate/elements/fckeditor/editor/dialog/fck_checkbox.html
new file mode 100644
index 000000000..ac7b4f3c7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_checkbox.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Checkbox dialog window.
+-->
+<html>
+ <head>
+ <title>Checkbox Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl && oActiveEl.tagName == 'INPUT' && oActiveEl.type == 'checkbox' )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtValue').value = oEditor.FCKBrowserInfo.IsIE ? oActiveEl.value : GetAttribute( oActiveEl, 'value' ) ;
+ GetE('txtSelected').checked = oActiveEl.checked ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oActiveEl.type = 'checkbox' ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ if ( GetE('txtName').value.length > 0 )
+ oActiveEl.name = GetE('txtName').value ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ oActiveEl.value = GetE('txtValue').value ;
+ else
+ SetAttribute( oActiveEl, 'value', GetE('txtValue').value ) ;
+
+ var bIsChecked = GetE('txtSelected').checked ;
+ SetAttribute( oActiveEl, 'checked', bIsChecked ? 'checked' : null ) ; // For Firefox
+ oActiveEl.checked = bIsChecked ;
+
+ return true ;
+}
+
+ </script>
+ </head>
+ <body style="OVERFLOW: hidden" scroll="no">
+ <table height="100%" width="100%">
+ <tr>
+ <td align="center">
+ <table border="0" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td>
+ <span fckLang="DlgCheckboxName">Name</span><br>
+ <input type="text" size="20" id="txtName" style="WIDTH: 100%">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fckLang="DlgCheckboxValue">Value</span><br>
+ <input type="text" size="20" id="txtValue" style="WIDTH: 100%">
+ </td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="txtSelected"><label for="txtSelected" fckLang="DlgCheckboxSelected">Checked</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_colorselector.html b/httemplate/elements/fckeditor/editor/dialog/fck_colorselector.html
new file mode 100644
index 000000000..1778f5101
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_colorselector.html
@@ -0,0 +1,171 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Color Selection dialog window.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <style TYPE="text/css">
+ #ColorTable { cursor: pointer ; cursor: hand ; }
+ #hicolor { height: 74px ; width: 74px ; border-width: 1px ; border-style: solid ; }
+ #hicolortext { width: 75px ; text-align: right ; margin-bottom: 7px ; }
+ #selhicolor { height: 20px ; width: 74px ; border-width: 1px ; border-style: solid ; }
+ #selcolor { width: 75px ; height: 20px ; margin-top: 0px ; margin-bottom: 7px ; }
+ #btnClear { width: 75px ; height: 22px ; margin-bottom: 6px ; }
+ .ColorCell { height: 15px ; width: 15px ; }
+ </style>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+function OnLoad()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ CreateColorTable() ;
+
+ window.parent.SetOkButton( true ) ;
+ window.parent.SetAutoSize( true ) ;
+}
+
+function CreateColorTable()
+{
+ // Get the target table.
+ var oTable = document.getElementById('ColorTable') ;
+
+ // Create the base colors array.
+ var aColors = ['00','33','66','99','cc','ff'] ;
+
+ // This function combines two ranges of three values from the color array into a row.
+ function AppendColorRow( rangeA, rangeB )
+ {
+ for ( var i = rangeA ; i < rangeA + 3 ; i++ )
+ {
+ var oRow = oTable.insertRow(-1) ;
+
+ for ( var j = rangeB ; j < rangeB + 3 ; j++ )
+ {
+ for ( var n = 0 ; n < 6 ; n++ )
+ {
+ AppendColorCell( oRow, '#' + aColors[j] + aColors[n] + aColors[i] ) ;
+ }
+ }
+ }
+ }
+
+ // This function create a single color cell in the color table.
+ function AppendColorCell( targetRow, color )
+ {
+ var oCell = targetRow.insertCell(-1) ;
+ oCell.className = 'ColorCell' ;
+ oCell.bgColor = color ;
+
+ oCell.onmouseover = function()
+ {
+ document.getElementById('hicolor').style.backgroundColor = this.bgColor ;
+ document.getElementById('hicolortext').innerHTML = this.bgColor ;
+ }
+
+ oCell.onclick = function()
+ {
+ document.getElementById('selhicolor').style.backgroundColor = this.bgColor ;
+ document.getElementById('selcolor').value = this.bgColor ;
+ }
+ }
+
+ AppendColorRow( 0, 0 ) ;
+ AppendColorRow( 3, 0 ) ;
+ AppendColorRow( 0, 3 ) ;
+ AppendColorRow( 3, 3 ) ;
+
+ // Create the last row.
+ var oRow = oTable.insertRow(-1) ;
+
+ // Create the gray scale colors cells.
+ for ( var n = 0 ; n < 6 ; n++ )
+ {
+ AppendColorCell( oRow, '#' + aColors[n] + aColors[n] + aColors[n] ) ;
+ }
+
+ // Fill the row with black cells.
+ for ( var i = 0 ; i < 12 ; i++ )
+ {
+ AppendColorCell( oRow, '#000000' ) ;
+ }
+}
+
+function Clear()
+{
+ document.getElementById('selhicolor').style.backgroundColor = '' ;
+ document.getElementById('selcolor').value = '' ;
+}
+
+function ClearActual()
+{
+ document.getElementById('hicolor').style.backgroundColor = '' ;
+ document.getElementById('hicolortext').innerHTML = '&nbsp;' ;
+}
+
+function UpdateColor()
+{
+ try { document.getElementById('selhicolor').style.backgroundColor = document.getElementById('selcolor').value ; }
+ catch (e) { Clear() ; }
+}
+
+function Ok()
+{
+ if ( typeof(window.parent.dialogArguments.CustomValue) == 'function' )
+ window.parent.dialogArguments.CustomValue( document.getElementById('selcolor').value ) ;
+
+ return true ;
+}
+ </script>
+ </head>
+ <body onload="OnLoad()" scroll="no" style="OVERFLOW: hidden">
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%">
+ <tr>
+ <td align="center" valign="middle">
+ <table border="0" cellspacing="5" cellpadding="0" width="100%">
+ <tr>
+ <td valign="top" align="center" nowrap width="100%">
+ <table id="ColorTable" border="0" cellspacing="0" cellpadding="0" width="270" onmouseout="ClearActual();">
+ </table>
+ </td>
+ <td valign="top" align="left" nowrap>
+ <span fckLang="DlgColorHighlight">Highlight</span>
+ <div id="hicolor"></div>
+ <div id="hicolortext">&nbsp;</div>
+ <span fckLang="DlgColorSelected">Selected</span>
+ <div id="selhicolor"></div>
+ <input id="selcolor" type="text" maxlength="20" onchange="UpdateColor();">
+ <br>
+ <input id="btnClear" type="button" fckLang="DlgColorBtnClear" value="Clear" onclick="Clear();" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_docprops.html b/httemplate/elements/fckeditor/editor/dialog/fck_docprops.html
new file mode 100644
index 000000000..308346631
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_docprops.html
@@ -0,0 +1,600 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Link dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKLang = oEditor.FCKLang ;
+var FCKConfig = oEditor.FCKConfig ;
+
+//#### Dialog Tabs
+
+// Set the dialog tabs.
+window.parent.AddTab( 'General' , FCKLang.DlgDocGeneralTab ) ;
+window.parent.AddTab( 'Background' , FCKLang.DlgDocBackTab ) ;
+window.parent.AddTab( 'Colors' , FCKLang.DlgDocColorsTab ) ;
+window.parent.AddTab( 'Meta' , FCKLang.DlgDocMetaTab ) ;
+
+// Function called when a dialog tag is selected.
+function OnDialogTabChange( tabCode )
+{
+ ShowE( 'divGeneral' , ( tabCode == 'General' ) ) ;
+ ShowE( 'divBackground' , ( tabCode == 'Background' ) ) ;
+ ShowE( 'divColors' , ( tabCode == 'Colors' ) ) ;
+ ShowE( 'divMeta' , ( tabCode == 'Meta' ) ) ;
+
+ ShowE( 'ePreview' , ( tabCode == 'Background' || tabCode == 'Colors' ) ) ;
+}
+
+//#### Get Base elements from the document: BEGIN
+
+// The HTML element of the document.
+var oHTML = FCK.EditorDocument.getElementsByTagName('html')[0] ;
+
+// The HEAD element of the document.
+var oHead = oHTML.getElementsByTagName('head')[0] ;
+
+var oBody = FCK.EditorDocument.body ;
+
+// This object contains all META tags defined in the document.
+var oMetaTags = new Object() ;
+
+// Get all META tags defined in the document.
+AppendMetaCollection( oMetaTags, oHead.getElementsByTagName('meta') ) ;
+AppendMetaCollection( oMetaTags, oHead.getElementsByTagName('fck:meta') ) ;
+
+function AppendMetaCollection( targetObject, metaCollection )
+{
+ // Loop throw all METAs and put it in the HashTable.
+ for ( var i = 0 ; i < metaCollection.length ; i++ )
+ {
+ // Try to get the "name" attribute.
+ var sName = GetAttribute( metaCollection[i], 'name', GetAttribute( metaCollection[i], '___fcktoreplace:name', '' ) ) ;
+
+ // If no "name", try with the "http-equiv" attribute.
+ if ( sName.length == 0 )
+ {
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ // Get the http-equiv value from the outerHTML.
+ var oHttpEquivMatch = metaCollection[i].outerHTML.match( oEditor.FCKRegexLib.MetaHttpEquiv ) ;
+ if ( oHttpEquivMatch )
+ sName = oHttpEquivMatch[1] ;
+ }
+ else
+ sName = GetAttribute( metaCollection[i], 'http-equiv', '' ) ;
+ }
+
+ if ( sName.length > 0 )
+ targetObject[ sName.toLowerCase() ] = metaCollection[i] ;
+ }
+}
+
+//#### END
+
+// Set a META tag in the document.
+function SetMetadata( name, content, isHttp )
+{
+ if ( content.length == 0 )
+ {
+ RemoveMetadata( name ) ;
+ return ;
+ }
+
+ var oMeta = oMetaTags[ name.toLowerCase() ] ;
+
+ if ( !oMeta )
+ {
+ oMeta = oHead.appendChild( FCK.EditorDocument.createElement('META') ) ;
+
+ if ( isHttp )
+ SetAttribute( oMeta, 'http-equiv', name ) ;
+ else
+ {
+ // On IE, it is not possible to set the "name" attribute of the META tag.
+ // So a temporary attribute is used and it is replaced when getting the
+ // editor's HTML/XHTML value. This is sad, I know :(
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ SetAttribute( oMeta, '___fcktoreplace:name', name ) ;
+ else
+ SetAttribute( oMeta, 'name', name ) ;
+ }
+
+ oMetaTags[ name.toLowerCase() ] = oMeta ;
+ }
+
+ SetAttribute( oMeta, 'content', content ) ;
+// oMeta.content = content ;
+}
+
+function RemoveMetadata( name )
+{
+ var oMeta = oMetaTags[ name.toLowerCase() ] ;
+
+ if ( oMeta && oMeta != null )
+ {
+ oMeta.parentNode.removeChild( oMeta ) ;
+ oMetaTags[ name.toLowerCase() ] = null ;
+ }
+}
+
+function GetMetadata( name )
+{
+ var oMeta = oMetaTags[ name.toLowerCase() ] ;
+
+ if ( oMeta && oMeta != null )
+ return oMeta.getAttribute( 'content', 2 ) ;
+ else
+ return '' ;
+}
+
+window.onload = function ()
+{
+ // Show/Hide the "Browse Server" button.
+ GetE('tdBrowse').style.display = oEditor.FCKConfig.ImageBrowser ? "" : "none";
+
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage( document ) ;
+
+ FillFields() ;
+
+ UpdatePreview() ;
+
+ // Show the "Ok" button.
+ window.parent.SetOkButton( true ) ;
+
+ window.parent.SetAutoSize( true ) ;
+}
+
+function FillFields()
+{
+ // ### General Info
+ GetE('txtPageTitle').value = FCK.EditorDocument.title ;
+
+ GetE('selDirection').value = GetAttribute( oHTML, 'dir', '' ) ;
+ GetE('txtLang').value = GetAttribute( oHTML, 'xml:lang', GetAttribute( oHTML, 'lang', '' ) ) ; // "xml:lang" takes precedence to "lang".
+
+ // Character Set Encoding.
+// if ( oEditor.FCKBrowserInfo.IsIE )
+// var sCharSet = FCK.EditorDocument.charset ;
+// else
+ var sCharSet = GetMetadata( 'Content-Type' ) ;
+
+ if ( sCharSet != null && sCharSet.length > 0 )
+ {
+// if ( !oEditor.FCKBrowserInfo.IsIE )
+ sCharSet = sCharSet.match( /[^=]*$/ ) ;
+
+ GetE('selCharSet').value = sCharSet ;
+
+ if ( GetE('selCharSet').selectedIndex == -1 )
+ {
+ GetE('selCharSet').value = '...' ;
+ GetE('txtCustomCharSet').value = sCharSet ;
+
+ CheckOther( GetE('selCharSet'), 'txtCustomCharSet' ) ;
+ }
+ }
+
+ // Document Type.
+ if ( FCK.DocTypeDeclaration && FCK.DocTypeDeclaration.length > 0 )
+ {
+ GetE('selDocType').value = FCK.DocTypeDeclaration ;
+
+ if ( GetE('selDocType').selectedIndex == -1 )
+ {
+ GetE('selDocType').value = '...' ;
+ GetE('txtDocType').value = FCK.DocTypeDeclaration ;
+
+ CheckOther( GetE('selDocType'), 'txtDocType' ) ;
+ }
+ }
+
+ // Document Type.
+ GetE('chkIncXHTMLDecl').checked = ( FCK.XmlDeclaration && FCK.XmlDeclaration.length > 0 ) ;
+
+ // ### Background
+ GetE('txtBackColor').value = GetAttribute( oBody, 'bgColor' , '' ) ;
+ GetE('txtBackImage').value = GetAttribute( oBody, 'background' , '' ) ;
+ GetE('chkBackNoScroll').checked = ( GetAttribute( oBody, 'bgProperties', '' ).toLowerCase() == 'fixed' ) ;
+
+ // ### Colors
+ GetE('txtColorText').value = GetAttribute( oBody, 'text' , '' ) ;
+ GetE('txtColorLink').value = GetAttribute( oBody, 'link' , '' ) ;
+ GetE('txtColorVisited').value = GetAttribute( oBody, 'vLink' , '' ) ;
+ GetE('txtColorActive').value = GetAttribute( oBody, 'aLink' , '' ) ;
+
+ // ### Margins
+ GetE('txtMarginTop').value = GetAttribute( oBody, 'topMargin' , '' ) ;
+ GetE('txtMarginLeft').value = GetAttribute( oBody, 'leftMargin' , '' ) ;
+ GetE('txtMarginRight').value = GetAttribute( oBody, 'rightMargin' , '' ) ;
+ GetE('txtMarginBottom').value = GetAttribute( oBody, 'bottomMargin' , '' ) ;
+
+ // ### Meta Data
+ GetE('txtMetaKeywords').value = GetMetadata( 'keywords' ) ;
+ GetE('txtMetaDescription').value = GetMetadata( 'description' ) ;
+ GetE('txtMetaAuthor').value = GetMetadata( 'author' ) ;
+ GetE('txtMetaCopyright').value = GetMetadata( 'copyright' ) ;
+}
+
+// Called when the "Ok" button is clicked.
+function Ok()
+{
+ // ### General Info
+ FCK.EditorDocument.title = GetE('txtPageTitle').value ;
+
+ var oHTML = FCK.EditorDocument.getElementsByTagName('html')[0] ;
+
+ SetAttribute( oHTML, 'dir' , GetE('selDirection').value ) ;
+ SetAttribute( oHTML, 'lang' , GetE('txtLang').value ) ;
+ SetAttribute( oHTML, 'xml:lang' , GetE('txtLang').value ) ;
+
+ // Character Set Enconding.
+ var sCharSet = GetE('selCharSet').value ;
+ if ( sCharSet == '...' )
+ sCharSet = GetE('txtCustomCharSet').value ;
+
+ if ( sCharSet.length > 0 )
+ sCharSet = 'text/html; charset=' + sCharSet ;
+
+// if ( oEditor.FCKBrowserInfo.IsIE )
+// FCK.EditorDocument.charset = sCharSet ;
+// else
+ SetMetadata( 'Content-Type', sCharSet, true ) ;
+
+ // Document Type
+ var sDocType = GetE('selDocType').value ;
+ if ( sDocType == '...' )
+ sDocType = GetE('txtDocType').value ;
+
+ FCK.DocTypeDeclaration = sDocType ;
+
+ // XHTML Declarations.
+ if ( GetE('chkIncXHTMLDecl').checked )
+ {
+ if ( sCharSet.length == 0 )
+ sCharSet = 'utf-8' ;
+
+ FCK.XmlDeclaration = '<?xml version="1.0" encoding="' + sCharSet + '"?>' ;
+
+ SetAttribute( oHTML, 'xmlns', 'http://www.w3.org/1999/xhtml' ) ;
+ }
+ else
+ {
+ FCK.XmlDeclaration = null ;
+ oHTML.removeAttribute( 'xmlns', 0 ) ;
+ }
+
+ // ### Background
+ SetAttribute( oBody, 'bgcolor' , GetE('txtBackColor').value ) ;
+ SetAttribute( oBody, 'background' , GetE('txtBackImage').value ) ;
+ SetAttribute( oBody, 'bgproperties' , GetE('chkBackNoScroll').checked ? 'fixed' : '' ) ;
+
+ // ### Colors
+ SetAttribute( oBody, 'text' , GetE('txtColorText').value ) ;
+ SetAttribute( oBody, 'link' , GetE('txtColorLink').value ) ;
+ SetAttribute( oBody, 'vlink', GetE('txtColorVisited').value ) ;
+ SetAttribute( oBody, 'alink', GetE('txtColorActive').value ) ;
+
+ // ### Margins
+ SetAttribute( oBody, 'topmargin' , GetE('txtMarginTop').value ) ;
+ SetAttribute( oBody, 'leftmargin' , GetE('txtMarginLeft').value ) ;
+ SetAttribute( oBody, 'rightmargin' , GetE('txtMarginRight').value ) ;
+ SetAttribute( oBody, 'bottommargin' , GetE('txtMarginBottom').value ) ;
+
+ // ### Meta data
+ SetMetadata( 'keywords' , GetE('txtMetaKeywords').value ) ;
+ SetMetadata( 'description' , GetE('txtMetaDescription').value ) ;
+ SetMetadata( 'author' , GetE('txtMetaAuthor').value ) ;
+ SetMetadata( 'copyright' , GetE('txtMetaCopyright').value ) ;
+
+ return true ;
+}
+
+var bPreviewIsLoaded = false ;
+var oPreviewWindow ;
+var oPreviewBody ;
+
+// Called by the Preview page when loaded.
+function OnPreviewLoad( previewWindow, previewBody )
+{
+ oPreviewWindow = previewWindow ;
+ oPreviewBody = previewBody ;
+
+ bPreviewIsLoaded = true ;
+ UpdatePreview() ;
+}
+
+function UpdatePreview()
+{
+ if ( !bPreviewIsLoaded )
+ return ;
+
+ // ### Background
+ SetAttribute( oPreviewBody, 'bgcolor' , GetE('txtBackColor').value ) ;
+ SetAttribute( oPreviewBody, 'background' , GetE('txtBackImage').value ) ;
+ SetAttribute( oPreviewBody, 'bgproperties' , GetE('chkBackNoScroll').checked ? 'fixed' : '' ) ;
+
+ // ### Colors
+ SetAttribute( oPreviewBody, 'text', GetE('txtColorText').value ) ;
+
+ oPreviewWindow.SetLinkColor( GetE('txtColorLink').value ) ;
+ oPreviewWindow.SetVisitedColor( GetE('txtColorVisited').value ) ;
+ oPreviewWindow.SetActiveColor( GetE('txtColorActive').value ) ;
+}
+
+function CheckOther( combo, txtField )
+{
+ var bNotOther = ( combo.value != '...' ) ;
+
+ GetE(txtField).style.backgroundColor = ( bNotOther ? '#cccccc' : '' ) ;
+ GetE(txtField).disabled = bNotOther ;
+}
+
+function SetColor( inputId, color )
+{
+ GetE( inputId ).value = color + '' ;
+ UpdatePreview() ;
+}
+
+function SelectBackColor( color ) { SetColor('txtBackColor', color ) ; }
+function SelectColorText( color ) { SetColor('txtColorText', color ) ; }
+function SelectColorLink( color ) { SetColor('txtColorLink', color ) ; }
+function SelectColorVisited( color ) { SetColor('txtColorVisited', color ) ; }
+function SelectColorActive( color ) { SetColor('txtColorActive', color ) ; }
+
+function SelectColor( wich )
+{
+ switch ( wich )
+ {
+ case 'Back' : oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, SelectBackColor, window ) ; return ;
+ case 'ColorText' : oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, SelectColorText, window ) ; return ;
+ case 'ColorLink' : oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, SelectColorLink, window ) ; return ;
+ case 'ColorVisited' : oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, SelectColorVisited, window ) ; return ;
+ case 'ColorActive' : oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, SelectColorActive, window ) ; return ;
+ }
+}
+
+function BrowseServerBack()
+{
+ OpenFileBrowser( FCKConfig.ImageBrowserURL, FCKConfig.ImageBrowserWindowWidth, FCKConfig.ImageBrowserWindowHeight ) ;
+}
+
+function SetUrl( url )
+{
+ GetE('txtBackImage').value = url ;
+ UpdatePreview() ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 100%">
+ <tr>
+ <td valign="top" style="height: 100%">
+ <div id="divGeneral">
+ <span fcklang="DlgDocPageTitle">Page Title</span><br />
+ <input id="txtPageTitle" style="width: 100%" type="text" />
+ <br />
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgDocLangDir">Language Direction</span><br />
+ <select id="selDirection">
+ <option value="" selected="selected"></option>
+ <option value="ltr" fcklang="DlgDocLangDirLTR">Left to Right (LTR)</option>
+ <option value="rtl" fcklang="DlgDocLangDirRTL">Right to Left (RTL)</option>
+ </select>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;</td>
+ <td>
+ <span fcklang="DlgDocLangCode">Language Code</span><br />
+ <input id="txtLang" type="text" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td style="white-space: nowrap">
+ <span fcklang="DlgDocCharSet">Character Set Encoding</span><br />
+ <select id="selCharSet" onchange="CheckOther( this, 'txtCustomCharSet' );">
+ <option value="" selected="selected"></option>
+ <option value="us-ascii">ASCII</option>
+ <option fcklang="DlgDocCharSetCE" value="iso-8859-2">Central European</option>
+ <option fcklang="DlgDocCharSetCT" value="big5">Chinese Traditional (Big5)</option>
+ <option fcklang="DlgDocCharSetCR" value="iso-8859-5">Cyrillic</option>
+ <option fcklang="DlgDocCharSetGR" value="iso-8859-7">Greek</option>
+ <option fcklang="DlgDocCharSetJP" value="iso-2022-jp">Japanese</option>
+ <option fcklang="DlgDocCharSetKR" value="iso-2022-kr">Korean</option>
+ <option fcklang="DlgDocCharSetTR" value="iso-8859-9">Turkish</option>
+ <option fcklang="DlgDocCharSetUN" value="utf-8">Unicode (UTF-8)</option>
+ <option fcklang="DlgDocCharSetWE" value="iso-8859-1">Western European</option>
+ <option fcklang="DlgOpOther" value="...">&lt;Other&gt;</option>
+ </select>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;</td>
+ <td width="100%">
+ <span fcklang="DlgDocCharSetOther">Other Character Set Encoding</span><br />
+ <input id="txtCustomCharSet" style="width: 100%; background-color: #cccccc" disabled="disabled"
+ type="text" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgDocDocType">Document Type Heading</span><br />
+ <select id="selDocType" name="selDocType" onchange="CheckOther( this, 'txtDocType' );">
+ <option value="" selected="selected"></option>
+ <option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'>HTML
+ 4.01 Transitional</option>
+ <option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'>
+ HTML 4.01 Strict</option>
+ <option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'>
+ HTML 4.01 Frameset</option>
+ <option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'>
+ XHTML 1.0 Transitional</option>
+ <option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'>
+ XHTML 1.0 Strict</option>
+ <option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'>
+ XHTML 1.0 Frameset</option>
+ <option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'>
+ XHTML 1.1</option>
+ <option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'>HTML 3.2</option>
+ <option value='<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">'>HTML 2.0</option>
+ <option value="..." fcklang="DlgOpOther">&lt;Other&gt;</option>
+ </select>
+ </td>
+ <td>
+ </td>
+ <td width="100%">
+ <span fcklang="DlgDocDocTypeOther">Other Document Type Heading</span><br />
+ <input id="txtDocType" style="width: 100%; background-color: #cccccc" disabled="disabled"
+ type="text" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <input id="chkIncXHTMLDecl" type="checkbox" />
+ <label for="chkIncXHTMLDecl" fcklang="DlgDocIncXHTML">
+ Include XHTML Declarations</label>
+ </div>
+ <div id="divBackground" style="display: none">
+ <span fcklang="DlgDocBgColor">Background Color</span><br />
+ <input id="txtBackColor" type="text" onchange="UpdatePreview();" onkeyup="UpdatePreview();" />&nbsp;<input
+ id="btnSelBackColor" onclick="SelectColor( 'Back' )" type="button" value="Select..."
+ fcklang="DlgCellBtnSelect" /><br />
+ <br />
+ <span fcklang="DlgDocBgImage">Background Image URL</span><br />
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td width="100%">
+ <input id="txtBackImage" style="width: 100%" type="text" onchange="UpdatePreview();"
+ onkeyup="UpdatePreview();" /></td>
+ <td id="tdBrowse" nowrap="nowrap">
+ &nbsp;<input id="btnBrowse" onclick="BrowseServerBack();" type="button" fcklang="DlgBtnBrowseServer"
+ value="Browse Server" /></td>
+ </tr>
+ </table>
+ <input id="chkBackNoScroll" type="checkbox" onclick="UpdatePreview();" />
+ <label for="chkBackNoScroll" fcklang="DlgDocBgNoScroll">
+ Nonscrolling Background</label>
+ </div>
+ <div id="divColors" style="display: none">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgDocCText">Text</span><br />
+ <input id="txtColorText" type="text" onchange="UpdatePreview();" onkeyup="UpdatePreview();" /><input
+ onclick="SelectColor( 'ColorText' )" type="button" value="Select..." fcklang="DlgCellBtnSelect" />
+ <br />
+ <span fcklang="DlgDocCLink">Link</span><br />
+ <input id="txtColorLink" type="text" onchange="UpdatePreview();" onkeyup="UpdatePreview();" /><input
+ onclick="SelectColor( 'ColorLink' )" type="button" value="Select..." fcklang="DlgCellBtnSelect" />
+ <br />
+ <span fcklang="DlgDocCVisited">Visited Link</span><br />
+ <input id="txtColorVisited" type="text" onchange="UpdatePreview();" onkeyup="UpdatePreview();" /><input
+ onclick="SelectColor( 'ColorVisited' )" type="button" value="Select..." fcklang="DlgCellBtnSelect" />
+ <br />
+ <span fcklang="DlgDocCActive">Active Link</span><br />
+ <input id="txtColorActive" type="text" onchange="UpdatePreview();" onkeyup="UpdatePreview();" /><input
+ onclick="SelectColor( 'ColorActive' )" type="button" value="Select..." fcklang="DlgCellBtnSelect" />
+ </td>
+ <td valign="middle" align="center">
+ <table cellspacing="2" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgDocMargins">Page Margins</span></td>
+ </tr>
+ <tr>
+ <td style="border: #000000 1px solid; padding: 5px">
+ <table cellpadding="0" cellspacing="0" border="0" dir="ltr">
+ <tr>
+ <td align="center" colspan="3">
+ <span fcklang="DlgDocMaTop">Top</span><br />
+ <input id="txtMarginTop" type="text" size="3" />
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <span fcklang="DlgDocMaLeft">Left</span><br />
+ <input id="txtMarginLeft" type="text" size="3" />
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td align="right">
+ <span fcklang="DlgDocMaRight">Right</span><br />
+ <input id="txtMarginRight" type="text" size="3" />
+ </td>
+ </tr>
+ <tr>
+ <td align="center" colspan="3">
+ <span fcklang="DlgDocMaBottom">Bottom</span><br />
+ <input id="txtMarginBottom" type="text" size="3" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divMeta" style="display: none">
+ <span fcklang="DlgDocMeIndex">Document Indexing Keywords (comma separated)</span><br />
+ <textarea id="txtMetaKeywords" style="width: 100%" rows="2" cols="20"></textarea>
+ <br />
+ <span fcklang="DlgDocMeDescr">Document Description</span><br />
+ <textarea id="txtMetaDescription" style="width: 100%" rows="4" cols="20"></textarea>
+ <br />
+ <span fcklang="DlgDocMeAuthor">Author</span><br />
+ <input id="txtMetaAuthor" style="width: 100%" type="text" /><br />
+ <br />
+ <span fcklang="DlgDocMeCopy">Copyright</span><br />
+ <input id="txtMetaCopyright" type="text" style="width: 100%" />
+ </div>
+ </td>
+ </tr>
+ <tr id="ePreview" style="display: none">
+ <td>
+ <span fcklang="DlgDocPreview">Preview</span><br />
+ <iframe id="frmPreview" src="fck_docprops/fck_document_preview.html" width="100%"
+ height="100"></iframe>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html b/httemplate/elements/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html
new file mode 100644
index 000000000..2092775a0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Preview shown in the "Document Properties" dialog window.
+-->
+<html>
+ <head>
+ <title>Document Properties - Preview</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="robots" content="noindex, nofollow">
+ <script language="javascript">
+
+var eBase = parent.FCK.EditorDocument.getElementsByTagName( 'BASE' ) ;
+if ( eBase.length > 0 && eBase[0].href.length > 0 )
+{
+ document.write( '<base href="' + eBase[0].href + '">' ) ;
+}
+
+window.onload = function()
+{
+ if ( typeof( parent.OnPreviewLoad ) == 'function' )
+ parent.OnPreviewLoad( window, document.body ) ;
+}
+
+function SetBaseHRef( baseHref )
+{
+ var eBase = document.createElement( 'BASE' ) ;
+ eBase.href = baseHref ;
+
+ var eHead = document.getElementsByTagName( 'HEAD' )[0] ;
+ eHead.appendChild( eBase ) ;
+}
+
+function SetLinkColor( color )
+{
+ if ( color && color.length > 0 )
+ document.getElementById('eLink').style.color = color ;
+ else
+ document.getElementById('eLink').style.color = window.document.linkColor ;
+}
+
+function SetVisitedColor( color )
+{
+ if ( color && color.length > 0 )
+ document.getElementById('eVisited').style.color = color ;
+ else
+ document.getElementById('eVisited').style.color = window.document.vlinkColor ;
+}
+
+function SetActiveColor( color )
+{
+ if ( color && color.length > 0 )
+ document.getElementById('eActive').style.color = color ;
+ else
+ document.getElementById('eActive').style.color = window.document.alinkColor ;
+}
+ </script>
+ </head>
+ <body>
+ <table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td align="center" valign="middle">
+ Normal Text
+ </td>
+ <td id="eLink" align="center" valign="middle">
+ <u>Link Text</u>
+ </td>
+ </tr>
+ <tr>
+ <td id="eVisited" valign="middle" align="center">
+ <u>Visited Link</u>
+ </td>
+ <td id="eActive" valign="middle" align="center">
+ <u>Active Link</u>
+ </td>
+ </tr>
+ </table>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_find.html b/httemplate/elements/fckeditor/editor/dialog/fck_find.html
new file mode 100644
index 000000000..eba7f9043
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_find.html
@@ -0,0 +1,173 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * "Find" dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+function OnLoad()
+{
+ // Whole word is available on IE only.
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ document.getElementById('divWord').style.display = '' ;
+
+ // First of all, translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage( document ) ;
+
+ window.parent.SetAutoSize( true ) ;
+}
+
+function btnStat(frm)
+{
+ document.getElementById('btnFind').disabled =
+ ( document.getElementById('txtFind').value.length == 0 ) ;
+}
+
+function ReplaceTextNodes( parentNode, regex, replaceValue, replaceAll )
+{
+ for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
+ {
+ var oNode = parentNode.childNodes[i] ;
+ if ( oNode.nodeType == 3 )
+ {
+ var sReplaced = oNode.nodeValue.replace( regex, replaceValue ) ;
+ if ( oNode.nodeValue != sReplaced )
+ {
+ oNode.nodeValue = sReplaced ;
+ if ( ! replaceAll )
+ return true ;
+ }
+ }
+ else
+ {
+ if ( ReplaceTextNodes( oNode, regex, replaceValue ) )
+ return true ;
+ }
+ }
+ return false ;
+}
+
+function GetRegexExpr()
+{
+ var sExpr ;
+
+ if ( document.getElementById('chkWord').checked )
+ sExpr = '\\b' + document.getElementById('txtFind').value + '\\b' ;
+ else
+ sExpr = document.getElementById('txtFind').value ;
+
+ return sExpr ;
+}
+
+function GetCase()
+{
+ return ( document.getElementById('chkCase').checked ? '' : 'i' ) ;
+}
+
+function Ok()
+{
+ if ( document.getElementById('txtFind').value.length == 0 )
+ return ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ FindIE() ;
+ else
+ FindGecko() ;
+}
+
+var oRange ;
+
+if ( oEditor.FCKBrowserInfo.IsIE )
+ oRange = oEditor.FCK.EditorDocument.body.createTextRange() ;
+
+function FindIE()
+{
+ var iFlags = 0 ;
+
+ if ( chkCase.checked )
+ iFlags = iFlags | 4 ;
+
+ if ( chkWord.checked )
+ iFlags = iFlags | 2 ;
+
+ var bFound = oRange.findText( document.getElementById('txtFind').value, 1, iFlags ) ;
+
+ if ( bFound )
+ {
+ oRange.scrollIntoView() ;
+ oRange.select() ;
+ oRange.collapse(false) ;
+ oLastRangeFound = oRange ;
+ }
+ else
+ {
+ oRange = oEditor.FCK.EditorDocument.body.createTextRange() ;
+ alert( oEditor.FCKLang.DlgFindNotFoundMsg ) ;
+ }
+}
+
+function FindGecko()
+{
+ var bCase = document.getElementById('chkCase').checked ;
+ var bWord = document.getElementById('chkWord').checked ;
+
+ // window.find( searchString, caseSensitive, backwards, wrapAround, wholeWord, searchInFrames, showDialog ) ;
+ if ( !oEditor.FCK.EditorWindow.find( document.getElementById('txtFind').value, bCase, false, false, bWord, false, false ) )
+ alert( oEditor.FCKLang.DlgFindNotFoundMsg ) ;
+}
+ </script>
+</head>
+<body onload="OnLoad()" style="overflow: hidden">
+ <table cellspacing="3" cellpadding="2" width="100%" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <label for="txtFind" fcklang="DlgReplaceFindLbl">
+ Find what:</label>&nbsp;
+ </td>
+ <td width="100%">
+ <input id="txtFind" style="width: 100%" tabindex="1" type="text" />
+ </td>
+ <td>
+ <input id="btnFind" style="padding-right: 5px; padding-left: 5px" onclick="Ok();"
+ type="button" value="Find" fcklang="DlgFindFindBtn" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="bottom" colspan="3">
+ &nbsp;<input id="chkCase" tabindex="3" type="checkbox" /><label for="chkCase" fcklang="DlgReplaceCaseChk">Match
+ case</label>
+ <br />
+ <div id="divWord" style="display: none">
+ &nbsp;<input id="chkWord" tabindex="4" type="checkbox" /><label for="chkWord" fcklang="DlgReplaceWordChk">Match
+ whole word</label>
+ </div>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_flash.html b/httemplate/elements/fckeditor/editor/dialog/fck_flash.html
new file mode 100644
index 000000000..be529e34e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_flash.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Flash Properties dialog window.
+-->
+<html>
+ <head>
+ <title>Flash Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script src="fck_flash/fck_flash.js" type="text/javascript"></script>
+ <link href="common/fck_dialog_common.css" type="text/css" rel="stylesheet">
+ </head>
+ <body scroll="no" style="OVERFLOW: hidden">
+ <div id="divInfo">
+ <table cellSpacing="1" cellPadding="1" width="100%" border="0">
+ <tr>
+ <td>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td width="100%"><span fckLang="DlgImgURL">URL</span>
+ </td>
+ <td id="tdBrowse" style="DISPLAY: none" noWrap rowSpan="2">&nbsp; <input id="btnBrowse" onclick="BrowseServer();" type="button" value="Browse Server" fckLang="DlgBtnBrowseServer">
+ </td>
+ </tr>
+ <tr>
+ <td vAlign="top"><input id="txtUrl" onblur="UpdatePreview();" style="WIDTH: 100%" type="text">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <TR>
+ <TD>
+ <table cellSpacing="0" cellPadding="0" border="0">
+ <TR>
+ <TD nowrap>
+ <span fckLang="DlgImgWidth">Width</span><br>
+ <input id="txtWidth" class="FCK__FieldNumeric" type="text" size="3">
+ </TD>
+ <TD>&nbsp;</TD>
+ <TD>
+ <span fckLang="DlgImgHeight">Height</span><br>
+ <input id="txtHeight" class="FCK__FieldNumeric" type="text" size="3">
+ </TD>
+ </TR>
+ </table>
+ </TD>
+ </TR>
+ <tr>
+ <td vAlign="top">
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td valign="top" width="100%">
+ <table cellSpacing="0" cellPadding="0" width="100%">
+ <tr>
+ <td><span fckLang="DlgImgPreview">Preview</span></td>
+ </tr>
+ <tr>
+ <td id="ePreviewCell" valign="top" class="FlashPreviewArea"><iframe src="fck_flash/fck_flash_preview.html" frameborder="0" marginheight="0" marginwidth="0"></iframe></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divUpload" style="DISPLAY: none">
+ <form id="frmUpload" method="post" target="UploadWindow" enctype="multipart/form-data" action="" onsubmit="return CheckUpload();">
+ <span fckLang="DlgLnkUpload">Upload</span><br />
+ <input id="txtUploadFile" style="WIDTH: 100%" type="file" size="40" name="NewFile" /><br />
+ <br />
+ <input id="btnUpload" type="submit" value="Send it to the Server" fckLang="DlgLnkBtnUpload" />
+ <iframe name="UploadWindow" style="DISPLAY: none" src="javascript:void(0)"></iframe>
+ </form>
+ </div>
+ <div id="divAdvanced" style="DISPLAY: none">
+ <TABLE cellSpacing="0" cellPadding="0" border="0">
+ <TR>
+ <TD nowrap>
+ <span fckLang="DlgFlashScale">Scale</span><BR>
+ <select id="cmbScale">
+ <option value="" selected></option>
+ <option value="showall" fckLang="DlgFlashScaleAll">Show all</option>
+ <option value="noborder" fckLang="DlgFlashScaleNoBorder">No Border</option>
+ <option value="exactfit" fckLang="DlgFlashScaleFit">Exact Fit</option>
+ </select></TD>
+ <TD>&nbsp;&nbsp;&nbsp; &nbsp;
+ </TD>
+ <td valign="bottom">
+ <table>
+ <tr>
+ <td><input id="chkAutoPlay" type="checkbox" checked></td>
+ <td><label for="chkAutoPlay" nowrap fckLang="DlgFlashChkPlay">Auto Play</label>&nbsp;&nbsp;</td>
+ <td><input id="chkLoop" type="checkbox" checked></td>
+ <td><label for="chkLoop" nowrap fckLang="DlgFlashChkLoop">Loop</label>&nbsp;&nbsp;</td>
+ <td><input id="chkMenu" type="checkbox" checked></td>
+ <td><label for="chkMenu" nowrap fckLang="DlgFlashChkMenu">Enable Flash Menu</label></td>
+ </tr>
+ </table>
+ </td>
+ </TR>
+ </TABLE>
+ <br>
+ &nbsp;
+ <table cellSpacing="0" cellPadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td vAlign="top" width="50%"><span fckLang="DlgGenId">Id</span><br>
+ <input id="txtAttId" style="WIDTH: 100%" type="text">
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td vAlign="top" nowrap><span fckLang="DlgGenClass">Stylesheet Classes</span><br>
+ <input id="txtAttClasses" style="WIDTH: 100%" type="text">
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td vAlign="top" nowrap width="50%">&nbsp;<span fckLang="DlgGenTitle">Advisory Title</span><br>
+ <input id="txtAttTitle" style="WIDTH: 100%" type="text">
+ </td>
+ </tr>
+ </table>
+ <span fckLang="DlgGenStyle">Style</span><br>
+ <input id="txtAttStyle" style="WIDTH: 100%" type="text">
+ </div>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash.js b/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash.js
new file mode 100644
index 000000000..ee97bc5aa
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash.js
@@ -0,0 +1,286 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Scripts related to the Flash dialog window (see fck_flash.html).
+ */
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKLang = oEditor.FCKLang ;
+var FCKConfig = oEditor.FCKConfig ;
+
+//#### Dialog Tabs
+
+// Set the dialog tabs.
+window.parent.AddTab( 'Info', oEditor.FCKLang.DlgInfoTab ) ;
+
+if ( FCKConfig.FlashUpload )
+ window.parent.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ;
+
+if ( !FCKConfig.FlashDlgHideAdvanced )
+ window.parent.AddTab( 'Advanced', oEditor.FCKLang.DlgAdvancedTag ) ;
+
+// Function called when a dialog tag is selected.
+function OnDialogTabChange( tabCode )
+{
+ ShowE('divInfo' , ( tabCode == 'Info' ) ) ;
+ ShowE('divUpload' , ( tabCode == 'Upload' ) ) ;
+ ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ;
+}
+
+// Get the selected flash embed (if available).
+var oFakeImage = FCK.Selection.GetSelectedElement() ;
+var oEmbed ;
+
+if ( oFakeImage )
+{
+ if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckflash') )
+ oEmbed = FCK.GetRealElement( oFakeImage ) ;
+ else
+ oFakeImage = null ;
+}
+
+window.onload = function()
+{
+ // Translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ // Load the selected element information (if any).
+ LoadSelection() ;
+
+ // Show/Hide the "Browse Server" button.
+ GetE('tdBrowse').style.display = FCKConfig.FlashBrowser ? '' : 'none' ;
+
+ // Set the actual uploader URL.
+ if ( FCKConfig.FlashUpload )
+ GetE('frmUpload').action = FCKConfig.FlashUploadURL ;
+
+ window.parent.SetAutoSize( true ) ;
+
+ // Activate the "OK" button.
+ window.parent.SetOkButton( true ) ;
+}
+
+function LoadSelection()
+{
+ if ( ! oEmbed ) return ;
+
+ GetE('txtUrl').value = GetAttribute( oEmbed, 'src', '' ) ;
+ GetE('txtWidth').value = GetAttribute( oEmbed, 'width', '' ) ;
+ GetE('txtHeight').value = GetAttribute( oEmbed, 'height', '' ) ;
+
+ // Get Advances Attributes
+ GetE('txtAttId').value = oEmbed.id ;
+ GetE('chkAutoPlay').checked = GetAttribute( oEmbed, 'play', 'true' ) == 'true' ;
+ GetE('chkLoop').checked = GetAttribute( oEmbed, 'loop', 'true' ) == 'true' ;
+ GetE('chkMenu').checked = GetAttribute( oEmbed, 'menu', 'true' ) == 'true' ;
+ GetE('cmbScale').value = GetAttribute( oEmbed, 'scale', '' ).toLowerCase() ;
+
+ GetE('txtAttTitle').value = oEmbed.title ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ GetE('txtAttClasses').value = oEmbed.getAttribute('className') || '' ;
+ GetE('txtAttStyle').value = oEmbed.style.cssText ;
+ }
+ else
+ {
+ GetE('txtAttClasses').value = oEmbed.getAttribute('class',2) || '' ;
+ GetE('txtAttStyle').value = oEmbed.getAttribute('style',2) || '' ;
+ }
+
+ UpdatePreview() ;
+}
+
+//#### The OK button was hit.
+function Ok()
+{
+ if ( GetE('txtUrl').value.length == 0 )
+ {
+ window.parent.SetSelectedTab( 'Info' ) ;
+ GetE('txtUrl').focus() ;
+
+ alert( oEditor.FCKLang.DlgAlertUrl ) ;
+
+ return false ;
+ }
+
+ if ( !oEmbed )
+ {
+ oEmbed = FCK.EditorDocument.createElement( 'EMBED' ) ;
+ oFakeImage = null ;
+ }
+ UpdateEmbed( oEmbed ) ;
+
+ if ( !oFakeImage )
+ {
+ oFakeImage = oEditor.FCKDocumentProcessor_CreateFakeImage( 'FCK__Flash', oEmbed ) ;
+ oFakeImage.setAttribute( '_fckflash', 'true', 0 ) ;
+ oFakeImage = FCK.InsertElementAndGetIt( oFakeImage ) ;
+ }
+ else
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ oEditor.FCKFlashProcessor.RefreshView( oFakeImage, oEmbed ) ;
+
+ return true ;
+}
+
+function UpdateEmbed( e )
+{
+ SetAttribute( e, 'type' , 'application/x-shockwave-flash' ) ;
+ SetAttribute( e, 'pluginspage' , 'http://www.macromedia.com/go/getflashplayer' ) ;
+
+ SetAttribute( e, 'src', GetE('txtUrl').value ) ;
+ SetAttribute( e, "width" , GetE('txtWidth').value ) ;
+ SetAttribute( e, "height", GetE('txtHeight').value ) ;
+
+ // Advances Attributes
+
+ SetAttribute( e, 'id' , GetE('txtAttId').value ) ;
+ SetAttribute( e, 'scale', GetE('cmbScale').value ) ;
+
+ SetAttribute( e, 'play', GetE('chkAutoPlay').checked ? 'true' : 'false' ) ;
+ SetAttribute( e, 'loop', GetE('chkLoop').checked ? 'true' : 'false' ) ;
+ SetAttribute( e, 'menu', GetE('chkMenu').checked ? 'true' : 'false' ) ;
+
+ SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ SetAttribute( e, 'className', GetE('txtAttClasses').value ) ;
+ e.style.cssText = GetE('txtAttStyle').value ;
+ }
+ else
+ {
+ SetAttribute( e, 'class', GetE('txtAttClasses').value ) ;
+ SetAttribute( e, 'style', GetE('txtAttStyle').value ) ;
+ }
+}
+
+var ePreview ;
+
+function SetPreviewElement( previewEl )
+{
+ ePreview = previewEl ;
+
+ if ( GetE('txtUrl').value.length > 0 )
+ UpdatePreview() ;
+}
+
+function UpdatePreview()
+{
+ if ( !ePreview )
+ return ;
+
+ while ( ePreview.firstChild )
+ ePreview.removeChild( ePreview.firstChild ) ;
+
+ if ( GetE('txtUrl').value.length == 0 )
+ ePreview.innerHTML = '&nbsp;' ;
+ else
+ {
+ var oDoc = ePreview.ownerDocument || ePreview.document ;
+ var e = oDoc.createElement( 'EMBED' ) ;
+
+ SetAttribute( e, 'src', GetE('txtUrl').value ) ;
+ SetAttribute( e, 'type', 'application/x-shockwave-flash' ) ;
+ SetAttribute( e, 'width', '100%' ) ;
+ SetAttribute( e, 'height', '100%' ) ;
+
+ ePreview.appendChild( e ) ;
+ }
+}
+
+// <embed id="ePreview" src="fck_flash/claims.swf" width="100%" height="100%" style="visibility:hidden" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">
+
+function BrowseServer()
+{
+ OpenFileBrowser( FCKConfig.FlashBrowserURL, FCKConfig.FlashBrowserWindowWidth, FCKConfig.FlashBrowserWindowHeight ) ;
+}
+
+function SetUrl( url, width, height )
+{
+ GetE('txtUrl').value = url ;
+
+ if ( width )
+ GetE('txtWidth').value = width ;
+
+ if ( height )
+ GetE('txtHeight').value = height ;
+
+ UpdatePreview() ;
+
+ window.parent.SetSelectedTab( 'Info' ) ;
+}
+
+function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg )
+{
+ switch ( errorNumber )
+ {
+ case 0 : // No errors
+ alert( 'Your file has been successfully uploaded' ) ;
+ break ;
+ case 1 : // Custom error
+ alert( customMsg ) ;
+ return ;
+ case 101 : // Custom warning
+ alert( customMsg ) ;
+ break ;
+ case 201 :
+ alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ;
+ break ;
+ case 202 :
+ alert( 'Invalid file type' ) ;
+ return ;
+ case 203 :
+ alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ;
+ return ;
+ default :
+ alert( 'Error on file upload. Error number: ' + errorNumber ) ;
+ return ;
+ }
+
+ SetUrl( fileUrl ) ;
+ GetE('frmUpload').reset() ;
+}
+
+var oUploadAllowedExtRegex = new RegExp( FCKConfig.FlashUploadAllowedExtensions, 'i' ) ;
+var oUploadDeniedExtRegex = new RegExp( FCKConfig.FlashUploadDeniedExtensions, 'i' ) ;
+
+function CheckUpload()
+{
+ var sFile = GetE('txtUploadFile').value ;
+
+ if ( sFile.length == 0 )
+ {
+ alert( 'Please select a file to upload' ) ;
+ return false ;
+ }
+
+ if ( ( FCKConfig.FlashUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) ||
+ ( FCKConfig.FlashUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) )
+ {
+ OnUploadCompleted( 202 ) ;
+ return false ;
+ }
+
+ return true ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html b/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html
new file mode 100644
index 000000000..ad3a0a168
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Preview page for the Flash dialog window.
+-->
+<html>
+ <head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="robots" content="noindex, nofollow">
+ <link href="../common/fck_dialog_common.css" rel="stylesheet" type="text/css" />
+ <script language="javascript">
+
+// Sets the Skin CSS
+document.write( '<link href="' + window.parent.FCKConfig.SkinPath + 'fck_dialog.css" type="text/css" rel="stylesheet">' ) ;
+
+if ( window.parent.FCKConfig.BaseHref.length > 0 )
+ document.write( '<base href="' + window.parent.FCKConfig.BaseHref + '">' ) ;
+
+window.onload = function()
+{
+ window.parent.SetPreviewElement( document.body ) ;
+}
+
+ </script>
+ </head>
+ <body style="COLOR: #000000; BACKGROUND-COLOR: #ffffff"></body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_form.html b/httemplate/elements/fckeditor/editor/dialog/fck_form.html
new file mode 100644
index 000000000..66e56d937
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_form.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Form dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.MoveToAncestorNode( 'FORM' ) ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtAction').value = oActiveEl.getAttribute( 'action', 2 ) ;
+ GetE('txtMethod').value = oActiveEl.method ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'FORM' ) ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ oActiveEl.innerHTML = '&nbsp;' ;
+ }
+
+ oActiveEl.name = GetE('txtName').value ;
+ SetAttribute( oActiveEl, 'action' , GetE('txtAction').value ) ;
+ oActiveEl.method = GetE('txtMethod').value ;
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table width="100%" style="height: 100%">
+ <tr>
+ <td align="center">
+ <table cellspacing="0" cellpadding="0" width="80%" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgFormName">Name</span><br />
+ <input style="width: 100%" type="text" id="txtName" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgFormAction">Action</span><br />
+ <input style="width: 100%" type="text" id="txtAction" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgFormMethod">Method</span><br />
+ <select id="txtMethod">
+ <option value="get" selected="selected">GET</option>
+ <option value="post">POST</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_hiddenfield.html b/httemplate/elements/fckeditor/editor/dialog/fck_hiddenfield.html
new file mode 100644
index 000000000..1ae8ae6d9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_hiddenfield.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Hidden Field dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Hidden Field Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+
+// Gets the document DOM
+var oDOM = FCK.EditorDocument ;
+
+// Get the selected flash embed (if available).
+var oFakeImage = FCK.Selection.GetSelectedElement() ;
+var oActiveEl ;
+
+if ( oFakeImage )
+{
+ if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckinputhidden') )
+ oActiveEl = FCK.GetRealElement( oFakeImage ) ;
+ else
+ oFakeImage = null ;
+}
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtValue').value = oActiveEl.value ;
+ }
+
+ window.parent.SetOkButton( true ) ;
+}
+
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oActiveEl.type = 'hidden' ;
+
+ oFakeImage = null ;
+ }
+
+ oActiveEl.name = GetE('txtName').value ;
+ SetAttribute( oActiveEl, 'value', GetE('txtValue').value ) ;
+
+ if ( !oFakeImage )
+ {
+ oFakeImage = oEditor.FCKDocumentProcessor_CreateFakeImage( 'FCK__InputHidden', oActiveEl ) ;
+ oFakeImage.setAttribute( '_fckinputhidden', 'true', 0 ) ;
+ oFakeImage = FCK.InsertElementAndGetIt( oFakeImage ) ;
+ }
+ else
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ oEditor.FCKFlashProcessor.RefreshView( oFakeImage, oActiveEl ) ;
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden" scroll="no">
+ <table height="100%" width="100%">
+ <tr>
+ <td align="center">
+ <table border="0" class="inhoud" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td>
+ <span fcklang="DlgHiddenName">Name</span><br />
+ <input type="text" size="20" id="txtName" style="width: 100%" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgHiddenValue">Value</span><br />
+ <input type="text" size="30" id="txtValue" style="width: 100%" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_image.html b/httemplate/elements/fckeditor/editor/dialog/fck_image.html
new file mode 100644
index 000000000..e4a8b036a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_image.html
@@ -0,0 +1,252 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Image Properties dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Image Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script src="fck_image/fck_image.js" type="text/javascript"></script>
+ <link href="common/fck_dialog_common.css" rel="stylesheet" type="text/css" />
+</head>
+<body scroll="no" style="overflow: hidden">
+ <div id="divInfo">
+ <table cellspacing="1" cellpadding="1" border="0" width="100%" height="100%">
+ <tr>
+ <td>
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td width="100%">
+ <span fcklang="DlgImgURL">URL</span>
+ </td>
+ <td id="tdBrowse" style="display: none" nowrap="nowrap" rowspan="2">
+ &nbsp;
+ <input id="btnBrowse" onclick="BrowseServer();" type="button" value="Browse Server"
+ fcklang="DlgBtnBrowseServer" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <input id="txtUrl" style="width: 100%" type="text" onblur="UpdatePreview();" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgImgAlt">Short Description</span><br />
+ <input id="txtAlt" style="width: 100%" type="text" /><br />
+ </td>
+ </tr>
+ <tr height="100%">
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0" height="100%">
+ <tr>
+ <td valign="top">
+ <br />
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgWidth">Width</span>&nbsp;</td>
+ <td>
+ <input type="text" size="3" id="txtWidth" onkeyup="OnSizeChanged('Width',this.value);" /></td>
+ <td rowspan="2">
+ <div id="btnLockSizes" class="BtnLocked" onmouseover="this.className = (bLockRatio ? 'BtnLocked' : 'BtnUnlocked' ) + ' BtnOver';"
+ onmouseout="this.className = (bLockRatio ? 'BtnLocked' : 'BtnUnlocked' );" title="Lock Sizes"
+ onclick="SwitchLock(this);">
+ </div>
+ </td>
+ <td rowspan="2">
+ <div id="btnResetSize" class="BtnReset" onmouseover="this.className='BtnReset BtnOver';"
+ onmouseout="this.className='BtnReset';" title="Reset Size" onclick="ResetSizes();">
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgHeight">Height</span>&nbsp;</td>
+ <td>
+ <input type="text" size="3" id="txtHeight" onkeyup="OnSizeChanged('Height',this.value);" /></td>
+ </tr>
+ </table>
+ <br />
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgBorder">Border</span>&nbsp;</td>
+ <td>
+ <input type="text" size="2" value="" id="txtBorder" onkeyup="UpdatePreview();" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgHSpace">HSpace</span>&nbsp;</td>
+ <td>
+ <input type="text" size="2" id="txtHSpace" onkeyup="UpdatePreview();" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgVSpace">VSpace</span>&nbsp;</td>
+ <td>
+ <input type="text" size="2" id="txtVSpace" onkeyup="UpdatePreview();" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgImgAlign">Align</span>&nbsp;</td>
+ <td>
+ <select id="cmbAlign" onchange="UpdatePreview();">
+ <option value="" selected="selected"></option>
+ <option fcklang="DlgImgAlignLeft" value="left">Left</option>
+ <option fcklang="DlgImgAlignAbsBottom" value="absBottom">Abs Bottom</option>
+ <option fcklang="DlgImgAlignAbsMiddle" value="absMiddle">Abs Middle</option>
+ <option fcklang="DlgImgAlignBaseline" value="baseline">Baseline</option>
+ <option fcklang="DlgImgAlignBottom" value="bottom">Bottom</option>
+ <option fcklang="DlgImgAlignMiddle" value="middle">Middle</option>
+ <option fcklang="DlgImgAlignRight" value="right">Right</option>
+ <option fcklang="DlgImgAlignTextTop" value="textTop">Text Top</option>
+ <option fcklang="DlgImgAlignTop" value="top">Top</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;</td>
+ <td width="100%" valign="top">
+ <table cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed">
+ <tr>
+ <td>
+ <span fcklang="DlgImgPreview">Preview</span></td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <iframe class="ImagePreviewArea" src="fck_image/fck_image_preview.html" frameborder="0"
+ marginheight="0" marginwidth="0"></iframe>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divUpload" style="display: none">
+ <form id="frmUpload" method="post" target="UploadWindow" enctype="multipart/form-data"
+ action="" onsubmit="return CheckUpload();">
+ <span fcklang="DlgLnkUpload">Upload</span><br />
+ <input id="txtUploadFile" style="width: 100%" type="file" size="40" name="NewFile" /><br />
+ <br />
+ <input id="btnUpload" type="submit" value="Send it to the Server" fcklang="DlgLnkBtnUpload" />
+ <iframe name="UploadWindow" style="display: none" src="javascript:void(0)"></iframe>
+ </form>
+ </div>
+ <div id="divLink" style="display: none">
+ <table cellspacing="1" cellpadding="1" border="0" width="100%">
+ <tr>
+ <td>
+ <div>
+ <span fcklang="DlgLnkURL">URL</span><br />
+ <input id="txtLnkUrl" style="width: 100%" type="text" onblur="UpdatePreview();" />
+ </div>
+ <div id="divLnkBrowseServer" align="right">
+ <input type="button" value="Browse Server" fcklang="DlgBtnBrowseServer" onclick="LnkBrowseServer();" />
+ </div>
+ <div>
+ <span fcklang="DlgLnkTarget">Target</span><br />
+ <select id="cmbLnkTarget">
+ <option value="" fcklang="DlgGenNotSet" selected="selected">&lt;not set&gt;</option>
+ <option value="_blank" fcklang="DlgLnkTargetBlank">New Window (_blank)</option>
+ <option value="_top" fcklang="DlgLnkTargetTop">Topmost Window (_top)</option>
+ <option value="_self" fcklang="DlgLnkTargetSelf">Same Window (_self)</option>
+ <option value="_parent" fcklang="DlgLnkTargetParent">Parent Window (_parent)</option>
+ </select>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divAdvanced" style="display: none">
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td valign="top" width="50%">
+ <span fcklang="DlgGenId">Id</span><br />
+ <input id="txtAttId" style="width: 100%" type="text" />
+ </td>
+ <td width="1">
+ &nbsp;&nbsp;</td>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td width="60%">
+ <span fcklang="DlgGenLangDir">Language Direction</span><br />
+ <select id="cmbAttLangDir" style="width: 100%">
+ <option value="" fcklang="DlgGenNotSet" selected="selected">&lt;not set&gt;</option>
+ <option value="ltr" fcklang="DlgGenLangDirLtr">Left to Right (LTR)</option>
+ <option value="rtl" fcklang="DlgGenLangDirRtl">Right to Left (RTL)</option>
+ </select>
+ </td>
+ <td width="1%">
+ &nbsp;&nbsp;</td>
+ <td nowrap="nowrap">
+ <span fcklang="DlgGenLangCode">Language Code</span><br />
+ <input id="txtAttLangCode" style="width: 100%" type="text" />&nbsp;
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <span fcklang="DlgGenLongDescr">Long Description URL</span><br />
+ <input id="txtLongDesc" style="width: 100%" type="text" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <span fcklang="DlgGenClass">Stylesheet Classes</span><br />
+ <input id="txtAttClasses" style="width: 100%" type="text" />
+ </td>
+ <td>
+ </td>
+ <td valign="top">
+ &nbsp;<span fcklang="DlgGenTitle">Advisory Title</span><br />
+ <input id="txtAttTitle" style="width: 100%" type="text" />
+ </td>
+ </tr>
+ </table>
+ <span fcklang="DlgGenStyle">Style</span><br />
+ <input id="txtAttStyle" style="width: 100%" type="text" />
+ </div>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image.js b/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image.js
new file mode 100644
index 000000000..89b0f95f4
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image.js
@@ -0,0 +1,493 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Scripts related to the Image dialog window (see fck_image.html).
+ */
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKLang = oEditor.FCKLang ;
+var FCKConfig = oEditor.FCKConfig ;
+var FCKDebug = oEditor.FCKDebug ;
+
+var bImageButton = ( document.location.search.length > 0 && document.location.search.substr(1) == 'ImageButton' ) ;
+
+//#### Dialog Tabs
+
+// Set the dialog tabs.
+window.parent.AddTab( 'Info', FCKLang.DlgImgInfoTab ) ;
+
+if ( !bImageButton && !FCKConfig.ImageDlgHideLink )
+ window.parent.AddTab( 'Link', FCKLang.DlgImgLinkTab ) ;
+
+if ( FCKConfig.ImageUpload )
+ window.parent.AddTab( 'Upload', FCKLang.DlgLnkUpload ) ;
+
+if ( !FCKConfig.ImageDlgHideAdvanced )
+ window.parent.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ;
+
+// Function called when a dialog tag is selected.
+function OnDialogTabChange( tabCode )
+{
+ ShowE('divInfo' , ( tabCode == 'Info' ) ) ;
+ ShowE('divLink' , ( tabCode == 'Link' ) ) ;
+ ShowE('divUpload' , ( tabCode == 'Upload' ) ) ;
+ ShowE('divAdvanced' , ( tabCode == 'Advanced' ) ) ;
+}
+
+// Get the selected image (if available).
+var oImage = FCK.Selection.GetSelectedElement() ;
+
+if ( oImage && oImage.tagName != 'IMG' && !( oImage.tagName == 'INPUT' && oImage.type == 'image' ) )
+ oImage = null ;
+
+// Get the active link.
+var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ;
+
+var oImageOriginal ;
+
+function UpdateOriginal( resetSize )
+{
+ if ( !eImgPreview )
+ return ;
+
+ if ( GetE('txtUrl').value.length == 0 )
+ {
+ oImageOriginal = null ;
+ return ;
+ }
+
+ oImageOriginal = document.createElement( 'IMG' ) ; // new Image() ;
+
+ if ( resetSize )
+ {
+ oImageOriginal.onload = function()
+ {
+ this.onload = null ;
+ ResetSizes() ;
+ }
+ }
+
+ oImageOriginal.src = eImgPreview.src ;
+}
+
+var bPreviewInitialized ;
+
+window.onload = function()
+{
+ // Translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ GetE('btnLockSizes').title = FCKLang.DlgImgLockRatio ;
+ GetE('btnResetSize').title = FCKLang.DlgBtnResetSize ;
+
+ // Load the selected element information (if any).
+ LoadSelection() ;
+
+ // Show/Hide the "Browse Server" button.
+ GetE('tdBrowse').style.display = FCKConfig.ImageBrowser ? '' : 'none' ;
+ GetE('divLnkBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ;
+
+ UpdateOriginal() ;
+
+ // Set the actual uploader URL.
+ if ( FCKConfig.ImageUpload )
+ GetE('frmUpload').action = FCKConfig.ImageUploadURL ;
+
+ window.parent.SetAutoSize( true ) ;
+
+ // Activate the "OK" button.
+ window.parent.SetOkButton( true ) ;
+}
+
+function LoadSelection()
+{
+ if ( ! oImage ) return ;
+
+ var sUrl = oImage.getAttribute( '_fcksavedurl' ) ;
+ if ( sUrl == null )
+ sUrl = GetAttribute( oImage, 'src', '' ) ;
+
+ GetE('txtUrl').value = sUrl ;
+ GetE('txtAlt').value = GetAttribute( oImage, 'alt', '' ) ;
+ GetE('txtVSpace').value = GetAttribute( oImage, 'vspace', '' ) ;
+ GetE('txtHSpace').value = GetAttribute( oImage, 'hspace', '' ) ;
+ GetE('txtBorder').value = GetAttribute( oImage, 'border', '' ) ;
+ GetE('cmbAlign').value = GetAttribute( oImage, 'align', '' ) ;
+
+ var iWidth, iHeight ;
+
+ var regexSize = /^\s*(\d+)px\s*$/i ;
+
+ if ( oImage.style.width )
+ {
+ var aMatchW = oImage.style.width.match( regexSize ) ;
+ if ( aMatchW )
+ {
+ iWidth = aMatchW[1] ;
+ oImage.style.width = '' ;
+ SetAttribute( oImage, 'width' , iWidth ) ;
+ }
+ }
+
+ if ( oImage.style.height )
+ {
+ var aMatchH = oImage.style.height.match( regexSize ) ;
+ if ( aMatchH )
+ {
+ iHeight = aMatchH[1] ;
+ oImage.style.height = '' ;
+ SetAttribute( oImage, 'height', iHeight ) ;
+ }
+ }
+
+ GetE('txtWidth').value = iWidth ? iWidth : GetAttribute( oImage, "width", '' ) ;
+ GetE('txtHeight').value = iHeight ? iHeight : GetAttribute( oImage, "height", '' ) ;
+
+ // Get Advances Attributes
+ GetE('txtAttId').value = oImage.id ;
+ GetE('cmbAttLangDir').value = oImage.dir ;
+ GetE('txtAttLangCode').value = oImage.lang ;
+ GetE('txtAttTitle').value = oImage.title ;
+ GetE('txtLongDesc').value = oImage.longDesc ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ GetE('txtAttClasses').value = oImage.className || '' ;
+ GetE('txtAttStyle').value = oImage.style.cssText ;
+ }
+ else
+ {
+ GetE('txtAttClasses').value = oImage.getAttribute('class',2) || '' ;
+ GetE('txtAttStyle').value = oImage.getAttribute('style',2) ;
+ }
+
+ if ( oLink )
+ {
+ var sLinkUrl = oLink.getAttribute( '_fcksavedurl' ) ;
+ if ( sLinkUrl == null )
+ sLinkUrl = oLink.getAttribute('href',2) ;
+
+ GetE('txtLnkUrl').value = sLinkUrl ;
+ GetE('cmbLnkTarget').value = oLink.target ;
+ }
+
+ UpdatePreview() ;
+}
+
+//#### The OK button was hit.
+function Ok()
+{
+ if ( GetE('txtUrl').value.length == 0 )
+ {
+ window.parent.SetSelectedTab( 'Info' ) ;
+ GetE('txtUrl').focus() ;
+
+ alert( FCKLang.DlgImgAlertUrl ) ;
+
+ return false ;
+ }
+
+ var bHasImage = ( oImage != null ) ;
+
+ if ( bHasImage && bImageButton && oImage.tagName == 'IMG' )
+ {
+ if ( confirm( 'Do you want to transform the selected image on a image button?' ) )
+ oImage = null ;
+ }
+ else if ( bHasImage && !bImageButton && oImage.tagName == 'INPUT' )
+ {
+ if ( confirm( 'Do you want to transform the selected image button on a simple image?' ) )
+ oImage = null ;
+ }
+
+ if ( !bHasImage )
+ {
+ if ( bImageButton )
+ {
+ oImage = FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oImage.type = 'image' ;
+ oImage = FCK.InsertElementAndGetIt( oImage ) ;
+ }
+ else
+ oImage = FCK.CreateElement( 'IMG' ) ;
+ }
+ else
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ UpdateImage( oImage ) ;
+
+ var sLnkUrl = GetE('txtLnkUrl').value.Trim() ;
+
+ if ( sLnkUrl.length == 0 )
+ {
+ if ( oLink )
+ FCK.ExecuteNamedCommand( 'Unlink' ) ;
+ }
+ else
+ {
+ if ( oLink ) // Modifying an existent link.
+ oLink.href = sLnkUrl ;
+ else // Creating a new link.
+ {
+ if ( !bHasImage )
+ oEditor.FCKSelection.SelectNode( oImage ) ;
+
+ oLink = oEditor.FCK.CreateLink( sLnkUrl )[0] ;
+
+ if ( !bHasImage )
+ {
+ oEditor.FCKSelection.SelectNode( oLink ) ;
+ oEditor.FCKSelection.Collapse( false ) ;
+ }
+ }
+
+ SetAttribute( oLink, '_fcksavedurl', sLnkUrl ) ;
+ SetAttribute( oLink, 'target', GetE('cmbLnkTarget').value ) ;
+ }
+
+ return true ;
+}
+
+function UpdateImage( e, skipId )
+{
+ e.src = GetE('txtUrl').value ;
+ SetAttribute( e, "_fcksavedurl", GetE('txtUrl').value ) ;
+ SetAttribute( e, "alt" , GetE('txtAlt').value ) ;
+ SetAttribute( e, "width" , GetE('txtWidth').value ) ;
+ SetAttribute( e, "height", GetE('txtHeight').value ) ;
+ SetAttribute( e, "vspace", GetE('txtVSpace').value ) ;
+ SetAttribute( e, "hspace", GetE('txtHSpace').value ) ;
+ SetAttribute( e, "border", GetE('txtBorder').value ) ;
+ SetAttribute( e, "align" , GetE('cmbAlign').value ) ;
+
+ // Advances Attributes
+
+ if ( ! skipId )
+ SetAttribute( e, 'id', GetE('txtAttId').value ) ;
+
+ SetAttribute( e, 'dir' , GetE('cmbAttLangDir').value ) ;
+ SetAttribute( e, 'lang' , GetE('txtAttLangCode').value ) ;
+ SetAttribute( e, 'title' , GetE('txtAttTitle').value ) ;
+ SetAttribute( e, 'longDesc' , GetE('txtLongDesc').value ) ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ e.className = GetE('txtAttClasses').value ;
+ e.style.cssText = GetE('txtAttStyle').value ;
+ }
+ else
+ {
+ SetAttribute( e, 'class' , GetE('txtAttClasses').value ) ;
+ SetAttribute( e, 'style', GetE('txtAttStyle').value ) ;
+ }
+}
+
+var eImgPreview ;
+var eImgPreviewLink ;
+
+function SetPreviewElements( imageElement, linkElement )
+{
+ eImgPreview = imageElement ;
+ eImgPreviewLink = linkElement ;
+
+ UpdatePreview() ;
+ UpdateOriginal() ;
+
+ bPreviewInitialized = true ;
+}
+
+function UpdatePreview()
+{
+ if ( !eImgPreview || !eImgPreviewLink )
+ return ;
+
+ if ( GetE('txtUrl').value.length == 0 )
+ eImgPreviewLink.style.display = 'none' ;
+ else
+ {
+ UpdateImage( eImgPreview, true ) ;
+
+ if ( GetE('txtLnkUrl').value.Trim().length > 0 )
+ eImgPreviewLink.href = 'javascript:void(null);' ;
+ else
+ SetAttribute( eImgPreviewLink, 'href', '' ) ;
+
+ eImgPreviewLink.style.display = '' ;
+ }
+}
+
+var bLockRatio = true ;
+
+function SwitchLock( lockButton )
+{
+ bLockRatio = !bLockRatio ;
+ lockButton.className = bLockRatio ? 'BtnLocked' : 'BtnUnlocked' ;
+ lockButton.title = bLockRatio ? 'Lock sizes' : 'Unlock sizes' ;
+
+ if ( bLockRatio )
+ {
+ if ( GetE('txtWidth').value.length > 0 )
+ OnSizeChanged( 'Width', GetE('txtWidth').value ) ;
+ else
+ OnSizeChanged( 'Height', GetE('txtHeight').value ) ;
+ }
+}
+
+// Fired when the width or height input texts change
+function OnSizeChanged( dimension, value )
+{
+ // Verifies if the aspect ration has to be mantained
+ if ( oImageOriginal && bLockRatio )
+ {
+ var e = dimension == 'Width' ? GetE('txtHeight') : GetE('txtWidth') ;
+
+ if ( value.length == 0 || isNaN( value ) )
+ {
+ e.value = '' ;
+ return ;
+ }
+
+ if ( dimension == 'Width' )
+ value = value == 0 ? 0 : Math.round( oImageOriginal.height * ( value / oImageOriginal.width ) ) ;
+ else
+ value = value == 0 ? 0 : Math.round( oImageOriginal.width * ( value / oImageOriginal.height ) ) ;
+
+ if ( !isNaN( value ) )
+ e.value = value ;
+ }
+
+ UpdatePreview() ;
+}
+
+// Fired when the Reset Size button is clicked
+function ResetSizes()
+{
+ if ( ! oImageOriginal ) return ;
+
+ GetE('txtWidth').value = oImageOriginal.width ;
+ GetE('txtHeight').value = oImageOriginal.height ;
+
+ UpdatePreview() ;
+}
+
+function BrowseServer()
+{
+ OpenServerBrowser(
+ 'Image',
+ FCKConfig.ImageBrowserURL,
+ FCKConfig.ImageBrowserWindowWidth,
+ FCKConfig.ImageBrowserWindowHeight ) ;
+}
+
+function LnkBrowseServer()
+{
+ OpenServerBrowser(
+ 'Link',
+ FCKConfig.LinkBrowserURL,
+ FCKConfig.LinkBrowserWindowWidth,
+ FCKConfig.LinkBrowserWindowHeight ) ;
+}
+
+function OpenServerBrowser( type, url, width, height )
+{
+ sActualBrowser = type ;
+ OpenFileBrowser( url, width, height ) ;
+}
+
+var sActualBrowser ;
+
+function SetUrl( url, width, height, alt )
+{
+ if ( sActualBrowser == 'Link' )
+ {
+ GetE('txtLnkUrl').value = url ;
+ UpdatePreview() ;
+ }
+ else
+ {
+ GetE('txtUrl').value = url ;
+ GetE('txtWidth').value = width ? width : '' ;
+ GetE('txtHeight').value = height ? height : '' ;
+
+ if ( alt )
+ GetE('txtAlt').value = alt;
+
+ UpdatePreview() ;
+ UpdateOriginal( true ) ;
+ }
+
+ window.parent.SetSelectedTab( 'Info' ) ;
+}
+
+function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg )
+{
+ switch ( errorNumber )
+ {
+ case 0 : // No errors
+ alert( 'Your file has been successfully uploaded' ) ;
+ break ;
+ case 1 : // Custom error
+ alert( customMsg ) ;
+ return ;
+ case 101 : // Custom warning
+ alert( customMsg ) ;
+ break ;
+ case 201 :
+ alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ;
+ break ;
+ case 202 :
+ alert( 'Invalid file type' ) ;
+ return ;
+ case 203 :
+ alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ;
+ return ;
+ default :
+ alert( 'Error on file upload. Error number: ' + errorNumber ) ;
+ return ;
+ }
+
+ sActualBrowser = '' ;
+ SetUrl( fileUrl ) ;
+ GetE('frmUpload').reset() ;
+}
+
+var oUploadAllowedExtRegex = new RegExp( FCKConfig.ImageUploadAllowedExtensions, 'i' ) ;
+var oUploadDeniedExtRegex = new RegExp( FCKConfig.ImageUploadDeniedExtensions, 'i' ) ;
+
+function CheckUpload()
+{
+ var sFile = GetE('txtUploadFile').value ;
+
+ if ( sFile.length == 0 )
+ {
+ alert( 'Please select a file to upload' ) ;
+ return false ;
+ }
+
+ if ( ( FCKConfig.ImageUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) ||
+ ( FCKConfig.ImageUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) )
+ {
+ OnUploadCompleted( 202 ) ;
+ return false ;
+ }
+
+ return true ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image_preview.html b/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image_preview.html
new file mode 100644
index 000000000..21bdc25ca
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_image/fck_image_preview.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Preview page for the Image dialog window.
+ *
+ * Curiosity: http://en.wikipedia.org/wiki/Lorem_ipsum
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <link href="../common/fck_dialog_common.css" rel="stylesheet" type="text/css" />
+ <script type="text/javascript">
+
+// Sets the Skin CSS
+document.write( '<link href="' + window.parent.FCKConfig.SkinPath + 'fck_dialog.css" type="text/css" rel="stylesheet">' ) ;
+
+if ( window.parent.FCKConfig.BaseHref.length > 0 )
+ document.write( '<base href="' + window.parent.FCKConfig.BaseHref + '">' ) ;
+
+window.onload = function()
+{
+ window.parent.SetPreviewElements(
+ document.getElementById( 'imgPreview' ),
+ document.getElementById( 'lnkPreview' ) ) ;
+}
+
+ </script>
+</head>
+<body style="color: #000000; background-color: #ffffff">
+ <a id="lnkPreview" onclick="return false;" style="cursor: default">
+ <img id="imgPreview" onload="window.parent.UpdateOriginal();" style="display: none" /></a>Lorem
+ ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas feugiat consequat diam.
+ Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, nulla.
+ Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis
+ euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce
+ mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie.
+ Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque
+ egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem,
+ in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut
+ placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy
+ metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices,
+ ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris
+ non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas
+ elementum. Nunc imperdiet gravida mauris.
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_link.html b/httemplate/elements/fckeditor/editor/dialog/fck_link.html
new file mode 100644
index 000000000..c8f37b605
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_link.html
@@ -0,0 +1,293 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Link dialog window.
+-->
+<html>
+ <head>
+ <title>Link Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script src="fck_link/fck_link.js" type="text/javascript"></script>
+ </head>
+ <body scroll="no" style="OVERFLOW: hidden">
+ <div id="divInfo" style="DISPLAY: none">
+ <span fckLang="DlgLnkType">Link Type</span><br />
+ <select id="cmbLinkType" onchange="SetLinkType(this.value);">
+ <option value="url" fckLang="DlgLnkTypeURL" selected="selected">URL</option>
+ <option value="anchor" fckLang="DlgLnkTypeAnchor">Anchor in this page</option>
+ <option value="email" fckLang="DlgLnkTypeEMail">E-Mail</option>
+ </select>
+ <br />
+ <br />
+ <div id="divLinkTypeUrl">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0" dir="ltr">
+ <tr>
+ <td nowrap="nowrap">
+ <span fckLang="DlgLnkProto">Protocol</span><br />
+ <select id="cmbLinkProtocol">
+ <option value="http://" selected="selected">http://</option>
+ <option value="https://">https://</option>
+ <option value="ftp://">ftp://</option>
+ <option value="news://">news://</option>
+ <option value="" fckLang="DlgLnkProtoOther">&lt;other&gt;</option>
+ </select>
+ </td>
+ <td nowrap="nowrap">&nbsp;</td>
+ <td nowrap="nowrap" width="100%">
+ <span fckLang="DlgLnkURL">URL</span><br />
+ <input id="txtUrl" style="WIDTH: 100%" type="text" onkeyup="OnUrlChange();" onchange="OnUrlChange();" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="divBrowseServer">
+ <input type="button" value="Browse Server" fckLang="DlgBtnBrowseServer" onclick="BrowseServer();" />
+ </div>
+ </div>
+ <div id="divLinkTypeAnchor" style="DISPLAY: none" align="center">
+ <div id="divSelAnchor" style="DISPLAY: none">
+ <table cellspacing="0" cellpadding="0" border="0" width="70%">
+ <tr>
+ <td colspan="3">
+ <span fckLang="DlgLnkAnchorSel">Select an Anchor</span>
+ </td>
+ </tr>
+ <tr>
+ <td width="50%">
+ <span fckLang="DlgLnkAnchorByName">By Anchor Name</span><br />
+ <select id="cmbAnchorName" onchange="GetE('cmbAnchorId').value='';" style="WIDTH: 100%">
+ <option value="" selected="selected"></option>
+ </select>
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;</td>
+ <td width="50%">
+ <span fckLang="DlgLnkAnchorById">By Element Id</span><br />
+ <select id="cmbAnchorId" onchange="GetE('cmbAnchorName').value='';" style="WIDTH: 100%">
+ <option value="" selected="selected"></option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divNoAnchor" style="DISPLAY: none">
+ <span fckLang="DlgLnkNoAnchors">&lt;No anchors available in the document&gt;</span>
+ </div>
+ </div>
+ <div id="divLinkTypeEMail" style="DISPLAY: none">
+ <span fckLang="DlgLnkEMail">E-Mail Address</span><br />
+ <input id="txtEMailAddress" style="WIDTH: 100%" type="text" /><br />
+ <span fckLang="DlgLnkEMailSubject">Message Subject</span><br />
+ <input id="txtEMailSubject" style="WIDTH: 100%" type="text" /><br />
+ <span fckLang="DlgLnkEMailBody">Message Body</span><br />
+ <textarea id="txtEMailBody" style="WIDTH: 100%" rows="3" cols="20"></textarea>
+ </div>
+ </div>
+ <div id="divUpload" style="DISPLAY: none">
+ <form id="frmUpload" method="post" target="UploadWindow" enctype="multipart/form-data" action="" onsubmit="return CheckUpload();">
+ <span fckLang="DlgLnkUpload">Upload</span><br />
+ <input id="txtUploadFile" style="WIDTH: 100%" type="file" size="40" name="NewFile" /><br />
+ <br />
+ <input id="btnUpload" type="submit" value="Send it to the Server" fckLang="DlgLnkBtnUpload" />
+ <iframe name="UploadWindow" style="DISPLAY: none" src="javascript:void(0)"></iframe>
+ </form>
+ </div>
+ <div id="divTarget" style="DISPLAY: none">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fckLang="DlgLnkTarget">Target</span><br />
+ <select id="cmbTarget" onchange="SetTarget(this.value);">
+ <option value="" fckLang="DlgGenNotSet" selected="selected">&lt;not set&gt;</option>
+ <option value="frame" fckLang="DlgLnkTargetFrame">&lt;frame&gt;</option>
+ <option value="popup" fckLang="DlgLnkTargetPopup">&lt;popup window&gt;</option>
+ <option value="_blank" fckLang="DlgLnkTargetBlank">New Window (_blank)</option>
+ <option value="_top" fckLang="DlgLnkTargetTop">Topmost Window (_top)</option>
+ <option value="_self" fckLang="DlgLnkTargetSelf">Same Window (_self)</option>
+ <option value="_parent" fckLang="DlgLnkTargetParent">Parent Window (_parent)</option>
+ </select>
+ </td>
+ <td>&nbsp;</td>
+ <td id="tdTargetFrame" nowrap="nowrap" width="100%">
+ <span fckLang="DlgLnkTargetFrameName">Target Frame Name</span><br />
+ <input id="txtTargetFrame" style="WIDTH: 100%" type="text" onkeyup="OnTargetNameChange();"
+ onchange="OnTargetNameChange();" />
+ </td>
+ <td id="tdPopupName" style="DISPLAY: none" nowrap="nowrap" width="100%">
+ <span fckLang="DlgLnkPopWinName">Popup Window Name</span><br />
+ <input id="txtPopupName" style="WIDTH: 100%" type="text" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <table id="tablePopupFeatures" style="DISPLAY: none" cellspacing="0" cellpadding="0" align="center"
+ border="0">
+ <tr>
+ <td>
+ <span fckLang="DlgLnkPopWinFeat">Popup Window Features</span><br />
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td valign="top" nowrap="nowrap" width="50%">
+ <input id="chkPopupResizable" name="chkFeature" value="resizable" type="checkbox" /><label for="chkPopupResizable" fckLang="DlgLnkPopResize">Resizable</label><br />
+ <input id="chkPopupLocationBar" name="chkFeature" value="location" type="checkbox" /><label for="chkPopupLocationBar" fckLang="DlgLnkPopLocation">Location
+ Bar</label><br />
+ <input id="chkPopupManuBar" name="chkFeature" value="menubar" type="checkbox" /><label for="chkPopupManuBar" fckLang="DlgLnkPopMenu">Menu
+ Bar</label><br />
+ <input id="chkPopupScrollBars" name="chkFeature" value="scrollbars" type="checkbox" /><label for="chkPopupScrollBars" fckLang="DlgLnkPopScroll">Scroll
+ Bars</label>
+ </td>
+ <td></td>
+ <td valign="top" nowrap="nowrap" width="50%">
+ <input id="chkPopupStatusBar" name="chkFeature" value="status" type="checkbox" /><label for="chkPopupStatusBar" fckLang="DlgLnkPopStatus">Status
+ Bar</label><br />
+ <input id="chkPopupToolbar" name="chkFeature" value="toolbar" type="checkbox" /><label for="chkPopupToolbar" fckLang="DlgLnkPopToolbar">Toolbar</label><br />
+ <input id="chkPopupFullScreen" name="chkFeature" value="fullscreen" type="checkbox" /><label for="chkPopupFullScreen" fckLang="DlgLnkPopFullScrn">Full
+ Screen (IE)</label><br />
+ <input id="chkPopupDependent" name="chkFeature" value="dependent" type="checkbox" /><label for="chkPopupDependent" fckLang="DlgLnkPopDependent">Dependent
+ (Netscape)</label>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" nowrap="nowrap" width="50%">&nbsp;</td>
+ <td></td>
+ <td valign="top" nowrap="nowrap" width="50%"></td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap"><span fckLang="DlgLnkPopWidth">Width</span></td>
+ <td>&nbsp;<input id="txtPopupWidth" type="text" maxlength="4" size="4" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap"><span fckLang="DlgLnkPopHeight">Height</span></td>
+ <td>&nbsp;<input id="txtPopupHeight" type="text" maxlength="4" size="4" /></td>
+ </tr>
+ </table>
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap"><span fckLang="DlgLnkPopLeft">Left Position</span></td>
+ <td>&nbsp;<input id="txtPopupLeft" type="text" maxlength="4" size="4" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap"><span fckLang="DlgLnkPopTop">Top Position</span></td>
+ <td>&nbsp;<input id="txtPopupTop" type="text" maxlength="4" size="4" /></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="divAttribs" style="DISPLAY: none">
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td valign="top" width="50%">
+ <span fckLang="DlgGenId">Id</span><br />
+ <input id="txtAttId" style="WIDTH: 100%" type="text" />
+ </td>
+ <td width="1"></td>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td width="60%">
+ <span fckLang="DlgGenLangDir">Language Direction</span><br />
+ <select id="cmbAttLangDir" style="WIDTH: 100%">
+ <option value="" fckLang="DlgGenNotSet" selected>&lt;not set&gt;</option>
+ <option value="ltr" fckLang="DlgGenLangDirLtr">Left to Right (LTR)</option>
+ <option value="rtl" fckLang="DlgGenLangDirRtl">Right to Left (RTL)</option>
+ </select>
+ </td>
+ <td width="1%">&nbsp;&nbsp;&nbsp;</td>
+ <td nowrap="nowrap"><span fckLang="DlgGenAccessKey">Access Key</span><br />
+ <input id="txtAttAccessKey" style="WIDTH: 100%" type="text" maxlength="1" size="1" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" width="50%">
+ <span fckLang="DlgGenName">Name</span><br />
+ <input id="txtAttName" style="WIDTH: 100%" type="text" />
+ </td>
+ <td width="1"></td>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td width="60%">
+ <span fckLang="DlgGenLangCode">Language Code</span><br />
+ <input id="txtAttLangCode" style="WIDTH: 100%" type="text" />
+ </td>
+ <td width="1%">&nbsp;&nbsp;&nbsp;</td>
+ <td nowrap="nowrap">
+ <span fckLang="DlgGenTabIndex">Tab Index</span><br />
+ <input id="txtAttTabIndex" style="WIDTH: 100%" type="text" maxlength="5" size="5" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" width="50%">&nbsp;</td>
+ <td width="1"></td>
+ <td valign="top"></td>
+ </tr>
+ <tr>
+ <td valign="top" width="50%">
+ <span fckLang="DlgGenTitle">Advisory Title</span><br />
+ <input id="txtAttTitle" style="WIDTH: 100%" type="text" />
+ </td>
+ <td width="1">&nbsp;&nbsp;&nbsp;</td>
+ <td valign="top">
+ <span fckLang="DlgGenContType">Advisory Content Type</span><br />
+ <input id="txtAttContentType" style="WIDTH: 100%" type="text" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <span fckLang="DlgGenClass">Stylesheet Classes</span><br />
+ <input id="txtAttClasses" style="WIDTH: 100%" type="text" />
+ </td>
+ <td></td>
+ <td valign="top">
+ <span fckLang="DlgGenLinkCharset">Linked Resource Charset</span><br />
+ <input id="txtAttCharSet" style="WIDTH: 100%" type="text" />
+ </td>
+ </tr>
+ </table>
+ <table cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
+ <tr>
+ <td>
+ <span fckLang="DlgGenStyle">Style</span><br />
+ <input id="txtAttStyle" style="WIDTH: 100%" type="text" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_link/fck_link.js b/httemplate/elements/fckeditor/editor/dialog/fck_link/fck_link.js
new file mode 100644
index 000000000..6d96499df
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_link/fck_link.js
@@ -0,0 +1,698 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Scripts related to the Link dialog window (see fck_link.html).
+ */
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKLang = oEditor.FCKLang ;
+var FCKConfig = oEditor.FCKConfig ;
+var FCKRegexLib = oEditor.FCKRegexLib ;
+
+//#### Dialog Tabs
+
+// Set the dialog tabs.
+window.parent.AddTab( 'Info', FCKLang.DlgLnkInfoTab ) ;
+
+if ( !FCKConfig.LinkDlgHideTarget )
+ window.parent.AddTab( 'Target', FCKLang.DlgLnkTargetTab, true ) ;
+
+if ( FCKConfig.LinkUpload )
+ window.parent.AddTab( 'Upload', FCKLang.DlgLnkUpload, true ) ;
+
+if ( !FCKConfig.LinkDlgHideAdvanced )
+ window.parent.AddTab( 'Advanced', FCKLang.DlgAdvancedTag ) ;
+
+// Function called when a dialog tag is selected.
+function OnDialogTabChange( tabCode )
+{
+ ShowE('divInfo' , ( tabCode == 'Info' ) ) ;
+ ShowE('divTarget' , ( tabCode == 'Target' ) ) ;
+ ShowE('divUpload' , ( tabCode == 'Upload' ) ) ;
+ ShowE('divAttribs' , ( tabCode == 'Advanced' ) ) ;
+
+ window.parent.SetAutoSize( true ) ;
+}
+
+//#### Regular Expressions library.
+var oRegex = new Object() ;
+
+oRegex.UriProtocol = /^(((http|https|ftp|news):\/\/)|mailto:)/gi ;
+
+oRegex.UrlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/gi ;
+
+oRegex.UrlOnChangeTestOther = /^((javascript:)|[#\/\.])/gi ;
+
+oRegex.ReserveTarget = /^_(blank|self|top|parent)$/i ;
+
+oRegex.PopupUri = /^javascript:void\(\s*window.open\(\s*'([^']+)'\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*\)\s*$/ ;
+
+// Accessible popups
+oRegex.OnClickPopup = /^\s*on[cC]lick="\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*"$/ ;
+
+oRegex.PopupFeatures = /(?:^|,)([^=]+)=(\d+|yes|no)/gi ;
+
+//#### Parser Functions
+
+var oParser = new Object() ;
+
+oParser.ParseEMailUrl = function( emailUrl )
+{
+ // Initializes the EMailInfo object.
+ var oEMailInfo = new Object() ;
+ oEMailInfo.Address = '' ;
+ oEMailInfo.Subject = '' ;
+ oEMailInfo.Body = '' ;
+
+ var oParts = emailUrl.match( /^([^\?]+)\??(.+)?/ ) ;
+ if ( oParts )
+ {
+ // Set the e-mail address.
+ oEMailInfo.Address = oParts[1] ;
+
+ // Look for the optional e-mail parameters.
+ if ( oParts[2] )
+ {
+ var oMatch = oParts[2].match( /(^|&)subject=([^&]+)/i ) ;
+ if ( oMatch ) oEMailInfo.Subject = decodeURIComponent( oMatch[2] ) ;
+
+ oMatch = oParts[2].match( /(^|&)body=([^&]+)/i ) ;
+ if ( oMatch ) oEMailInfo.Body = decodeURIComponent( oMatch[2] ) ;
+ }
+ }
+
+ return oEMailInfo ;
+}
+
+oParser.CreateEMailUri = function( address, subject, body )
+{
+ var sBaseUri = 'mailto:' + address ;
+
+ var sParams = '' ;
+
+ if ( subject.length > 0 )
+ sParams = '?subject=' + encodeURIComponent( subject ) ;
+
+ if ( body.length > 0 )
+ {
+ sParams += ( sParams.length == 0 ? '?' : '&' ) ;
+ sParams += 'body=' + encodeURIComponent( body ) ;
+ }
+
+ return sBaseUri + sParams ;
+}
+
+//#### Initialization Code
+
+// oLink: The actual selected link in the editor.
+var oLink = FCK.Selection.MoveToAncestorNode( 'A' ) ;
+if ( oLink )
+ FCK.Selection.SelectNode( oLink ) ;
+
+window.onload = function()
+{
+ // Translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ // Fill the Anchor Names and Ids combos.
+ LoadAnchorNamesAndIds() ;
+
+ // Load the selected link information (if any).
+ LoadSelection() ;
+
+ // Update the dialog box.
+ SetLinkType( GetE('cmbLinkType').value ) ;
+
+ // Show/Hide the "Browse Server" button.
+ GetE('divBrowseServer').style.display = FCKConfig.LinkBrowser ? '' : 'none' ;
+
+ // Show the initial dialog content.
+ GetE('divInfo').style.display = '' ;
+
+ // Set the actual uploader URL.
+ if ( FCKConfig.LinkUpload )
+ GetE('frmUpload').action = FCKConfig.LinkUploadURL ;
+
+ // Set the default target (from configuration).
+ SetDefaultTarget() ;
+
+ // Activate the "OK" button.
+ window.parent.SetOkButton( true ) ;
+}
+
+var bHasAnchors ;
+
+function LoadAnchorNamesAndIds()
+{
+ // Since version 2.0, the anchors are replaced in the DOM by IMGs so the user see the icon
+ // to edit them. So, we must look for that images now.
+ var aAnchors = new Array() ;
+ var i ;
+ var oImages = oEditor.FCK.EditorDocument.getElementsByTagName( 'IMG' ) ;
+ for( i = 0 ; i < oImages.length ; i++ )
+ {
+ if ( oImages[i].getAttribute('_fckanchor') )
+ aAnchors[ aAnchors.length ] = oEditor.FCK.GetRealElement( oImages[i] ) ;
+ }
+
+ // Add also real anchors
+ var oLinks = oEditor.FCK.EditorDocument.getElementsByTagName( 'A' ) ;
+ for( i = 0 ; i < oLinks.length ; i++ )
+ {
+ if ( oLinks[i].name && ( oLinks[i].name.length > 0 ) )
+ aAnchors[ aAnchors.length ] = oLinks[i] ;
+ }
+
+ var aIds = oEditor.FCKTools.GetAllChildrenIds( oEditor.FCK.EditorDocument.body ) ;
+
+ bHasAnchors = ( aAnchors.length > 0 || aIds.length > 0 ) ;
+
+ for ( i = 0 ; i < aAnchors.length ; i++ )
+ {
+ var sName = aAnchors[i].name ;
+ if ( sName && sName.length > 0 )
+ oEditor.FCKTools.AddSelectOption( GetE('cmbAnchorName'), sName, sName ) ;
+ }
+
+ for ( i = 0 ; i < aIds.length ; i++ )
+ {
+ oEditor.FCKTools.AddSelectOption( GetE('cmbAnchorId'), aIds[i], aIds[i] ) ;
+ }
+
+ ShowE( 'divSelAnchor' , bHasAnchors ) ;
+ ShowE( 'divNoAnchor' , !bHasAnchors ) ;
+}
+
+function LoadSelection()
+{
+ if ( !oLink ) return ;
+
+ var sType = 'url' ;
+
+ // Get the actual Link href.
+ var sHRef = oLink.getAttribute( '_fcksavedurl' ) ;
+ if ( sHRef == null )
+ sHRef = oLink.getAttribute( 'href' , 2 ) || '' ;
+
+ // Look for a popup javascript link.
+ var oPopupMatch = oRegex.PopupUri.exec( sHRef ) ;
+ if( oPopupMatch )
+ {
+ GetE('cmbTarget').value = 'popup' ;
+ sHRef = oPopupMatch[1] ;
+ FillPopupFields( oPopupMatch[2], oPopupMatch[3] ) ;
+ SetTarget( 'popup' ) ;
+ }
+
+ // Accesible popups, the popup data is in the onclick attribute
+ if ( !oPopupMatch ) {
+ var onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ;
+ oPopupMatch = oRegex.OnClickPopup.exec( onclick ) ;
+ if( oPopupMatch )
+ {
+ GetE( 'cmbTarget' ).value = 'popup' ;
+ FillPopupFields( oPopupMatch[1], oPopupMatch[2] ) ;
+ SetTarget( 'popup' ) ;
+ }
+ }
+
+ // Search for the protocol.
+ var sProtocol = oRegex.UriProtocol.exec( sHRef ) ;
+
+ if ( sProtocol )
+ {
+ sProtocol = sProtocol[0].toLowerCase() ;
+ GetE('cmbLinkProtocol').value = sProtocol ;
+
+ // Remove the protocol and get the remainig URL.
+ var sUrl = sHRef.replace( oRegex.UriProtocol, '' ) ;
+
+ if ( sProtocol == 'mailto:' ) // It is an e-mail link.
+ {
+ sType = 'email' ;
+
+ var oEMailInfo = oParser.ParseEMailUrl( sUrl ) ;
+ GetE('txtEMailAddress').value = oEMailInfo.Address ;
+ GetE('txtEMailSubject').value = oEMailInfo.Subject ;
+ GetE('txtEMailBody').value = oEMailInfo.Body ;
+ }
+ else // It is a normal link.
+ {
+ sType = 'url' ;
+ GetE('txtUrl').value = sUrl ;
+ }
+ }
+ else if ( sHRef.substr(0,1) == '#' && sHRef.length > 1 ) // It is an anchor link.
+ {
+ sType = 'anchor' ;
+ GetE('cmbAnchorName').value = GetE('cmbAnchorId').value = sHRef.substr(1) ;
+ }
+ else // It is another type of link.
+ {
+ sType = 'url' ;
+
+ GetE('cmbLinkProtocol').value = '' ;
+ GetE('txtUrl').value = sHRef ;
+ }
+
+ if ( !oPopupMatch )
+ {
+ // Get the target.
+ var sTarget = oLink.target ;
+
+ if ( sTarget && sTarget.length > 0 )
+ {
+ if ( oRegex.ReserveTarget.test( sTarget ) )
+ {
+ sTarget = sTarget.toLowerCase() ;
+ GetE('cmbTarget').value = sTarget ;
+ }
+ else
+ GetE('cmbTarget').value = 'frame' ;
+ GetE('txtTargetFrame').value = sTarget ;
+ }
+ }
+
+ // Get Advances Attributes
+ GetE('txtAttId').value = oLink.id ;
+ GetE('txtAttName').value = oLink.name ;
+ GetE('cmbAttLangDir').value = oLink.dir ;
+ GetE('txtAttLangCode').value = oLink.lang ;
+ GetE('txtAttAccessKey').value = oLink.accessKey ;
+ GetE('txtAttTabIndex').value = oLink.tabIndex <= 0 ? '' : oLink.tabIndex ;
+ GetE('txtAttTitle').value = oLink.title ;
+ GetE('txtAttContentType').value = oLink.type ;
+ GetE('txtAttCharSet').value = oLink.charset ;
+
+ var sClass ;
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ sClass = oLink.getAttribute('className',2) || '' ;
+ // Clean up temporary classes for internal use:
+ sClass = sClass.replace( FCKRegexLib.FCK_Class, '' ) ;
+
+ GetE('txtAttStyle').value = oLink.style.cssText ;
+ }
+ else
+ {
+ sClass = oLink.getAttribute('class',2) || '' ;
+ GetE('txtAttStyle').value = oLink.getAttribute('style',2) || '' ;
+ }
+ GetE('txtAttClasses').value = sClass ;
+
+ // Update the Link type combo.
+ GetE('cmbLinkType').value = sType ;
+}
+
+//#### Link type selection.
+function SetLinkType( linkType )
+{
+ ShowE('divLinkTypeUrl' , (linkType == 'url') ) ;
+ ShowE('divLinkTypeAnchor' , (linkType == 'anchor') ) ;
+ ShowE('divLinkTypeEMail' , (linkType == 'email') ) ;
+
+ if ( !FCKConfig.LinkDlgHideTarget )
+ window.parent.SetTabVisibility( 'Target' , (linkType == 'url') ) ;
+
+ if ( FCKConfig.LinkUpload )
+ window.parent.SetTabVisibility( 'Upload' , (linkType == 'url') ) ;
+
+ if ( !FCKConfig.LinkDlgHideAdvanced )
+ window.parent.SetTabVisibility( 'Advanced' , (linkType != 'anchor' || bHasAnchors) ) ;
+
+ if ( linkType == 'email' )
+ window.parent.SetAutoSize( true ) ;
+}
+
+//#### Target type selection.
+function SetTarget( targetType )
+{
+ GetE('tdTargetFrame').style.display = ( targetType == 'popup' ? 'none' : '' ) ;
+ GetE('tdPopupName').style.display =
+ GetE('tablePopupFeatures').style.display = ( targetType == 'popup' ? '' : 'none' ) ;
+
+ switch ( targetType )
+ {
+ case "_blank" :
+ case "_self" :
+ case "_parent" :
+ case "_top" :
+ GetE('txtTargetFrame').value = targetType ;
+ break ;
+ case "" :
+ GetE('txtTargetFrame').value = '' ;
+ break ;
+ }
+
+ if ( targetType == 'popup' )
+ window.parent.SetAutoSize( true ) ;
+}
+
+//#### Called while the user types the URL.
+function OnUrlChange()
+{
+ var sUrl = GetE('txtUrl').value ;
+ var sProtocol = oRegex.UrlOnChangeProtocol.exec( sUrl ) ;
+
+ if ( sProtocol )
+ {
+ sUrl = sUrl.substr( sProtocol[0].length ) ;
+ GetE('txtUrl').value = sUrl ;
+ GetE('cmbLinkProtocol').value = sProtocol[0].toLowerCase() ;
+ }
+ else if ( oRegex.UrlOnChangeTestOther.test( sUrl ) )
+ {
+ GetE('cmbLinkProtocol').value = '' ;
+ }
+}
+
+//#### Called while the user types the target name.
+function OnTargetNameChange()
+{
+ var sFrame = GetE('txtTargetFrame').value ;
+
+ if ( sFrame.length == 0 )
+ GetE('cmbTarget').value = '' ;
+ else if ( oRegex.ReserveTarget.test( sFrame ) )
+ GetE('cmbTarget').value = sFrame.toLowerCase() ;
+ else
+ GetE('cmbTarget').value = 'frame' ;
+}
+
+// Accesible popups
+function BuildOnClickPopup()
+{
+ var sWindowName = "'" + GetE('txtPopupName').value.replace(/\W/gi, "") + "'" ;
+
+ var sFeatures = '' ;
+ var aChkFeatures = document.getElementsByName( 'chkFeature' ) ;
+ for ( var i = 0 ; i < aChkFeatures.length ; i++ )
+ {
+ if ( i > 0 ) sFeatures += ',' ;
+ sFeatures += aChkFeatures[i].value + '=' + ( aChkFeatures[i].checked ? 'yes' : 'no' ) ;
+ }
+
+ if ( GetE('txtPopupWidth').value.length > 0 ) sFeatures += ',width=' + GetE('txtPopupWidth').value ;
+ if ( GetE('txtPopupHeight').value.length > 0 ) sFeatures += ',height=' + GetE('txtPopupHeight').value ;
+ if ( GetE('txtPopupLeft').value.length > 0 ) sFeatures += ',left=' + GetE('txtPopupLeft').value ;
+ if ( GetE('txtPopupTop').value.length > 0 ) sFeatures += ',top=' + GetE('txtPopupTop').value ;
+
+ if ( sFeatures != '' )
+ sFeatures = sFeatures + ",status" ;
+
+ return ( "window.open(this.href," + sWindowName + ",'" + sFeatures + "'); return false" ) ;
+}
+
+//#### Fills all Popup related fields.
+function FillPopupFields( windowName, features )
+{
+ if ( windowName )
+ GetE('txtPopupName').value = windowName ;
+
+ var oFeatures = new Object() ;
+ var oFeaturesMatch ;
+ while( ( oFeaturesMatch = oRegex.PopupFeatures.exec( features ) ) != null )
+ {
+ var sValue = oFeaturesMatch[2] ;
+ if ( sValue == ( 'yes' || '1' ) )
+ oFeatures[ oFeaturesMatch[1] ] = true ;
+ else if ( ! isNaN( sValue ) && sValue != 0 )
+ oFeatures[ oFeaturesMatch[1] ] = sValue ;
+ }
+
+ // Update all features check boxes.
+ var aChkFeatures = document.getElementsByName('chkFeature') ;
+ for ( var i = 0 ; i < aChkFeatures.length ; i++ )
+ {
+ if ( oFeatures[ aChkFeatures[i].value ] )
+ aChkFeatures[i].checked = true ;
+ }
+
+ // Update position and size text boxes.
+ if ( oFeatures['width'] ) GetE('txtPopupWidth').value = oFeatures['width'] ;
+ if ( oFeatures['height'] ) GetE('txtPopupHeight').value = oFeatures['height'] ;
+ if ( oFeatures['left'] ) GetE('txtPopupLeft').value = oFeatures['left'] ;
+ if ( oFeatures['top'] ) GetE('txtPopupTop').value = oFeatures['top'] ;
+}
+
+//#### The OK button was hit.
+function Ok()
+{
+ var sUri, sInnerHtml ;
+
+ switch ( GetE('cmbLinkType').value )
+ {
+ case 'url' :
+ sUri = GetE('txtUrl').value ;
+
+ if ( sUri.length == 0 )
+ {
+ alert( FCKLang.DlnLnkMsgNoUrl ) ;
+ return false ;
+ }
+
+ sUri = GetE('cmbLinkProtocol').value + sUri ;
+
+ break ;
+
+ case 'email' :
+ sUri = GetE('txtEMailAddress').value ;
+
+ if ( sUri.length == 0 )
+ {
+ alert( FCKLang.DlnLnkMsgNoEMail ) ;
+ return false ;
+ }
+
+ sUri = oParser.CreateEMailUri(
+ sUri,
+ GetE('txtEMailSubject').value,
+ GetE('txtEMailBody').value ) ;
+ break ;
+
+ case 'anchor' :
+ var sAnchor = GetE('cmbAnchorName').value ;
+ if ( sAnchor.length == 0 ) sAnchor = GetE('cmbAnchorId').value ;
+
+ if ( sAnchor.length == 0 )
+ {
+ alert( FCKLang.DlnLnkMsgNoAnchor ) ;
+ return false ;
+ }
+
+ sUri = '#' + sAnchor ;
+ break ;
+ }
+
+ // If no link is selected, create a new one (it may result in more than one link creation - #220).
+ var aLinks = oLink ? [ oLink ] : oEditor.FCK.CreateLink( sUri ) ;
+
+ // If no selection, no links are created, so use the uri as the link text (by dom, 2006-05-26)
+ var aHasSelection = ( aLinks.length > 0 ) ;
+ if ( !aHasSelection )
+ {
+ sInnerHtml = sUri;
+
+ // Built a better text for empty links.
+ switch ( GetE('cmbLinkType').value )
+ {
+ // anchor: use old behavior --> return true
+ case 'anchor':
+ sInnerHtml = sInnerHtml.replace( /^#/, '' ) ;
+ break ;
+
+ // url: try to get path
+ case 'url':
+ var oLinkPathRegEx = new RegExp("//?([^?\"']+)([?].*)?$") ;
+ var asLinkPath = oLinkPathRegEx.exec( sUri ) ;
+ if (asLinkPath != null)
+ sInnerHtml = asLinkPath[1]; // use matched path
+ break ;
+
+ // mailto: try to get email address
+ case 'email':
+ sInnerHtml = GetE('txtEMailAddress').value ;
+ break ;
+ }
+
+ // Create a new (empty) anchor.
+ aLinks = [ oEditor.FCK.CreateElement( 'a' ) ] ;
+ }
+
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ for ( var i = 0 ; i < aLinks.length ; i++ )
+ {
+ oLink = aLinks[i] ;
+
+ if ( aHasSelection )
+ sInnerHtml = oLink.innerHTML ; // Save the innerHTML (IE changes it if it is like an URL).
+
+ oLink.href = sUri ;
+ SetAttribute( oLink, '_fcksavedurl', sUri ) ;
+
+ // Accesible popups
+ if( GetE('cmbTarget').value == 'popup' )
+ {
+ SetAttribute( oLink, 'onclick_fckprotectedatt', " onclick=\"" + BuildOnClickPopup() + "\"") ;
+ }
+ else
+ {
+ // Check if the previous onclick was for a popup:
+ // In that case remove the onclick handler.
+ var onclick = oLink.getAttribute( 'onclick_fckprotectedatt' ) ;
+ if( oRegex.OnClickPopup.test( onclick ) )
+ SetAttribute( oLink, 'onclick_fckprotectedatt', '' ) ;
+ }
+
+ oLink.innerHTML = sInnerHtml ; // Set (or restore) the innerHTML
+
+ // Target
+ if( GetE('cmbTarget').value != 'popup' )
+ SetAttribute( oLink, 'target', GetE('txtTargetFrame').value ) ;
+ else
+ SetAttribute( oLink, 'target', null ) ;
+
+ // Let's set the "id" only for the first link to avoid duplication.
+ if ( i == 0 )
+ SetAttribute( oLink, 'id', GetE('txtAttId').value ) ;
+
+ // Advances Attributes
+ SetAttribute( oLink, 'name' , GetE('txtAttName').value ) ;
+ SetAttribute( oLink, 'dir' , GetE('cmbAttLangDir').value ) ;
+ SetAttribute( oLink, 'lang' , GetE('txtAttLangCode').value ) ;
+ SetAttribute( oLink, 'accesskey', GetE('txtAttAccessKey').value ) ;
+ SetAttribute( oLink, 'tabindex' , ( GetE('txtAttTabIndex').value > 0 ? GetE('txtAttTabIndex').value : null ) ) ;
+ SetAttribute( oLink, 'title' , GetE('txtAttTitle').value ) ;
+ SetAttribute( oLink, 'type' , GetE('txtAttContentType').value ) ;
+ SetAttribute( oLink, 'charset' , GetE('txtAttCharSet').value ) ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ {
+ var sClass = GetE('txtAttClasses').value ;
+ // If it's also an anchor add an internal class
+ if ( GetE('txtAttName').value.length != 0 )
+ sClass += ' FCK__AnchorC' ;
+ SetAttribute( oLink, 'className', sClass ) ;
+
+ oLink.style.cssText = GetE('txtAttStyle').value ;
+ }
+ else
+ {
+ SetAttribute( oLink, 'class', GetE('txtAttClasses').value ) ;
+ SetAttribute( oLink, 'style', GetE('txtAttStyle').value ) ;
+ }
+ }
+
+ // Select the (first) link.
+ oEditor.FCKSelection.SelectNode( aLinks[0] );
+
+ return true ;
+}
+
+function BrowseServer()
+{
+ OpenFileBrowser( FCKConfig.LinkBrowserURL, FCKConfig.LinkBrowserWindowWidth, FCKConfig.LinkBrowserWindowHeight ) ;
+}
+
+function SetUrl( url )
+{
+ document.getElementById('txtUrl').value = url ;
+ OnUrlChange() ;
+ window.parent.SetSelectedTab( 'Info' ) ;
+}
+
+function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg )
+{
+ switch ( errorNumber )
+ {
+ case 0 : // No errors
+ alert( 'Your file has been successfully uploaded' ) ;
+ break ;
+ case 1 : // Custom error
+ alert( customMsg ) ;
+ return ;
+ case 101 : // Custom warning
+ alert( customMsg ) ;
+ break ;
+ case 201 :
+ alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ;
+ break ;
+ case 202 :
+ alert( 'Invalid file type' ) ;
+ return ;
+ case 203 :
+ alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ;
+ return ;
+ default :
+ alert( 'Error on file upload. Error number: ' + errorNumber ) ;
+ return ;
+ }
+
+ SetUrl( fileUrl ) ;
+ GetE('frmUpload').reset() ;
+}
+
+var oUploadAllowedExtRegex = new RegExp( FCKConfig.LinkUploadAllowedExtensions, 'i' ) ;
+var oUploadDeniedExtRegex = new RegExp( FCKConfig.LinkUploadDeniedExtensions, 'i' ) ;
+
+function CheckUpload()
+{
+ var sFile = GetE('txtUploadFile').value ;
+
+ if ( sFile.length == 0 )
+ {
+ alert( 'Please select a file to upload' ) ;
+ return false ;
+ }
+
+ if ( ( FCKConfig.LinkUploadAllowedExtensions.length > 0 && !oUploadAllowedExtRegex.test( sFile ) ) ||
+ ( FCKConfig.LinkUploadDeniedExtensions.length > 0 && oUploadDeniedExtRegex.test( sFile ) ) )
+ {
+ OnUploadCompleted( 202 ) ;
+ return false ;
+ }
+
+ return true ;
+}
+
+function SetDefaultTarget()
+{
+ var target = FCKConfig.DefaultLinkTarget + '' ;
+
+ if ( oLink || target.length == 0 )
+ return ;
+
+ switch ( target )
+ {
+ case '_blank' :
+ case '_self' :
+ case '_parent' :
+ case '_top' :
+ GetE('cmbTarget').value = target ;
+ break ;
+ default :
+ GetE('cmbTarget').value = 'frame' ;
+ break ;
+ }
+
+ GetE('txtTargetFrame').value = target ;
+}
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_listprop.html b/httemplate/elements/fckeditor/editor/dialog/fck_listprop.html
new file mode 100644
index 000000000..a0a927e13
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_listprop.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Bulleted List dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+var sListType = ( location.search == '?OL' ? 'OL' : 'UL' ) ;
+
+var oActiveEl = oEditor.FCKSelection.MoveToAncestorNode( sListType ) ;
+var oActiveSel ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( sListType == 'UL' )
+ oActiveSel = GetE('selBulleted') ;
+ else
+ {
+ if ( oActiveEl )
+ {
+ oActiveSel = GetE('selNumbered') ;
+ GetE('eStart').style.display = '' ;
+ GetE('txtStartPosition').value = GetAttribute( oActiveEl, 'start' ) ;
+ }
+ }
+
+ oActiveSel.style.display = '' ;
+
+ if ( oActiveEl )
+ {
+ if ( oActiveEl.getAttribute('type') )
+ oActiveSel.value = oActiveEl.getAttribute('type') ;
+ }
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( oActiveEl ){
+ SetAttribute( oActiveEl, 'type' , oActiveSel.value ) ;
+ if(oActiveEl.tagName == 'OL')
+ SetAttribute( oActiveEl, 'start', GetE('txtStartPosition').value ) ;
+ }
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table width="100%" style="height: 100%">
+ <tr>
+ <td style="text-align:center">
+ <table cellspacing="0" cellpadding="0" border="0" style="margin-left: auto; margin-right: auto;">
+ <tr>
+ <td id="eStart" style="display: none; padding-right: 5px; padding-left: 5px">
+ <span fcklang="DlgLstStart">Start</span><br />
+ <input type="text" id="txtStartPosition" size="5" />
+ </td>
+ <td style="padding-right: 5px; padding-left: 5px">
+ <span fcklang="DlgLstType">List Type</span><br />
+ <select id="selBulleted" style="display: none">
+ <option value="" selected="selected"></option>
+ <option value="circle" fcklang="DlgLstTypeCircle">Circle</option>
+ <option value="disc" fcklang="DlgLstTypeDisc">Disc</option>
+ <option value="square" fcklang="DlgLstTypeSquare">Square</option>
+ </select>
+ <select id="selNumbered" style="display: none">
+ <option value="" selected="selected"></option>
+ <option value="1" fcklang="DlgLstTypeNumbers">Numbers (1, 2, 3)</option>
+ <option value="a" fcklang="DlgLstTypeLCase">Lowercase Letters (a, b, c)</option>
+ <option value="A" fcklang="DlgLstTypeUCase">Uppercase Letters (A, B, C)</option>
+ <option value="i" fcklang="DlgLstTypeSRoman">Small Roman Numerals (i, ii, iii)</option>
+ <option value="I" fcklang="DlgLstTypeLRoman">Large Roman Numerals (I, II, III)</option>
+ </select>
+ &nbsp;
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_paste.html b/httemplate/elements/fckeditor/editor/dialog/fck_paste.html
new file mode 100644
index 000000000..fd16c317a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_paste.html
@@ -0,0 +1,285 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This dialog is shown when, for some reason (usually security settings),
+ * the user is not able to paste data from the clipboard to the editor using
+ * the toolbar buttons or the context menu.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+
+ <script type="text/javascript">
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK;
+var FCKTools = oEditor.FCKTools ;
+var FCKConfig = oEditor.FCKConfig ;
+
+window.onload = function ()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ var sPastingType = window.parent.dialogArguments.CustomValue ;
+
+ if ( sPastingType == 'Word' || sPastingType == 'Security' )
+ {
+ if ( sPastingType == 'Security' )
+ document.getElementById( 'xSecurityMsg' ).style.display = '' ;
+
+ var oFrame = document.getElementById('frmData') ;
+ oFrame.style.display = '' ;
+
+ if ( oFrame.contentDocument )
+ oFrame.contentDocument.designMode = 'on' ;
+ else
+ oFrame.contentWindow.document.body.contentEditable = true ;
+ }
+ else
+ {
+ document.getElementById('txtData').style.display = '' ;
+ }
+
+ if ( sPastingType != 'Word' )
+ document.getElementById('oWordCommands').style.display = 'none' ;
+
+ window.parent.SetOkButton( true ) ;
+ window.parent.SetAutoSize( true ) ;
+}
+
+function Ok()
+{
+ var sHtml ;
+
+ var sPastingType = window.parent.dialogArguments.CustomValue ;
+
+ if ( sPastingType == 'Word' || sPastingType == 'Security' )
+ {
+ var oFrame = document.getElementById('frmData') ;
+ var oBody ;
+
+ if ( oFrame.contentDocument )
+ oBody = oFrame.contentDocument.body ;
+ else
+ oBody = oFrame.contentWindow.document.body ;
+
+ if ( sPastingType == 'Word' )
+ {
+ // If a plugin creates a FCK.CustomCleanWord function it will be called instead of the default one
+ if ( typeof( FCK.CustomCleanWord ) == 'function' )
+ sHtml = FCK.CustomCleanWord( oBody, document.getElementById('chkRemoveFont').checked, document.getElementById('chkRemoveStyles').checked ) ;
+ else
+ sHtml = CleanWord( oBody, document.getElementById('chkRemoveFont').checked, document.getElementById('chkRemoveStyles').checked ) ;
+ }
+ else
+ sHtml = oBody.innerHTML ;
+
+ // Fix relative anchor URLs (IE automatically adds the current page URL).
+ var re = new RegExp( window.location + "#", "g" ) ;
+ sHtml = sHtml.replace( re, '#') ;
+ }
+ else
+ {
+ sHtml = oEditor.FCKTools.HTMLEncode( document.getElementById('txtData').value ) ;
+ sHtml = sHtml.replace( /\n/g, '<BR>' ) ;
+ }
+
+ oEditor.FCK.InsertHtml( sHtml ) ;
+
+ return true ;
+}
+
+function CleanUpBox()
+{
+ var oFrame = document.getElementById('frmData') ;
+
+ if ( oFrame.contentDocument )
+ oFrame.contentDocument.body.innerHTML = '' ;
+ else
+ oFrame.contentWindow.document.body.innerHTML = '' ;
+}
+
+
+// This function will be called from the PasteFromWord dialog (fck_paste.html)
+// Input: oNode a DOM node that contains the raw paste from the clipboard
+// bIgnoreFont, bRemoveStyles booleans according to the values set in the dialog
+// Output: the cleaned string
+function CleanWord( oNode, bIgnoreFont, bRemoveStyles )
+{
+ var html = oNode.innerHTML ;
+
+ html = html.replace(/<o:p>\s*<\/o:p>/g, '') ;
+ html = html.replace(/<o:p>.*?<\/o:p>/g, '&nbsp;') ;
+
+ // Remove mso-xxx styles.
+ html = html.replace( /\s*mso-[^:]+:[^;"]+;?/gi, '' ) ;
+
+ // Remove margin styles.
+ html = html.replace( /\s*MARGIN: 0cm 0cm 0pt\s*;/gi, '' ) ;
+ html = html.replace( /\s*MARGIN: 0cm 0cm 0pt\s*"/gi, "\"" ) ;
+
+ html = html.replace( /\s*TEXT-INDENT: 0cm\s*;/gi, '' ) ;
+ html = html.replace( /\s*TEXT-INDENT: 0cm\s*"/gi, "\"" ) ;
+
+ html = html.replace( /\s*TEXT-ALIGN: [^\s;]+;?"/gi, "\"" ) ;
+
+ html = html.replace( /\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\"" ) ;
+
+ html = html.replace( /\s*FONT-VARIANT: [^\s;]+;?"/gi, "\"" ) ;
+
+ html = html.replace( /\s*tab-stops:[^;"]*;?/gi, '' ) ;
+ html = html.replace( /\s*tab-stops:[^"]*/gi, '' ) ;
+
+ // Remove FONT face attributes.
+ if ( bIgnoreFont )
+ {
+ html = html.replace( /\s*face="[^"]*"/gi, '' ) ;
+ html = html.replace( /\s*face=[^ >]*/gi, '' ) ;
+
+ html = html.replace( /\s*FONT-FAMILY:[^;"]*;?/gi, '' ) ;
+ }
+
+ // Remove Class attributes
+ html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3") ;
+
+ // Remove styles.
+ if ( bRemoveStyles )
+ html = html.replace( /<(\w[^>]*) style="([^\"]*)"([^>]*)/gi, "<$1$3" ) ;
+
+ // Remove empty styles.
+ html = html.replace( /\s*style="\s*"/gi, '' ) ;
+
+ html = html.replace( /<SPAN\s*[^>]*>\s*&nbsp;\s*<\/SPAN>/gi, '&nbsp;' ) ;
+
+ html = html.replace( /<SPAN\s*[^>]*><\/SPAN>/gi, '' ) ;
+
+ // Remove Lang attributes
+ html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ;
+
+ html = html.replace( /<SPAN\s*>(.*?)<\/SPAN>/gi, '$1' ) ;
+
+ html = html.replace( /<FONT\s*>(.*?)<\/FONT>/gi, '$1' ) ;
+
+ // Remove XML elements and declarations
+ html = html.replace(/<\\?\?xml[^>]*>/gi, '' ) ;
+
+ // Remove Tags with XML namespace declarations: <o:p><\/o:p>
+ html = html.replace(/<\/?\w+:[^>]*>/gi, '' ) ;
+
+ // Remove comments [SF BUG-1481861].
+ html = html.replace(/<\!--.*-->/g, '' ) ;
+
+ html = html.replace( /<(U|I|STRIKE)>&nbsp;<\/\1>/g, '&nbsp;' ) ;
+
+ html = html.replace( /<H\d>\s*<\/H\d>/gi, '' ) ;
+
+ // Remove "display:none" tags.
+ html = html.replace( /<(\w+)[^>]*\sstyle="[^"]*DISPLAY\s?:\s?none(.*?)<\/\1>/ig, '' ) ;
+
+ if ( FCKConfig.CleanWordKeepsStructure )
+ {
+ // The original <Hn> tag send from Word is something like this: <Hn style="margin-top:0px;margin-bottom:0px">
+ html = html.replace( /<H(\d)([^>]*)>/gi, '<h$1>' ) ;
+
+ // Word likes to insert extra <font> tags, when using MSIE. (Wierd).
+ html = html.replace( /<(H\d)><FONT[^>]*>(.*?)<\/FONT><\/\1>/gi, '<$1>$2<\/$1>' );
+ html = html.replace( /<(H\d)><EM>(.*?)<\/EM><\/\1>/gi, '<$1>$2<\/$1>' );
+ }
+ else
+ {
+ html = html.replace( /<H1([^>]*)>/gi, '<div$1><b><font size="6">' ) ;
+ html = html.replace( /<H2([^>]*)>/gi, '<div$1><b><font size="5">' ) ;
+ html = html.replace( /<H3([^>]*)>/gi, '<div$1><b><font size="4">' ) ;
+ html = html.replace( /<H4([^>]*)>/gi, '<div$1><b><font size="3">' ) ;
+ html = html.replace( /<H5([^>]*)>/gi, '<div$1><b><font size="2">' ) ;
+ html = html.replace( /<H6([^>]*)>/gi, '<div$1><b><font size="1">' ) ;
+
+ html = html.replace( /<\/H\d>/gi, '<\/font><\/b><\/div>' ) ;
+
+ // Transform <P> to <DIV>
+ var re = new RegExp( '(<P)([^>]*>.*?)(<\/P>)', 'gi' ) ; // Different because of a IE 5.0 error
+ html = html.replace( re, '<div$2<\/div>' ) ;
+
+ // Remove empty tags (three times, just to be sure).
+ // This also removes any empty anchor
+ html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
+ html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
+ html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
+ }
+
+ return html ;
+}
+
+ </script>
+
+</head>
+<body style="overflow: hidden">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 98%">
+ <tr>
+ <td>
+ <div id="xSecurityMsg" style="display: none">
+ <span fcklang="DlgPasteSec">Because of your browser security settings,
+ the editor is not able to access your clipboard data directly. You are required
+ to paste it again in this window.</span><br />
+ &nbsp;
+ </div>
+ <div>
+ <span fcklang="DlgPasteMsg2">Please paste inside the following box using the keyboard
+ (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.</span><br />
+ &nbsp;
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" height="100%" style="border-right: #000000 1px solid; border-top: #000000 1px solid;
+ border-left: #000000 1px solid; border-bottom: #000000 1px solid">
+ <textarea id="txtData" cols="80" rows="5" style="border: #000000 1px; display: none;
+ width: 99%; height: 98%"></textarea>
+ <iframe id="frmData" src="javascript:void(0)" height="98%" width="99%" frameborder="0"
+ style="border-right: #000000 1px; border-top: #000000 1px; display: none; border-left: #000000 1px;
+ border-bottom: #000000 1px; background-color: #ffffff"></iframe>
+ </td>
+ </tr>
+ <tr id="oWordCommands">
+ <td>
+ <table border="0" cellpadding="0" cellspacing="0" width="100%">
+ <tr>
+ <td nowrap="nowrap">
+ <input id="chkRemoveFont" type="checkbox" checked="checked" />
+ <label for="chkRemoveFont" fcklang="DlgPasteIgnoreFont">
+ Ignore Font Face definitions</label>
+ <br />
+ <input id="chkRemoveStyles" type="checkbox" />
+ <label for="chkRemoveStyles" fcklang="DlgPasteRemoveStyles">
+ Remove Styles definitions</label>
+ </td>
+ <td align="right" valign="top">
+ <input type="button" fcklang="DlgPasteCleanBox" value="Clean Up Box" onclick="CleanUpBox()" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_radiobutton.html b/httemplate/elements/fckeditor/editor/dialog/fck_radiobutton.html
new file mode 100644
index 000000000..f239ad3e4
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_radiobutton.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Radio Button dialog window.
+-->
+<html>
+ <head>
+ <title>Radio Button Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl && oActiveEl.tagName.toUpperCase() == 'INPUT' && oActiveEl.type == 'radio' )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtValue').value = oEditor.FCKBrowserInfo.IsIE ? oActiveEl.value : GetAttribute( oActiveEl, 'value' ) ;
+ GetE('txtSelected').checked = oActiveEl.checked ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oActiveEl.type = 'radio' ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ if ( GetE('txtName').value.length > 0 )
+ oActiveEl.name = GetE('txtName').value ;
+
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ oActiveEl.value = GetE('txtValue').value ;
+ else
+ SetAttribute( oActiveEl, 'value', GetE('txtValue').value ) ;
+
+ var bIsChecked = GetE('txtSelected').checked ;
+ SetAttribute( oActiveEl, 'checked', bIsChecked ? 'checked' : null ) ; // For Firefox
+ oActiveEl.checked = bIsChecked ;
+
+ return true ;
+}
+
+ </script>
+ </head>
+ <body style="OVERFLOW: hidden" scroll="no">
+ <table height="100%" width="100%">
+ <tr>
+ <td align="center">
+ <table border="0" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td>
+ <span fckLang="DlgCheckboxName">Name</span><br>
+ <input type="text" size="20" id="txtName" style="WIDTH: 100%">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fckLang="DlgCheckboxValue">Value</span><br>
+ <input type="text" size="20" id="txtValue" style="WIDTH: 100%">
+ </td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="txtSelected"><label for="txtSelected" fckLang="DlgCheckboxSelected">Checked</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_replace.html b/httemplate/elements/fckeditor/editor/dialog/fck_replace.html
new file mode 100644
index 000000000..fe5a7884c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_replace.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * "Replace" dialog box window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+function OnLoad()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage( document ) ;
+
+ window.parent.SetAutoSize( true ) ;
+
+ oEditor.FCKUndo.SaveUndoStep() ;
+}
+
+function btnStat(frm)
+{
+ document.getElementById('btnReplace').disabled =
+ document.getElementById('btnReplaceAll').disabled =
+ ( document.getElementById('txtFind').value.length == 0 ) ;
+}
+
+function ReplaceTextNodes( parentNode, regex, replaceValue, replaceAll, hasFound )
+{
+ for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
+ {
+ var oNode = parentNode.childNodes[i] ;
+ if ( oNode.nodeType == 3 )
+ {
+ var sReplaced = oNode.nodeValue.replace( regex, replaceValue ) ;
+ if ( oNode.nodeValue != sReplaced )
+ {
+ oNode.nodeValue = sReplaced ;
+ if ( ! replaceAll )
+ return true ;
+ hasFound = true ;
+ }
+ }
+
+ hasFound = ReplaceTextNodes( oNode, regex, replaceValue, replaceAll, hasFound ) ;
+ if ( ! replaceAll && hasFound )
+ return true ;
+ }
+
+ return hasFound ;
+}
+
+function GetRegexExpr()
+{
+ var sExpr = EscapeRegexString( document.getElementById('txtFind').value ) ;
+
+ if ( document.getElementById('chkWord').checked )
+ sExpr = '\\b' + sExpr + '\\b' ;
+
+ return sExpr ;
+}
+
+function GetCase()
+{
+ return ( document.getElementById('chkCase').checked ? '' : 'i' ) ;
+}
+
+function GetReplacement()
+{
+ return document.getElementById('txtReplace').value.replace( /\$/g, '$$$$' ) ;
+}
+
+function EscapeRegexString( str )
+{
+ return str.replace( /[\\\^\$\*\+\?\{\}\.\(\)\!\|\[\]\-]/g, '\\$&' ) ;
+}
+
+function Replace()
+{
+ var oRegex = new RegExp( GetRegexExpr(), GetCase() ) ;
+ if ( !ReplaceTextNodes( oEditor.FCK.EditorDocument.body, oRegex, GetReplacement(), false, false ) )
+ alert( oEditor.FCKLang.DlgFindNotFoundMsg ) ;
+}
+
+function ReplaceAll()
+{
+ var oRegex = new RegExp( GetRegexExpr(), GetCase() + 'g' ) ;
+ if ( !ReplaceTextNodes( oEditor.FCK.EditorDocument.body, oRegex, GetReplacement(), true, false ) )
+ alert( oEditor.FCKLang.DlgFindNotFoundMsg ) ;
+ window.parent.Cancel() ;
+}
+ </script>
+</head>
+<body onload="OnLoad()" style="overflow: hidden">
+ <table cellspacing="3" cellpadding="2" width="100%" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <label for="txtFind" fcklang="DlgReplaceFindLbl">
+ Find what:</label>
+ </td>
+ <td width="100%">
+ <input id="txtFind" onkeyup="btnStat(this.form)" style="width: 100%" tabindex="1"
+ type="text" />
+ </td>
+ <td>
+ <input id="btnReplace" style="width: 100%" disabled="disabled" onclick="Replace();"
+ type="button" value="Replace" fcklang="DlgReplaceReplaceBtn" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" nowrap="nowrap">
+ <label for="txtReplace" fcklang="DlgReplaceReplaceLbl">
+ Replace with:</label>
+ </td>
+ <td valign="top">
+ <input id="txtReplace" style="width: 100%" tabindex="2" type="text" />
+ </td>
+ <td>
+ <input id="btnReplaceAll" disabled="disabled" onclick="ReplaceAll()" type="button"
+ value="Replace All" fcklang="DlgReplaceReplAllBtn" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="bottom" colspan="3">
+ &nbsp;<input id="chkCase" tabindex="3" type="checkbox" /><label for="chkCase" fcklang="DlgReplaceCaseChk">Match
+ case</label>
+ <br />
+ &nbsp;<input id="chkWord" tabindex="4" type="checkbox" /><label for="chkWord" fcklang="DlgReplaceWordChk">Match
+ whole word</label>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_select.html b/httemplate/elements/fckeditor/editor/dialog/fck_select.html
new file mode 100644
index 000000000..cb48b5070
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_select.html
@@ -0,0 +1,176 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Select dialog window.
+-->
+<html>
+ <head>
+ <title>Select Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript" src="fck_select/fck_select.js"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+var oListText ;
+var oListValue ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ oListText = document.getElementById( 'cmbText' ) ;
+ oListValue = document.getElementById( 'cmbValue' ) ;
+
+ if ( oActiveEl && oActiveEl.tagName == 'SELECT' )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtSelValue').value = oActiveEl.value ;
+ GetE('txtLines').value = GetAttribute( oActiveEl, 'size' ) ;
+ GetE('chkMultiple').checked = oActiveEl.multiple ;
+
+ // Load the actual options
+ for ( var i = 0 ; i < oActiveEl.options.length ; i++ )
+ {
+ var sText = HTMLDecode( oActiveEl.options[i].innerHTML ) ;
+ var sValue = oActiveEl.options[i].value ;
+
+ AddComboOption( oListText, sText, sText ) ;
+ AddComboOption( oListValue, sValue, sValue ) ;
+ }
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ var sSize = GetE('txtLines').value ;
+ if ( sSize == null || isNaN( sSize ) || sSize <= 1 )
+ sSize = '' ;
+
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'SELECT' ) ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ SetAttribute( oActiveEl, 'name' , GetE('txtName').value ) ;
+ SetAttribute( oActiveEl, 'size' , sSize ) ;
+ oActiveEl.multiple = ( sSize.length > 0 && GetE('chkMultiple').checked ) ;
+
+ // Remove all options.
+ while ( oActiveEl.options.length > 0 )
+ oActiveEl.remove(0) ;
+
+ // Add all available options.
+ for ( var i = 0 ; i < oListText.options.length ; i++ )
+ {
+ var sText = oListText.options[i].value ;
+ var sValue = oListValue.options[i].value ;
+ if ( sValue.length == 0 ) sValue = sText ;
+
+ var oOption = AddComboOption( oActiveEl, sText, sValue, oDOM ) ;
+
+ if ( sValue == GetE('txtSelValue').value )
+ {
+ SetAttribute( oOption, 'selected', 'selected' ) ;
+ oOption.selected = true ;
+ }
+ }
+
+ return true ;
+}
+
+ </script>
+ </head>
+ <body style='OVERFLOW: hidden' scroll='no'>
+ <table width="100%" height="100%">
+ <tr>
+ <td>
+ <table width="100%">
+ <tr>
+ <td nowrap><span fckLang="DlgSelectName">Name</span>&nbsp;</td>
+ <td width="100%" colSpan="2"><input id="txtName" style="WIDTH: 100%" type="text"></td>
+ </tr>
+ <tr>
+ <td nowrap><span fckLang="DlgSelectValue">Value</span>&nbsp;</td>
+ <td width="100%" colSpan="2"><input id="txtSelValue" style="WIDTH: 100%; BACKGROUND-COLOR: buttonface" type="text" readonly></td>
+ </tr>
+ <tr>
+ <td nowrap><span fckLang="DlgSelectSize">Size</span>&nbsp;</td>
+ <td nowrap><input id="txtLines" type="text" size="2" value="">&nbsp;<span fckLang="DlgSelectLines">lines</span></td>
+ <td nowrap align="right"><input id="chkMultiple" name="chkMultiple" type="checkbox"><label for="chkMultiple" fckLang="DlgSelectChkMulti">Allow
+ multiple selections</label></td>
+ </tr>
+ </table>
+ <br>
+ <hr style="POSITION: absolute">
+ <span style="LEFT: 10px; POSITION: relative; TOP: -7px" class="BackColor">&nbsp;<span fckLang="DlgSelectOpAvail">Available
+ Options</span>&nbsp;</span>
+ <table width="100%">
+ <tr>
+ <td width="50%"><span fckLang="DlgSelectOpText">Text</span><br>
+ <input id="txtText" style="WIDTH: 100%" type="text" name="txtText">
+ </td>
+ <td width="50%"><span fckLang="DlgSelectOpValue">Value</span><br>
+ <input id="txtValue" style="WIDTH: 100%" type="text" name="txtValue">
+ </td>
+ <td vAlign="bottom"><input onclick="Add();" type="button" fckLang="DlgSelectBtnAdd" value="Add"></td>
+ <td vAlign="bottom"><input onclick="Modify();" type="button" fckLang="DlgSelectBtnModify" value="Modify"></td>
+ </tr>
+ <tr>
+ <td rowSpan="2"><select id="cmbText" style="WIDTH: 100%" onchange="GetE('cmbValue').selectedIndex = this.selectedIndex;Select(this);"
+ size="5" name="cmbText"></select>
+ </td>
+ <td rowSpan="2"><select id="cmbValue" style="WIDTH: 100%" onchange="GetE('cmbText').selectedIndex = this.selectedIndex;Select(this);"
+ size="5" name="cmbValue"></select>
+ </td>
+ <td vAlign="top" colSpan="2">
+ </td>
+ </tr>
+ <tr>
+ <td vAlign="bottom" colSpan="2"><input style="WIDTH: 100%" onclick="Move(-1);" type="button" fckLang="DlgSelectBtnUp" value="Up">
+ <br>
+ <input style="WIDTH: 100%" onclick="Move(1);" type="button" fckLang="DlgSelectBtnDown"
+ value="Down">
+ </td>
+ </tr>
+ <TR>
+ <TD vAlign="bottom" colSpan="4"><INPUT onclick="SetSelectedValue();" type="button" fckLang="DlgSelectBtnSetValue" value="Set as selected value">&nbsp;&nbsp;
+ <input onclick="Delete();" type="button" fckLang="DlgSelectBtnDelete" value="Delete"></TD>
+ </TR>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_select/fck_select.js b/httemplate/elements/fckeditor/editor/dialog/fck_select/fck_select.js
new file mode 100644
index 000000000..181b66648
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_select/fck_select.js
@@ -0,0 +1,194 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Scripts for the fck_select.html page.
+ */
+
+function Select( combo )
+{
+ var iIndex = combo.selectedIndex ;
+
+ oListText.selectedIndex = iIndex ;
+ oListValue.selectedIndex = iIndex ;
+
+ var oTxtText = document.getElementById( "txtText" ) ;
+ var oTxtValue = document.getElementById( "txtValue" ) ;
+
+ oTxtText.value = oListText.value ;
+ oTxtValue.value = oListValue.value ;
+}
+
+function Add()
+{
+ var oTxtText = document.getElementById( "txtText" ) ;
+ var oTxtValue = document.getElementById( "txtValue" ) ;
+
+ AddComboOption( oListText, oTxtText.value, oTxtText.value ) ;
+ AddComboOption( oListValue, oTxtValue.value, oTxtValue.value ) ;
+
+ oListText.selectedIndex = oListText.options.length - 1 ;
+ oListValue.selectedIndex = oListValue.options.length - 1 ;
+
+ oTxtText.value = '' ;
+ oTxtValue.value = '' ;
+
+ oTxtText.focus() ;
+}
+
+function Modify()
+{
+ var iIndex = oListText.selectedIndex ;
+
+ if ( iIndex < 0 ) return ;
+
+ var oTxtText = document.getElementById( "txtText" ) ;
+ var oTxtValue = document.getElementById( "txtValue" ) ;
+
+ oListText.options[ iIndex ].innerHTML = HTMLEncode( oTxtText.value ) ;
+ oListText.options[ iIndex ].value = oTxtText.value ;
+
+ oListValue.options[ iIndex ].innerHTML = HTMLEncode( oTxtValue.value ) ;
+ oListValue.options[ iIndex ].value = oTxtValue.value ;
+
+ oTxtText.value = '' ;
+ oTxtValue.value = '' ;
+
+ oTxtText.focus() ;
+}
+
+function Move( steps )
+{
+ ChangeOptionPosition( oListText, steps ) ;
+ ChangeOptionPosition( oListValue, steps ) ;
+}
+
+function Delete()
+{
+ RemoveSelectedOptions( oListText ) ;
+ RemoveSelectedOptions( oListValue ) ;
+}
+
+function SetSelectedValue()
+{
+ var iIndex = oListValue.selectedIndex ;
+ if ( iIndex < 0 ) return ;
+
+ var oTxtValue = document.getElementById( "txtSelValue" ) ;
+
+ oTxtValue.value = oListValue.options[ iIndex ].value ;
+}
+
+// Moves the selected option by a number of steps (also negative)
+function ChangeOptionPosition( combo, steps )
+{
+ var iActualIndex = combo.selectedIndex ;
+
+ if ( iActualIndex < 0 )
+ return ;
+
+ var iFinalIndex = iActualIndex + steps ;
+
+ if ( iFinalIndex < 0 )
+ iFinalIndex = 0 ;
+
+ if ( iFinalIndex > ( combo.options.length - 1 ) )
+ iFinalIndex = combo.options.length - 1 ;
+
+ if ( iActualIndex == iFinalIndex )
+ return ;
+
+ var oOption = combo.options[ iActualIndex ] ;
+ var sText = HTMLDecode( oOption.innerHTML ) ;
+ var sValue = oOption.value ;
+
+ combo.remove( iActualIndex ) ;
+
+ oOption = AddComboOption( combo, sText, sValue, null, iFinalIndex ) ;
+
+ oOption.selected = true ;
+}
+
+// Remove all selected options from a SELECT object
+function RemoveSelectedOptions(combo)
+{
+ // Save the selected index
+ var iSelectedIndex = combo.selectedIndex ;
+
+ var oOptions = combo.options ;
+
+ // Remove all selected options
+ for ( var i = oOptions.length - 1 ; i >= 0 ; i-- )
+ {
+ if (oOptions[i].selected) combo.remove(i) ;
+ }
+
+ // Reset the selection based on the original selected index
+ if ( combo.options.length > 0 )
+ {
+ if ( iSelectedIndex >= combo.options.length ) iSelectedIndex = combo.options.length - 1 ;
+ combo.selectedIndex = iSelectedIndex ;
+ }
+}
+
+// Add a new option to a SELECT object (combo or list)
+function AddComboOption( combo, optionText, optionValue, documentObject, index )
+{
+ var oOption ;
+
+ if ( documentObject )
+ oOption = documentObject.createElement("OPTION") ;
+ else
+ oOption = document.createElement("OPTION") ;
+
+ if ( index != null )
+ combo.options.add( oOption, index ) ;
+ else
+ combo.options.add( oOption ) ;
+
+ oOption.innerHTML = optionText.length > 0 ? HTMLEncode( optionText ) : '&nbsp;' ;
+ oOption.value = optionValue ;
+
+ return oOption ;
+}
+
+function HTMLEncode( text )
+{
+ if ( !text )
+ return '' ;
+
+ text = text.replace( /&/g, '&amp;' ) ;
+ text = text.replace( /</g, '&lt;' ) ;
+ text = text.replace( />/g, '&gt;' ) ;
+
+ return text ;
+}
+
+
+function HTMLDecode( text )
+{
+ if ( !text )
+ return '' ;
+
+ text = text.replace( /&gt;/g, '>' ) ;
+ text = text.replace( /&lt;/g, '<' ) ;
+ text = text.replace( /&amp;/g, '&' ) ;
+
+ return text ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_smiley.html b/httemplate/elements/fckeditor/editor/dialog/fck_smiley.html
new file mode 100644
index 000000000..c8efd0cd1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_smiley.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Smileys (emoticons) dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <style type="text/css">
+ .Hand
+ {
+ cursor: pointer;
+ cursor: hand;
+ }
+ </style>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+window.onload = function ()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+}
+
+function InsertSmiley( url )
+{
+ var oImg = oEditor.FCK.CreateElement( 'IMG' ) ;
+ oImg.src = url ;
+ oImg.setAttribute( '_fcksavedurl', url ) ;
+
+ // For long smileys list, it seams that IE continues loading the images in
+ // the background when you quickly select one image. so, let's clear
+ // everything before closing.
+ document.body.innerHTML = '' ;
+
+ window.parent.Cancel() ;
+}
+
+function over(td)
+{
+ td.className = 'LightBackground Hand' ;
+}
+
+function out(td)
+{
+ td.className = 'DarkBackground Hand' ;
+}
+ </script>
+</head>
+<body scroll="no">
+ <table cellpadding="2" cellspacing="2" align="center" border="0" width="100%" height="100%">
+ <script type="text/javascript">
+
+var FCKConfig = oEditor.FCKConfig ;
+
+var sBasePath = FCKConfig.SmileyPath ;
+var aImages = FCKConfig.SmileyImages ;
+var iCols = FCKConfig.SmileyColumns ;
+var iColWidth = parseInt( 100 / iCols, 10 ) ;
+
+var i = 0 ;
+while (i < aImages.length)
+{
+ document.write( '<tr>' ) ;
+ for(var j = 0 ; j < iCols ; j++)
+ {
+ if (aImages[i])
+ {
+ var sUrl = sBasePath + aImages[i] ;
+ document.write( '<td width="' + iColWidth + '%" align="center" class="DarkBackground Hand" onclick="InsertSmiley(\'' + sUrl.replace(/'/g, "\\'" ) + '\')" onmouseover="over(this)" onmouseout="out(this)">' ) ;
+ document.write( '<img src="' + sUrl + '" border="0" />' ) ;
+ }
+ else
+ document.write( '<td width="' + iColWidth + '%" class="DarkBackground">&nbsp;' ) ;
+ document.write( '<\/td>' ) ;
+ i++ ;
+ }
+ document.write('<\/tr>') ;
+}
+
+ </script>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_source.html b/httemplate/elements/fckeditor/editor/dialog/fck_source.html
new file mode 100644
index 000000000..aba9b395f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_source.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Source editor dialog window.
+-->
+<html>
+ <head>
+ <title>Source</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="robots" content="noindex, nofollow">
+ <link href="common/fck_dialog_common.css" rel="stylesheet" type="text/css" />
+ <script language="javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKConfig = oEditor.FCKConfig ;
+
+window.onload = function()
+{
+ // EnableXHTML and EnableSourceXHTML has been deprecated
+// document.getElementById('txtSource').value = ( FCKConfig.EnableXHTML && FCKConfig.EnableSourceXHTML ? FCK.GetXHTML( FCKConfig.FormatSource ) : FCK.GetHTML( FCKConfig.FormatSource ) ) ;
+ document.getElementById('txtSource').value = FCK.GetXHTML( FCKConfig.FormatSource ) ;
+
+ // Activate the "OK" button.
+ window.parent.SetOkButton( true ) ;
+}
+
+//#### The OK button was hit.
+function Ok()
+{
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ FCK.SetHTML( document.getElementById('txtSource').value, false ) ;
+
+ return true ;
+}
+ </script>
+ </head>
+ <body scroll="no" style="OVERFLOW: hidden">
+ <table width="100%" height="100%">
+ <tr>
+ <td height="100%"><textarea id="txtSource" dir="ltr" style="PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; WIDTH: 100%; PADDING-TOP: 5px; FONT-FAMILY: Monospace; HEIGHT: 100%">Loading. Please wait...</textarea></td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_specialchar.html b/httemplate/elements/fckeditor/editor/dialog/fck_specialchar.html
new file mode 100644
index 000000000..e6d0a5a86
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_specialchar.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Special Chars Selector dialog window.
+-->
+<html>
+ <head>
+ <meta name="robots" content="noindex, nofollow">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ .Hand
+ {
+ cursor: pointer ;
+ cursor: hand ;
+ }
+ .Sample { font-size: 24px; }
+ </style>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+var oSample ;
+
+function insertChar(charValue)
+{
+ oEditor.FCK.InsertHtml( charValue || "" ) ;
+ window.parent.Cancel() ;
+}
+
+function over(td)
+{
+ oSample.innerHTML = td.innerHTML ;
+ td.className = 'LightBackground SpecialCharsOver Hand' ;
+}
+
+function out(td)
+{
+ oSample.innerHTML = "&nbsp;" ;
+ td.className = 'DarkBackground SpecialCharsOut Hand' ;
+}
+
+function setDefaults()
+{
+ // Gets the sample placeholder.
+ oSample = document.getElementById("SampleTD") ;
+
+ // First of all, translates the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+}
+
+ </script>
+ </HEAD>
+ <BODY onload="setDefaults()" scroll="no">
+ <table cellpadding="0" cellspacing="0" width="100%" height="100%">
+ <tr>
+ <td width="100%">
+ <table cellpadding="1" cellspacing="1" align="center" border="0" width="100%" height="100%">
+ <script type="text/javascript">
+var aChars = ["!","&quot;","#","$","%","&amp;","\\'","(",")","*","+","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","&lt;","=","&gt;","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","&euro;","&lsquo;","&rsquo;","&rsquo;","&ldquo;","&rdquo;","&ndash;","&mdash;","&iexcl;","&cent;","&pound;","&curren;","&yen;","&brvbar;","&sect;","&uml;","&copy;","&ordf;","&laquo;","&not;","&reg;","&macr;","&deg;","&plusmn;","&sup2;","&sup3;","&acute;","&micro;","&para;","&middot;","&cedil;","&sup1;","&ordm;","&raquo;","&frac14;","&frac12;","&frac34;","&iquest;","&Agrave;","&Aacute;","&Acirc;","&Atilde;","&Auml;","&Aring;","&AElig;","&Ccedil;","&Egrave;","&Eacute;","&Ecirc;","&Euml;","&Igrave;","&Iacute;","&Icirc;","&Iuml;","&ETH;","&Ntilde;","&Ograve;","&Oacute;","&Ocirc;","&Otilde;","&Ouml;","&times;","&Oslash;","&Ugrave;","&Uacute;","&Ucirc;","&Uuml;","&Yacute;","&THORN;","&szlig;","&agrave;","&aacute;","&acirc;","&atilde;","&auml;","&aring;","&aelig;","&ccedil;","&egrave;","&eacute;","&ecirc;","&euml;","&igrave;","&iacute;","&icirc;","&iuml;","&eth;","&ntilde;","&ograve;","&oacute;","&ocirc;","&otilde;","&ouml;","&divide;","&oslash;","&ugrave;","&uacute;","&ucirc;","&uuml;","&uuml;","&yacute;","&thorn;","&yuml;","&OElig;","&oelig;","&sbquo;","&#8219;","&bdquo;","&hellip;","&trade;","&#9658;","&bull;","&rarr;","&rArr;","&hArr;","&diams;","&asymp;"] ;
+
+var cols = 20 ;
+
+var i = 0 ;
+while (i < aChars.length)
+{
+ document.write("<TR>") ;
+ for(var j = 0 ; j < cols ; j++)
+ {
+ if (aChars[i])
+ {
+ document.write('<TD width="1%" class="DarkBackground SpecialCharsOut Hand" align="center" onclick="insertChar(\'' + aChars[i].replace(/&/g, "&amp;") + '\')" onmouseover="over(this)" onmouseout="out(this)">') ;
+ document.write(aChars[i]) ;
+ }
+ else
+ document.write("<TD class='DarkBackground SpecialCharsOut'>&nbsp;") ;
+ document.write("<\/TD>") ;
+ i++ ;
+ }
+ document.write("<\/TR>") ;
+}
+ </script>
+ </table>
+ </td>
+ <td nowrap>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td valign="top">
+ <table width="40" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td id="SampleTD" width="40" height="40" align="center" class="DarkBackground SpecialCharsOut Sample">&nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </BODY>
+</HTML> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages.html b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages.html
new file mode 100644
index 000000000..66596e17f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Spell Check dialog window.
+-->
+<html>
+ <head>
+ <title>Spell Check</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="fck_spellerpages/spellerpages/spellChecker.js"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCKLang = oEditor.FCKLang ;
+
+window.onload = function()
+{
+ document.getElementById('txtHtml').value = oEditor.FCK.EditorDocument.body.innerHTML ;
+
+ var oSpeller = new spellChecker( document.getElementById('txtHtml') ) ;
+ oSpeller.spellCheckScript = oEditor.FCKConfig.SpellerPagesServerScript || 'server-scripts/spellchecker.php' ;
+ oSpeller.OnFinished = oSpeller_OnFinished ;
+ oSpeller.openChecker() ;
+}
+
+function OnSpellerControlsLoad( controlsWindow )
+{
+ // Translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage( controlsWindow.document ) ;
+}
+
+function oSpeller_OnFinished( numberOCorrections )
+{
+ if ( numberOCorrections > 0 )
+ oEditor.FCK.SetHTML( document.getElementById('txtHtml').value ) ;
+ window.parent.Cancel() ;
+}
+
+ </script>
+ </head>
+ <body style="OVERFLOW: hidden" scroll="no" style="padding:0px;">
+ <input type="hidden" id="txtHtml" value="">
+ <iframe id="frmSpell" src="javascript:void(0)" name="spellchecker" width="100%" height="100%" frameborder="0"></iframe>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js
new file mode 100644
index 000000000..80af84995
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js
@@ -0,0 +1,87 @@
+////////////////////////////////////////////////////
+// controlWindow object
+////////////////////////////////////////////////////
+function controlWindow( controlForm ) {
+ // private properties
+ this._form = controlForm;
+
+ // public properties
+ this.windowType = "controlWindow";
+// this.noSuggestionSelection = "- No suggestions -"; // by FredCK
+ this.noSuggestionSelection = FCKLang.DlgSpellNoSuggestions ;
+ // set up the properties for elements of the given control form
+ this.suggestionList = this._form.sugg;
+ this.evaluatedText = this._form.misword;
+ this.replacementText = this._form.txtsugg;
+ this.undoButton = this._form.btnUndo;
+
+ // public methods
+ this.addSuggestion = addSuggestion;
+ this.clearSuggestions = clearSuggestions;
+ this.selectDefaultSuggestion = selectDefaultSuggestion;
+ this.resetForm = resetForm;
+ this.setSuggestedText = setSuggestedText;
+ this.enableUndo = enableUndo;
+ this.disableUndo = disableUndo;
+}
+
+function resetForm() {
+ if( this._form ) {
+ this._form.reset();
+ }
+}
+
+function setSuggestedText() {
+ var slct = this.suggestionList;
+ var txt = this.replacementText;
+ var str = "";
+ if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) {
+ str = slct.options[slct.selectedIndex].text;
+ }
+ txt.value = str;
+}
+
+function selectDefaultSuggestion() {
+ var slct = this.suggestionList;
+ var txt = this.replacementText;
+ if( slct.options.length == 0 ) {
+ this.addSuggestion( this.noSuggestionSelection );
+ } else {
+ slct.options[0].selected = true;
+ }
+ this.setSuggestedText();
+}
+
+function addSuggestion( sugg_text ) {
+ var slct = this.suggestionList;
+ if( sugg_text ) {
+ var i = slct.options.length;
+ var newOption = new Option( sugg_text, 'sugg_text'+i );
+ slct.options[i] = newOption;
+ }
+}
+
+function clearSuggestions() {
+ var slct = this.suggestionList;
+ for( var j = slct.length - 1; j > -1; j-- ) {
+ if( slct.options[j] ) {
+ slct.options[j] = null;
+ }
+ }
+}
+
+function enableUndo() {
+ if( this.undoButton ) {
+ if( this.undoButton.disabled == true ) {
+ this.undoButton.disabled = false;
+ }
+ }
+}
+
+function disableUndo() {
+ if( this.undoButton ) {
+ if( this.undoButton.disabled == false ) {
+ this.undoButton.disabled = true;
+ }
+ }
+}
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html
new file mode 100644
index 000000000..d91bcce2d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html
@@ -0,0 +1,153 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="spellerStyle.css" />
+ <script type="text/javascript" src="controlWindow.js"></script>
+ <script type="text/javascript">
+var spellerObject;
+var controlWindowObj;
+
+if( parent.opener ) {
+ spellerObject = parent.opener.speller;
+}
+
+function ignore_word() {
+ if( spellerObject ) {
+ spellerObject.ignoreWord();
+ }
+}
+
+function ignore_all() {
+ if( spellerObject ) {
+ spellerObject.ignoreAll();
+ }
+}
+
+function replace_word() {
+ if( spellerObject ) {
+ spellerObject.replaceWord();
+ }
+}
+
+function replace_all() {
+ if( spellerObject ) {
+ spellerObject.replaceAll();
+ }
+}
+
+function end_spell() {
+ if( spellerObject ) {
+ spellerObject.terminateSpell();
+ }
+}
+
+function undo() {
+ if( spellerObject ) {
+ spellerObject.undo();
+ }
+}
+
+function suggText() {
+ if( controlWindowObj ) {
+ controlWindowObj.setSuggestedText();
+ }
+}
+
+var FCKLang = window.parent.parent.FCKLang ; // by FredCK
+
+function init_spell() {
+ // By FredCK (fckLang attributes have been added to the HTML source of this page)
+ window.parent.parent.OnSpellerControlsLoad( this ) ;
+
+ var controlForm = document.spellcheck;
+
+ // create a new controlWindow object
+ controlWindowObj = new controlWindow( controlForm );
+
+ // call the init_spell() function in the parent frameset
+ if( parent.frames.length ) {
+ parent.init_spell( controlWindowObj );
+ } else {
+ alert( 'This page was loaded outside of a frameset. It might not display properly' );
+ }
+}
+
+</script>
+ </head>
+ <body class="controlWindowBody" onLoad="init_spell();" style="OVERFLOW: hidden" scroll="no"> <!-- by FredCK -->
+ <form name="spellcheck">
+ <table border="0" cellpadding="0" cellspacing="0" border="0" align="center">
+ <tr>
+ <td colspan="3" class="normalLabel"><span fckLang="DlgSpellNotInDic">Not in dictionary:</span></td>
+ </tr>
+ <tr>
+ <td colspan="3"><input class="readonlyInput" type="text" name="misword" readonly /></td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td class="normalLabel"><span fckLang="DlgSpellChangeTo">Change to:</span></td>
+ </tr>
+ <tr valign="top">
+ <td>
+ <table border="0" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="normalLabel">
+ <input class="textDefault" type="text" name="txtsugg" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <select class="suggSlct" name="sugg" size="7" onChange="suggText();" onDblClick="replace_word();">
+ <option></option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td>
+ <table border="0" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnore" value="Ignore" onClick="ignore_word();">
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnIgnoreAll" value="Ignore All" onClick="ignore_all();">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplace" value="Replace" onClick="replace_word();">
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td>
+ <input class="buttonDefault" type="button" fckLang="DlgSpellBtnReplaceAll" value="Replace All" onClick="replace_all();">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" height="5"></td>
+ </tr>
+ <tr>
+ <td>
+ <input class="buttonDefault" type="button" name="btnUndo" fckLang="DlgSpellBtnUndo" value="Undo" onClick="undo();"
+ disabled>
+ </td>
+ <td>&nbsp;&nbsp;</td>
+ <td>
+ <!-- by FredCK
+ <input class="buttonDefault" type="button" value="Close" onClick="end_spell();">
+ -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl
new file mode 100644
index 000000000..8d3df65e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl
@@ -0,0 +1,180 @@
+#!/usr/bin/perl
+
+use CGI qw/ :standard /;
+use File::Temp qw/ tempfile tempdir /;
+
+# my $spellercss = '/speller/spellerStyle.css'; # by FredCK
+my $spellercss = '../spellerStyle.css'; # by FredCK
+# my $wordWindowSrc = '/speller/wordWindow.js'; # by FredCK
+my $wordWindowSrc = '../wordWindow.js'; # by FredCK
+my @textinputs = param( 'textinputs[]' ); # array
+# my $aspell_cmd = 'aspell'; # by FredCK (for Linux)
+my $aspell_cmd = '"C:\Program Files\Aspell\bin\aspell.exe"'; # by FredCK (for Windows)
+my $lang = 'en_US';
+# my $aspell_opts = "-a --lang=$lang --encoding=utf-8"; # by FredCK
+my $aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt"; # by FredCK
+my $input_separator = "A";
+
+# set the 'wordtext' JavaScript variable to the submitted text.
+sub printTextVar {
+ for( my $i = 0; $i <= $#textinputs; $i++ ) {
+ print "textinputs[$i] = decodeURIComponent('" . escapeQuote( $textinputs[$i] ) . "')\n";
+ }
+}
+
+sub printTextIdxDecl {
+ my $idx = shift;
+ print "words[$idx] = [];\n";
+ print "suggs[$idx] = [];\n";
+}
+
+sub printWordsElem {
+ my( $textIdx, $wordIdx, $word ) = @_;
+ print "words[$textIdx][$wordIdx] = '" . escapeQuote( $word ) . "';\n";
+}
+
+sub printSuggsElem {
+ my( $textIdx, $wordIdx, @suggs ) = @_;
+ print "suggs[$textIdx][$wordIdx] = [";
+ for my $i ( 0..$#suggs ) {
+ print "'" . escapeQuote( $suggs[$i] ) . "'";
+ if( $i < $#suggs ) {
+ print ", ";
+ }
+ }
+ print "];\n";
+}
+
+sub printCheckerResults {
+ my $textInputIdx = -1;
+ my $wordIdx = 0;
+ my $unhandledText;
+ # create temp file
+ my $dir = tempdir( CLEANUP => 1 );
+ my( $fh, $tmpfilename ) = tempfile( DIR => $dir );
+
+ # temp file was created properly?
+
+ # open temp file, add the submitted text.
+ for( my $i = 0; $i <= $#textinputs; $i++ ) {
+ $text = url_decode( $textinputs[$i] );
+ @lines = split( /\n/, $text );
+ print $fh "\%\n"; # exit terse mode
+ print $fh "^$input_separator\n";
+ print $fh "!\n"; # enter terse mode
+ for my $line ( @lines ) {
+ # use carat on each line to escape possible aspell commands
+ print $fh "^$line\n";
+ }
+
+ }
+ # exec aspell command
+ my $cmd = "$aspell_cmd $aspell_opts < $tmpfilename 2>&1";
+ open ASPELL, "$cmd |" or handleError( "Could not execute `$cmd`\\n$!" ) and return;
+ # parse each line of aspell return
+ for my $ret ( <ASPELL> ) {
+ chomp( $ret );
+ # if '&', then not in dictionary but has suggestions
+ # if '#', then not in dictionary and no suggestions
+ # if '*', then it is a delimiter between text inputs
+ if( $ret =~ /^\*/ ) {
+ $textInputIdx++;
+ printTextIdxDecl( $textInputIdx );
+ $wordIdx = 0;
+
+ } elsif( $ret =~ /^(&|#)/ ) {
+ my @tokens = split( " ", $ret, 5 );
+ printWordsElem( $textInputIdx, $wordIdx, $tokens[1] );
+ my @suggs = ();
+ if( $tokens[4] ) {
+ @suggs = split( ", ", $tokens[4] );
+ }
+ printSuggsElem( $textInputIdx, $wordIdx, @suggs );
+ $wordIdx++;
+ } else {
+ $unhandledText .= $ret;
+ }
+ }
+ close ASPELL or handleError( "Error executing `$cmd`\\n$unhandledText" ) and return;
+}
+
+sub escapeQuote {
+ my $str = shift;
+ $str =~ s/'/\\'/g;
+ return $str;
+}
+
+sub handleError {
+ my $err = shift;
+ print "error = '" . escapeQuote( $err ) . "';\n";
+}
+
+sub url_decode {
+ local $_ = @_ ? shift : $_;
+ defined or return;
+ # change + signs to spaces
+ tr/+/ /;
+ # change hex escapes to the proper characters
+ s/%([a-fA-F0-9]{2})/pack "H2", $1/eg;
+ return $_;
+}
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Display HTML
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+print <<EOF;
+Content-type: text/html; charset=utf-8
+
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" type="text/css" href="$spellercss"/>
+<script src="$wordWindowSrc"></script>
+<script type="text/javascript">
+var suggs = new Array();
+var words = new Array();
+var textinputs = new Array();
+var error;
+EOF
+
+printTextVar();
+
+printCheckerResults();
+
+print <<EOF;
+var wordWindowObj = new wordWindow();
+wordWindowObj.originalSpellings = words;
+wordWindowObj.suggestions = suggs;
+wordWindowObj.textInputs = textinputs;
+
+
+function init_spell() {
+ // check if any error occured during server-side processing
+ if( error ) {
+ alert( error );
+ } else {
+ // call the init_spell() function in the parent frameset
+ if (parent.frames.length) {
+ parent.init_spell( wordWindowObj );
+ } else {
+ error = "This page was loaded outside of a frameset. ";
+ error += "It might not display properly";
+ alert( error );
+ }
+ }
+}
+
+</script>
+
+</head>
+<body onLoad="init_spell();">
+
+<script type="text/javascript">
+wordWindowObj.writeBody();
+</script>
+
+</body>
+</html>
+EOF
+
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js
new file mode 100644
index 000000000..b5e55b74b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js
@@ -0,0 +1,462 @@
+////////////////////////////////////////////////////
+// spellChecker.js
+//
+// spellChecker object
+//
+// This file is sourced on web pages that have a textarea object to evaluate
+// for spelling. It includes the implementation for the spellCheckObject.
+//
+////////////////////////////////////////////////////
+
+
+// constructor
+function spellChecker( textObject ) {
+
+ // public properties - configurable
+// this.popUpUrl = '/speller/spellchecker.html'; // by FredCK
+ this.popUpUrl = 'fck_spellerpages/spellerpages/spellchecker.html'; // by FredCK
+ this.popUpName = 'spellchecker';
+// this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; // by FredCK
+ this.popUpProps = null ; // by FredCK
+// this.spellCheckScript = '/speller/server-scripts/spellchecker.php'; // by FredCK
+ //this.spellCheckScript = '/cgi-bin/spellchecker.pl';
+
+ // values used to keep track of what happened to a word
+ this.replWordFlag = "R"; // single replace
+ this.ignrWordFlag = "I"; // single ignore
+ this.replAllFlag = "RA"; // replace all occurances
+ this.ignrAllFlag = "IA"; // ignore all occurances
+ this.fromReplAll = "~RA"; // an occurance of a "replace all" word
+ this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word
+ // properties set at run time
+ this.wordFlags = new Array();
+ this.currentTextIndex = 0;
+ this.currentWordIndex = 0;
+ this.spellCheckerWin = null;
+ this.controlWin = null;
+ this.wordWin = null;
+ this.textArea = textObject; // deprecated
+ this.textInputs = arguments;
+
+ // private methods
+ this._spellcheck = _spellcheck;
+ this._getSuggestions = _getSuggestions;
+ this._setAsIgnored = _setAsIgnored;
+ this._getTotalReplaced = _getTotalReplaced;
+ this._setWordText = _setWordText;
+ this._getFormInputs = _getFormInputs;
+
+ // public methods
+ this.openChecker = openChecker;
+ this.startCheck = startCheck;
+ this.checkTextBoxes = checkTextBoxes;
+ this.checkTextAreas = checkTextAreas;
+ this.spellCheckAll = spellCheckAll;
+ this.ignoreWord = ignoreWord;
+ this.ignoreAll = ignoreAll;
+ this.replaceWord = replaceWord;
+ this.replaceAll = replaceAll;
+ this.terminateSpell = terminateSpell;
+ this.undo = undo;
+
+ // set the current window's "speller" property to the instance of this class.
+ // this object can now be referenced by child windows/frames.
+ window.speller = this;
+}
+
+// call this method to check all text boxes (and only text boxes) in the HTML document
+function checkTextBoxes() {
+ this.textInputs = this._getFormInputs( "^text$" );
+ this.openChecker();
+}
+
+// call this method to check all textareas (and only textareas ) in the HTML document
+function checkTextAreas() {
+ this.textInputs = this._getFormInputs( "^textarea$" );
+ this.openChecker();
+}
+
+// call this method to check all text boxes and textareas in the HTML document
+function spellCheckAll() {
+ this.textInputs = this._getFormInputs( "^text(area)?$" );
+ this.openChecker();
+}
+
+// call this method to check text boxe(s) and/or textarea(s) that were passed in to the
+// object's constructor or to the textInputs property
+function openChecker() {
+ this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps );
+ if( !this.spellCheckerWin.opener ) {
+ this.spellCheckerWin.opener = window;
+ }
+}
+
+function startCheck( wordWindowObj, controlWindowObj ) {
+
+ // set properties from args
+ this.wordWin = wordWindowObj;
+ this.controlWin = controlWindowObj;
+
+ // reset properties
+ this.wordWin.resetForm();
+ this.controlWin.resetForm();
+ this.currentTextIndex = 0;
+ this.currentWordIndex = 0;
+ // initialize the flags to an array - one element for each text input
+ this.wordFlags = new Array( this.wordWin.textInputs.length );
+ // each element will be an array that keeps track of each word in the text
+ for( var i=0; i<this.wordFlags.length; i++ ) {
+ this.wordFlags[i] = [];
+ }
+
+ // start
+ this._spellcheck();
+
+ return true;
+}
+
+function ignoreWord() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ if( !this.wordWin.getTextVal( ti, wi )) {
+ alert( 'Error: "Not in dictionary" text is missing.' );
+ return false;
+ }
+ // set as ignored
+ if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) {
+ this.currentWordIndex++;
+ this._spellcheck();
+ }
+ return true;
+}
+
+function ignoreAll() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ // get the word that is currently being evaluated.
+ var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
+ if( !s_word_to_repl ) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+
+ // set this word as an "ignore all" word.
+ this._setAsIgnored( ti, wi, this.ignrAllFlag );
+
+ // loop through all the words after this word
+ for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
+ for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == ti && j > wi ) || i > ti ) {
+ // future word: set as "from ignore all" if
+ // 1) do not already have a flag and
+ // 2) have the same value as current word
+ if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
+ && ( !this.wordFlags[i][j] )) {
+ this._setAsIgnored( i, j, this.fromIgnrAll );
+ }
+ }
+ }
+ }
+
+ // finally, move on
+ this.currentWordIndex++;
+ this._spellcheck();
+ return true;
+}
+
+function replaceWord() {
+ var wi = this.currentWordIndex;
+ var ti = this.currentTextIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ if( !this.wordWin.getTextVal( ti, wi )) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+ if( !this.controlWin.replacementText ) {
+ return false ;
+ }
+ var txt = this.controlWin.replacementText;
+ if( txt.value ) {
+ var newspell = new String( txt.value );
+ if( this._setWordText( ti, wi, newspell, this.replWordFlag )) {
+ this.currentWordIndex++;
+ this._spellcheck();
+ }
+ }
+ return true;
+}
+
+function replaceAll() {
+ var ti = this.currentTextIndex;
+ var wi = this.currentWordIndex;
+ if( !this.wordWin ) {
+ alert( 'Error: Word frame not available.' );
+ return false;
+ }
+ var s_word_to_repl = this.wordWin.getTextVal( ti, wi );
+ if( !s_word_to_repl ) {
+ alert( 'Error: "Not in dictionary" text is missing' );
+ return false;
+ }
+ var txt = this.controlWin.replacementText;
+ if( !txt.value ) return false;
+ var newspell = new String( txt.value );
+
+ // set this word as a "replace all" word.
+ this._setWordText( ti, wi, newspell, this.replAllFlag );
+
+ // loop through all the words after this word
+ for( var i = ti; i < this.wordWin.textInputs.length; i++ ) {
+ for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == ti && j > wi ) || i > ti ) {
+ // future word: set word text to s_word_to_repl if
+ // 1) do not already have a flag and
+ // 2) have the same value as s_word_to_repl
+ if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl )
+ && ( !this.wordFlags[i][j] )) {
+ this._setWordText( i, j, newspell, this.fromReplAll );
+ }
+ }
+ }
+ }
+
+ // finally, move on
+ this.currentWordIndex++;
+ this._spellcheck();
+ return true;
+}
+
+function terminateSpell() {
+ // called when we have reached the end of the spell checking.
+ var msg = ""; // by FredCK
+ var numrepl = this._getTotalReplaced();
+ if( numrepl == 0 ) {
+ // see if there were no misspellings to begin with
+ if( !this.wordWin ) {
+ msg = "";
+ } else {
+ if( this.wordWin.totalMisspellings() ) {
+// msg += "No words changed."; // by FredCK
+ msg += FCKLang.DlgSpellNoChanges ; // by FredCK
+ } else {
+// msg += "No misspellings found."; // by FredCK
+ msg += FCKLang.DlgSpellNoMispell ; // by FredCK
+ }
+ }
+ } else if( numrepl == 1 ) {
+// msg += "One word changed."; // by FredCK
+ msg += FCKLang.DlgSpellOneChange ; // by FredCK
+ } else {
+// msg += numrepl + " words changed."; // by FredCK
+ msg += FCKLang.DlgSpellManyChanges.replace( /%1/g, numrepl ) ;
+ }
+ if( msg ) {
+// msg += "\n"; // by FredCK
+ alert( msg );
+ }
+
+ if( numrepl > 0 ) {
+ // update the text field(s) on the opener window
+ for( var i = 0; i < this.textInputs.length; i++ ) {
+ // this.textArea.value = this.wordWin.text;
+ if( this.wordWin ) {
+ if( this.wordWin.textInputs[i] ) {
+ this.textInputs[i].value = this.wordWin.textInputs[i];
+ }
+ }
+ }
+ }
+
+ // return back to the calling window
+// this.spellCheckerWin.close(); // by FredCK
+ if ( typeof( this.OnFinished ) == 'function' ) // by FredCK
+ this.OnFinished(numrepl) ; // by FredCK
+
+ return true;
+}
+
+function undo() {
+ // skip if this is the first word!
+ var ti = this.currentTextIndex;
+ var wi = this.currentWordIndex;
+
+ if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) {
+ this.wordWin.removeFocus( ti, wi );
+
+ // go back to the last word index that was acted upon
+ do {
+ // if the current word index is zero then reset the seed
+ if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) {
+ this.currentTextIndex--;
+ this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1;
+ if( this.currentWordIndex < 0 ) this.currentWordIndex = 0;
+ } else {
+ if( this.currentWordIndex > 0 ) {
+ this.currentWordIndex--;
+ }
+ }
+ } while (
+ this.wordWin.totalWords( this.currentTextIndex ) == 0
+ || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll
+ || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll
+ );
+
+ var text_idx = this.currentTextIndex;
+ var idx = this.currentWordIndex;
+ var preReplSpell = this.wordWin.originalSpellings[text_idx][idx];
+
+ // if we got back to the first word then set the Undo button back to disabled
+ if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) {
+ this.controlWin.disableUndo();
+ }
+
+ var i, j, origSpell ;
+ // examine what happened to this current word.
+ switch( this.wordFlags[text_idx][idx] ) {
+ // replace all: go through this and all the future occurances of the word
+ // and revert them all to the original spelling and clear their flags
+ case this.replAllFlag :
+ for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
+ for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == text_idx && j >= idx ) || i > text_idx ) {
+ origSpell = this.wordWin.originalSpellings[i][j];
+ if( origSpell == preReplSpell ) {
+ this._setWordText ( i, j, origSpell, undefined );
+ }
+ }
+ }
+ }
+ break;
+
+ // ignore all: go through all the future occurances of the word
+ // and clear their flags
+ case this.ignrAllFlag :
+ for( i = text_idx; i < this.wordWin.textInputs.length; i++ ) {
+ for( j = 0; j < this.wordWin.totalWords( i ); j++ ) {
+ if(( i == text_idx && j >= idx ) || i > text_idx ) {
+ origSpell = this.wordWin.originalSpellings[i][j];
+ if( origSpell == preReplSpell ) {
+ this.wordFlags[i][j] = undefined;
+ }
+ }
+ }
+ }
+ break;
+
+ // replace: revert the word to its original spelling
+ case this.replWordFlag :
+ this._setWordText ( text_idx, idx, preReplSpell, undefined );
+ break;
+ }
+
+ // For all four cases, clear the wordFlag of this word. re-start the process
+ this.wordFlags[text_idx][idx] = undefined;
+ this._spellcheck();
+ }
+}
+
+function _spellcheck() {
+ var ww = this.wordWin;
+
+ // check if this is the last word in the current text element
+ if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) {
+ this.currentTextIndex++;
+ this.currentWordIndex = 0;
+ // keep going if we're not yet past the last text element
+ if( this.currentTextIndex < this.wordWin.textInputs.length ) {
+ this._spellcheck();
+ return;
+ } else {
+ this.terminateSpell();
+ return;
+ }
+ }
+
+ // if this is after the first one make sure the Undo button is enabled
+ if( this.currentWordIndex > 0 ) {
+ this.controlWin.enableUndo();
+ }
+
+ // skip the current word if it has already been worked on
+ if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) {
+ // increment the global current word index and move on.
+ this.currentWordIndex++;
+ this._spellcheck();
+ } else {
+ var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex );
+ if( evalText ) {
+ this.controlWin.evaluatedText.value = evalText;
+ ww.setFocus( this.currentTextIndex, this.currentWordIndex );
+ this._getSuggestions( this.currentTextIndex, this.currentWordIndex );
+ }
+ }
+}
+
+function _getSuggestions( text_num, word_num ) {
+ this.controlWin.clearSuggestions();
+ // add suggestion in list for each suggested word.
+ // get the array of suggested words out of the
+ // three-dimensional array containing all suggestions.
+ var a_suggests = this.wordWin.suggestions[text_num][word_num];
+ if( a_suggests ) {
+ // got an array of suggestions.
+ for( var ii = 0; ii < a_suggests.length; ii++ ) {
+ this.controlWin.addSuggestion( a_suggests[ii] );
+ }
+ }
+ this.controlWin.selectDefaultSuggestion();
+}
+
+function _setAsIgnored( text_num, word_num, flag ) {
+ // set the UI
+ this.wordWin.removeFocus( text_num, word_num );
+ // do the bookkeeping
+ this.wordFlags[text_num][word_num] = flag;
+ return true;
+}
+
+function _getTotalReplaced() {
+ var i_replaced = 0;
+ for( var i = 0; i < this.wordFlags.length; i++ ) {
+ for( var j = 0; j < this.wordFlags[i].length; j++ ) {
+ if(( this.wordFlags[i][j] == this.replWordFlag )
+ || ( this.wordFlags[i][j] == this.replAllFlag )
+ || ( this.wordFlags[i][j] == this.fromReplAll )) {
+ i_replaced++;
+ }
+ }
+ }
+ return i_replaced;
+}
+
+function _setWordText( text_num, word_num, newText, flag ) {
+ // set the UI and form inputs
+ this.wordWin.setText( text_num, word_num, newText );
+ // keep track of what happened to this word:
+ this.wordFlags[text_num][word_num] = flag;
+ return true;
+}
+
+function _getFormInputs( inputPattern ) {
+ var inputs = new Array();
+ for( var i = 0; i < document.forms.length; i++ ) {
+ for( var j = 0; j < document.forms[i].elements.length; j++ ) {
+ if( document.forms[i].elements[j].type.match( inputPattern )) {
+ inputs[inputs.length] = document.forms[i].elements[j];
+ }
+ }
+ }
+ return inputs;
+}
+
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html
new file mode 100644
index 000000000..cbcd7db79
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html
@@ -0,0 +1,71 @@
+
+<script>
+
+var wordWindow = null;
+var controlWindow = null;
+
+function init_spell( spellerWindow ) {
+
+ if( spellerWindow ) {
+ if( spellerWindow.windowType == "wordWindow" ) {
+ wordWindow = spellerWindow;
+ } else if ( spellerWindow.windowType == "controlWindow" ) {
+ controlWindow = spellerWindow;
+ }
+ }
+
+ if( controlWindow && wordWindow ) {
+ // populate the speller object and start it off!
+ var speller = opener.speller;
+ wordWindow.speller = speller;
+ speller.startCheck( wordWindow, controlWindow );
+ }
+}
+
+// encodeForPost
+function encodeForPost( str ) {
+ var s = new String( str );
+ s = encodeURIComponent( s );
+ // additionally encode single quotes to evade any PHP
+ // magic_quotes_gpc setting (it inserts escape characters and
+ // therefore skews the btye positions of misspelled words)
+ return s.replace( /\'/g, '%27' );
+}
+
+// post the text area data to the script that populates the speller
+function postWords() {
+ var bodyDoc = window.frames[0].document;
+ bodyDoc.open();
+ bodyDoc.write('<html>');
+ bodyDoc.write('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">');
+ bodyDoc.write('<link rel="stylesheet" type="text/css" href="spellerStyle.css"/>');
+ if (opener) {
+ var speller = opener.speller;
+ bodyDoc.write('<body class="normalText" onLoad="document.forms[0].submit();">');
+ bodyDoc.write('<p>' + window.parent.FCKLang.DlgSpellProgress + '<\/p>'); // by FredCK
+ bodyDoc.write('<form action="'+speller.spellCheckScript+'" method="post">');
+ for( var i = 0; i < speller.textInputs.length; i++ ) {
+ bodyDoc.write('<input type="hidden" name="textinputs[]" value="'+encodeForPost(speller.textInputs[i].value)+'">');
+ }
+ bodyDoc.write('<\/form>');
+ bodyDoc.write('<\/body>');
+ } else {
+ bodyDoc.write('<body class="normalText">');
+ bodyDoc.write('<p><b>This page cannot be displayed<\/b><\/p><p>The window was not opened from another window.<\/p>');
+ bodyDoc.write('<\/body>');
+ }
+ bodyDoc.write('<\/html>');
+ bodyDoc.close();
+}
+</script>
+
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<head>
+<title>Speller Pages</title>
+</head>
+<frameset rows="*,201" onLoad="postWords();">
+<frame src="blank.html">
+<frame src="controls.html">
+</frameset>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css
new file mode 100644
index 000000000..4df608d8b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css
@@ -0,0 +1,49 @@
+.blend {
+ font-family: courier new;
+ font-size: 10pt;
+ border: 0;
+ margin-bottom:-1;
+}
+.normalLabel {
+ font-size:8pt;
+}
+.normalText {
+ font-family:arial, helvetica, sans-serif;
+ font-size:10pt;
+ color:000000;
+ background-color:FFFFFF;
+}
+.plainText {
+ font-family: courier new, courier, monospace;
+ font-size: 10pt;
+ color:000000;
+ background-color:FFFFFF;
+}
+.controlWindowBody {
+ font-family:arial, helvetica, sans-serif;
+ font-size:8pt;
+ padding: 7px ; /* by FredCK */
+ margin: 0px ; /* by FredCK */
+ /* color:000000; by FredCK */
+ /* background-color:DADADA; by FredCK */
+}
+.readonlyInput {
+ background-color:DADADA;
+ color:000000;
+ font-size:8pt;
+ width:392px;
+}
+.textDefault {
+ font-size:8pt;
+ width: 200px;
+}
+.buttonDefault {
+ width:90px;
+ height:22px;
+ font-size:8pt;
+}
+.suggSlct {
+ width:200px;
+ margin-top:2;
+ font-size:8pt;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js
new file mode 100644
index 000000000..7990296a2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js
@@ -0,0 +1,272 @@
+////////////////////////////////////////////////////
+// wordWindow object
+////////////////////////////////////////////////////
+function wordWindow() {
+ // private properties
+ this._forms = [];
+
+ // private methods
+ this._getWordObject = _getWordObject;
+ //this._getSpellerObject = _getSpellerObject;
+ this._wordInputStr = _wordInputStr;
+ this._adjustIndexes = _adjustIndexes;
+ this._isWordChar = _isWordChar;
+ this._lastPos = _lastPos;
+
+ // public properties
+ this.wordChar = /[a-zA-Z]/;
+ this.windowType = "wordWindow";
+ this.originalSpellings = new Array();
+ this.suggestions = new Array();
+ this.checkWordBgColor = "pink";
+ this.normWordBgColor = "white";
+ this.text = "";
+ this.textInputs = new Array();
+ this.indexes = new Array();
+ //this.speller = this._getSpellerObject();
+
+ // public methods
+ this.resetForm = resetForm;
+ this.totalMisspellings = totalMisspellings;
+ this.totalWords = totalWords;
+ this.totalPreviousWords = totalPreviousWords;
+ //this.getTextObjectArray = getTextObjectArray;
+ this.getTextVal = getTextVal;
+ this.setFocus = setFocus;
+ this.removeFocus = removeFocus;
+ this.setText = setText;
+ //this.getTotalWords = getTotalWords;
+ this.writeBody = writeBody;
+ this.printForHtml = printForHtml;
+}
+
+function resetForm() {
+ if( this._forms ) {
+ for( var i = 0; i < this._forms.length; i++ ) {
+ this._forms[i].reset();
+ }
+ }
+ return true;
+}
+
+function totalMisspellings() {
+ var total_words = 0;
+ for( var i = 0; i < this.textInputs.length; i++ ) {
+ total_words += this.totalWords( i );
+ }
+ return total_words;
+}
+
+function totalWords( textIndex ) {
+ return this.originalSpellings[textIndex].length;
+}
+
+function totalPreviousWords( textIndex, wordIndex ) {
+ var total_words = 0;
+ for( var i = 0; i <= textIndex; i++ ) {
+ for( var j = 0; j < this.totalWords( i ); j++ ) {
+ if( i == textIndex && j == wordIndex ) {
+ break;
+ } else {
+ total_words++;
+ }
+ }
+ }
+ return total_words;
+}
+
+//function getTextObjectArray() {
+// return this._form.elements;
+//}
+
+function getTextVal( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ return word.value;
+ }
+}
+
+function setFocus( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ if( word.type == "text" ) {
+ word.focus();
+ word.style.backgroundColor = this.checkWordBgColor;
+ }
+ }
+}
+
+function removeFocus( textIndex, wordIndex ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ if( word ) {
+ if( word.type == "text" ) {
+ word.blur();
+ word.style.backgroundColor = this.normWordBgColor;
+ }
+ }
+}
+
+function setText( textIndex, wordIndex, newText ) {
+ var word = this._getWordObject( textIndex, wordIndex );
+ var beginStr;
+ var endStr;
+ if( word ) {
+ var pos = this.indexes[textIndex][wordIndex];
+ var oldText = word.value;
+ // update the text given the index of the string
+ beginStr = this.textInputs[textIndex].substring( 0, pos );
+ endStr = this.textInputs[textIndex].substring(
+ pos + oldText.length,
+ this.textInputs[textIndex].length
+ );
+ this.textInputs[textIndex] = beginStr + newText + endStr;
+
+ // adjust the indexes on the stack given the differences in
+ // length between the new word and old word.
+ var lengthDiff = newText.length - oldText.length;
+ this._adjustIndexes( textIndex, wordIndex, lengthDiff );
+
+ word.size = newText.length;
+ word.value = newText;
+ this.removeFocus( textIndex, wordIndex );
+ }
+}
+
+
+function writeBody() {
+ var d = window.document;
+ var is_html = false;
+
+ d.open();
+
+ // iterate through each text input.
+ for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) {
+ var end_idx = 0;
+ var begin_idx = 0;
+ d.writeln( '<form name="textInput'+txtid+'">' );
+ var wordtxt = this.textInputs[txtid];
+ this.indexes[txtid] = [];
+
+ if( wordtxt ) {
+ var orig = this.originalSpellings[txtid];
+ if( !orig ) break;
+
+ //!!! plain text, or HTML mode?
+ d.writeln( '<div class="plainText">' );
+ // iterate through each occurrence of a misspelled word.
+ for( var i = 0; i < orig.length; i++ ) {
+ // find the position of the current misspelled word,
+ // starting at the last misspelled word.
+ // and keep looking if it's a substring of another word
+ do {
+ begin_idx = wordtxt.indexOf( orig[i], end_idx );
+ end_idx = begin_idx + orig[i].length;
+ // word not found? messed up!
+ if( begin_idx == -1 ) break;
+ // look at the characters immediately before and after
+ // the word. If they are word characters we'll keep looking.
+ var before_char = wordtxt.charAt( begin_idx - 1 );
+ var after_char = wordtxt.charAt( end_idx );
+ } while (
+ this._isWordChar( before_char )
+ || this._isWordChar( after_char )
+ );
+
+ // keep track of its position in the original text.
+ this.indexes[txtid][i] = begin_idx;
+
+ // write out the characters before the current misspelled word
+ for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) {
+ // !!! html mode? make it html compatible
+ d.write( this.printForHtml( wordtxt.charAt( j )));
+ }
+
+ // write out the misspelled word.
+ d.write( this._wordInputStr( orig[i] ));
+
+ // if it's the last word, write out the rest of the text
+ if( i == orig.length-1 ){
+ d.write( printForHtml( wordtxt.substr( end_idx )));
+ }
+ }
+
+ d.writeln( '</div>' );
+
+ }
+ d.writeln( '</form>' );
+ }
+ //for ( var j = 0; j < d.forms.length; j++ ) {
+ // alert( d.forms[j].name );
+ // for( var k = 0; k < d.forms[j].elements.length; k++ ) {
+ // alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value );
+ // }
+ //}
+
+ // set the _forms property
+ this._forms = d.forms;
+ d.close();
+}
+
+// return the character index in the full text after the last word we evaluated
+function _lastPos( txtid, idx ) {
+ if( idx > 0 )
+ return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length;
+ else
+ return 0;
+}
+
+function printForHtml( n ) {
+ return n ; // by FredCK
+/*
+ var htmlstr = n;
+ if( htmlstr.length == 1 ) {
+ // do simple case statement if it's just one character
+ switch ( n ) {
+ case "\n":
+ htmlstr = '<br/>';
+ break;
+ case "<":
+ htmlstr = '&lt;';
+ break;
+ case ">":
+ htmlstr = '&gt;';
+ break;
+ }
+ return htmlstr;
+ } else {
+ htmlstr = htmlstr.replace( /</g, '&lt' );
+ htmlstr = htmlstr.replace( />/g, '&gt' );
+ htmlstr = htmlstr.replace( /\n/g, '<br/>' );
+ return htmlstr;
+ }
+*/
+}
+
+function _isWordChar( letter ) {
+ if( letter.search( this.wordChar ) == -1 ) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+function _getWordObject( textIndex, wordIndex ) {
+ if( this._forms[textIndex] ) {
+ if( this._forms[textIndex].elements[wordIndex] ) {
+ return this._forms[textIndex].elements[wordIndex];
+ }
+ }
+ return null;
+}
+
+function _wordInputStr( word ) {
+ var str = '<input readonly ';
+ str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">';
+ return str;
+}
+
+function _adjustIndexes( textIndex, wordIndex, lengthDiff ) {
+ for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) {
+ this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff;
+ }
+}
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_table.html b/httemplate/elements/fckeditor/editor/dialog/fck_table.html
new file mode 100644
index 000000000..6bb9d1101
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_table.html
@@ -0,0 +1,291 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Table dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Table Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+// Gets the table if there is one selected.
+var table ;
+var e = oEditor.FCKSelection.GetSelectedElement() ;
+
+if ( ( !e && document.location.search.substr(1) == 'Parent' ) || ( e && e.tagName != 'TABLE' ) )
+ e = oEditor.FCKSelection.MoveToAncestorNode( 'TABLE' ) ;
+
+if ( e && e.tagName == "TABLE" )
+ table = e ;
+
+// Fired when the window loading process is finished. It sets the fields with the
+// actual values if a table is selected in the editor.
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if (table)
+ {
+ document.getElementById('txtRows').value = table.rows.length ;
+ document.getElementById('txtColumns').value = table.rows[0].cells.length ;
+
+ // Gets the value from the Width or the Style attribute
+ var iWidth = (table.style.width ? table.style.width : table.width ) ;
+ var iHeight = (table.style.height ? table.style.height : table.height ) ;
+
+ if (iWidth.indexOf('%') >= 0) // Percentual = %
+ {
+ iWidth = parseInt( iWidth.substr(0,iWidth.length - 1), 10 ) ;
+ document.getElementById('selWidthType').value = "percent" ;
+ }
+ else if (iWidth.indexOf('px') >= 0) // Style Pixel = px
+ { //
+ iWidth = iWidth.substr(0,iWidth.length - 2);
+ document.getElementById('selWidthType').value = "pixels" ;
+ }
+
+ if (iHeight && iHeight.indexOf('px') >= 0) // Style Pixel = px
+ iHeight = iHeight.substr(0,iHeight.length - 2);
+
+ document.getElementById('txtWidth').value = iWidth || '' ;
+ document.getElementById('txtHeight').value = iHeight || '' ;
+ document.getElementById('txtBorder').value = GetAttribute( table, 'border', '' ) ;
+ document.getElementById('selAlignment').value = GetAttribute( table, 'align', '' ) ;
+ document.getElementById('txtCellPadding').value = GetAttribute( table, 'cellPadding', '' ) ;
+ document.getElementById('txtCellSpacing').value = GetAttribute( table, 'cellSpacing', '' ) ;
+ document.getElementById('txtSummary').value = GetAttribute( table, 'summary', '' ) ;
+// document.getElementById('cmbFontStyle').value = table.className ;
+
+ if (table.caption) document.getElementById('txtCaption').value = table.caption.innerHTML ;
+
+ document.getElementById('txtRows').disabled = true ;
+ document.getElementById('txtColumns').disabled = true ;
+ }
+
+ window.parent.SetOkButton( true ) ;
+ window.parent.SetAutoSize( true ) ;
+}
+
+// Fired when the user press the OK button
+function Ok()
+{
+ var bExists = ( table != null ) ;
+
+ if ( ! bExists )
+ table = oEditor.FCK.EditorDocument.createElement( "TABLE" ) ;
+
+ // Removes the Width and Height styles
+ if ( bExists && table.style.width ) table.style.width = null ; //.removeAttribute("width") ;
+ if ( bExists && table.style.height ) table.style.height = null ; //.removeAttribute("height") ;
+
+ var sWidth = GetE('txtWidth').value ;
+ if ( sWidth.length > 0 && GetE('selWidthType').value == 'percent' )
+ sWidth += '%' ;
+
+ SetAttribute( table, 'width' , sWidth ) ;
+ SetAttribute( table, 'height' , GetE('txtHeight').value ) ;
+ SetAttribute( table, 'border' , GetE('txtBorder').value ) ;
+ SetAttribute( table, 'align' , GetE('selAlignment').value ) ;
+ SetAttribute( table, 'cellPadding' , GetE('txtCellPadding').value ) ;
+ SetAttribute( table, 'cellSpacing' , GetE('txtCellSpacing').value ) ;
+ SetAttribute( table, 'summary' , GetE('txtSummary').value ) ;
+
+ var eCaption = oEditor.FCKDomTools.GetFirstChild( table, 'CAPTION' ) ;
+
+ if ( document.getElementById('txtCaption').value != '')
+ {
+ if ( !eCaption )
+ {
+ eCaption = oEditor.FCK.EditorDocument.createElement( 'CAPTION' ) ;
+ table.insertBefore( eCaption, table.firstChild ) ;
+ }
+
+ eCaption.innerHTML = document.getElementById('txtCaption').value ;
+ }
+ else if ( bExists && eCaption )
+ {
+ if ( oEditor.FCKBrowserInfo.IsIE )
+ eCaption.innerHTML = '' ; // TODO: It causes an IE internal error if using removeChild or table.deleteCaption().
+ else
+ eCaption.parentNode.removeChild( eCaption ) ;
+ }
+
+ if (! bExists)
+ {
+ var iRows = document.getElementById('txtRows').value ;
+ var iCols = document.getElementById('txtColumns').value ;
+
+ for ( var r = 0 ; r < iRows ; r++ )
+ {
+ var oRow = table.insertRow(-1) ;
+ for ( var c = 0 ; c < iCols ; c++ )
+ {
+ var oCell = oRow.insertCell(-1) ;
+ if ( oEditor.FCKBrowserInfo.IsGeckoLike )
+ oCell.innerHTML = GECKO_BOGUS ;
+ //oCell.innerHTML = "&nbsp;" ;
+ }
+ }
+
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ oEditor.FCK.InsertElement( table ) ;
+ }
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table id="otable" cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 100%">
+ <tr>
+ <td>
+ <table cellspacing="1" cellpadding="1" width="100%" border="0">
+ <tr>
+ <td valign="top">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgTableRows">Rows</span>:</td>
+ <td>
+ &nbsp;<input id="txtRows" type="text" maxlength="3" size="2" value="3" name="txtRows"
+ onkeypress="return IsDigit(event);" /></td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTableColumns">Columns</span>:</td>
+ <td>
+ &nbsp;<input id="txtColumns" type="text" maxlength="2" size="2" value="2" name="txtColumns"
+ onkeypress="return IsDigit(event);" /></td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTableBorder">Border size</span>:</td>
+ <td>
+ &nbsp;<input id="txtBorder" type="text" maxlength="2" size="2" value="1" name="txtBorder"
+ onkeypress="return IsDigit(event);" /></td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTableAlign">Alignment</span>:</td>
+ <td>
+ &nbsp;<select id="selAlignment" name="selAlignment">
+ <option fcklang="DlgTableAlignNotSet" value="" selected="selected">&lt;Not set&gt;</option>
+ <option fcklang="DlgTableAlignLeft" value="left">Left</option>
+ <option fcklang="DlgTableAlignCenter" value="center">Center</option>
+ <option fcklang="DlgTableAlignRight" value="right">Right</option>
+ </select></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;</td>
+ <td align="right" valign="top">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgTableWidth">Width</span>:</td>
+ <td>
+ &nbsp;<input id="txtWidth" type="text" maxlength="4" size="3" value="200" name="txtWidth"
+ onkeypress="return IsDigit(event);" /></td>
+ <td>
+ &nbsp;<select id="selWidthType" name="selWidthType">
+ <option fcklang="DlgTableWidthPx" value="pixels" selected="selected">pixels</option>
+ <option fcklang="DlgTableWidthPc" value="percent">percent</option>
+ </select></td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTableHeight">Height</span>:</td>
+ <td>
+ &nbsp;<input id="txtHeight" type="text" maxlength="4" size="3" name="txtHeight" onkeypress="return IsDigit(event);" /></td>
+ <td>
+ &nbsp;<span fcklang="DlgTableWidthPx">pixels</span></td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgTableCellSpace">Cell spacing</span>:</td>
+ <td>
+ &nbsp;<input id="txtCellSpacing" type="text" maxlength="2" size="2" value="1" name="txtCellSpacing"
+ onkeypress="return IsDigit(event);" /></td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgTableCellPad">Cell padding</span>:</td>
+ <td>
+ &nbsp;<input id="txtCellPadding" type="text" maxlength="2" size="2" value="1" name="txtCellPadding"
+ onkeypress="return IsDigit(event);" /></td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgTableCaption">Caption</span>:&nbsp;</td>
+ <td>
+ &nbsp;</td>
+ <td width="100%" nowrap="nowrap">
+ <input id="txtCaption" type="text" style="width: 100%" /></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgTableSummary">Summary</span>:&nbsp;</td>
+ <td>
+ &nbsp;</td>
+ <td width="100%" nowrap="nowrap">
+ <input id="txtSummary" type="text" style="width: 100%" /></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_tablecell.html b/httemplate/elements/fckeditor/editor/dialog/fck_tablecell.html
new file mode 100644
index 000000000..b7c536bce
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_tablecell.html
@@ -0,0 +1,255 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Cell properties dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Table Cell Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+// Array of selected Cells
+var aCells = oEditor.FCKTableHandler.GetSelectedCells() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage( document ) ;
+
+ SetStartupValue() ;
+
+ window.parent.SetOkButton( true ) ;
+ window.parent.SetAutoSize( true ) ;
+}
+
+function SetStartupValue()
+{
+ if ( aCells.length > 0 )
+ {
+ var oCell = aCells[0] ;
+ var iWidth = GetAttribute( oCell, 'width' ) ;
+
+ if ( iWidth.indexOf && iWidth.indexOf( '%' ) >= 0 )
+ {
+ iWidth = iWidth.substr( 0, iWidth.length - 1 ) ;
+ GetE('selWidthType').value = 'percent' ;
+ }
+
+ if ( oCell.attributes['noWrap'] != null && oCell.attributes['noWrap'].specified )
+ GetE('selWordWrap').value = !oCell.noWrap ;
+
+ GetE('txtWidth').value = iWidth ;
+ GetE('txtHeight').value = GetAttribute( oCell, 'height' ) ;
+ GetE('selHAlign').value = GetAttribute( oCell, 'align' ) ;
+ GetE('selVAlign').value = GetAttribute( oCell, 'vAlign' ) ;
+ GetE('txtRowSpan').value = GetAttribute( oCell, 'rowSpan' ) ;
+ GetE('txtCollSpan').value = GetAttribute( oCell, 'colSpan' ) ;
+ GetE('txtBackColor').value = GetAttribute( oCell, 'bgColor' ) ;
+ GetE('txtBorderColor').value = GetAttribute( oCell, 'borderColor' ) ;
+// GetE('cmbFontStyle').value = oCell.className ;
+ }
+}
+
+// Fired when the user press the OK button
+function Ok()
+{
+ for( i = 0 ; i < aCells.length ; i++ )
+ {
+ if ( GetE('txtWidth').value.length > 0 )
+ aCells[i].width = GetE('txtWidth').value + ( GetE('selWidthType').value == 'percent' ? '%' : '') ;
+ else
+ aCells[i].removeAttribute( 'width', 0 ) ;
+
+ if ( GetE('selWordWrap').value == 'false' )
+ aCells[i].noWrap = true ;
+ else
+ aCells[i].removeAttribute( 'noWrap' ) ;
+
+ SetAttribute( aCells[i], 'height' , GetE('txtHeight').value ) ;
+ SetAttribute( aCells[i], 'align' , GetE('selHAlign').value ) ;
+ SetAttribute( aCells[i], 'vAlign' , GetE('selVAlign').value ) ;
+ SetAttribute( aCells[i], 'rowSpan' , GetE('txtRowSpan').value ) ;
+ SetAttribute( aCells[i], 'colSpan' , GetE('txtCollSpan').value ) ;
+ SetAttribute( aCells[i], 'bgColor' , GetE('txtBackColor').value ) ;
+ SetAttribute( aCells[i], 'borderColor' , GetE('txtBorderColor').value ) ;
+// SetAttribute( aCells[i], 'className' , GetE('cmbFontStyle').value ) ;
+ }
+
+ return true ;
+}
+
+function SelectBackColor( color )
+{
+ if ( color && color.length > 0 )
+ GetE('txtBackColor').value = color ;
+}
+
+function SelectBorderColor( color )
+{
+ if ( color && color.length > 0 )
+ GetE('txtBorderColor').value = color ;
+}
+
+function SelectColor( wich )
+{
+ oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', oEditor.FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 400, 330, wich == 'Back' ? SelectBackColor : SelectBorderColor, window ) ;
+}
+
+ </script>
+</head>
+<body scroll="no" style="overflow: hidden">
+ <table cellspacing="0" cellpadding="0" width="100%" border="0" height="100%">
+ <tr>
+ <td>
+ <table cellspacing="1" cellpadding="1" width="100%" border="0">
+ <tr>
+ <td>
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellWidth">Width</span>:</td>
+ <td>
+ &nbsp;<input onkeypress="return IsDigit(event);" id="txtWidth" type="text" maxlength="4"
+ size="3" name="txtWidth" />&nbsp;<select id="selWidthType" name="selWidthType">
+ <option fcklang="DlgCellWidthPx" value="pixels" selected="selected">pixels</option>
+ <option fcklang="DlgCellWidthPc" value="percent">percent</option>
+ </select></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellHeight">Height</span>:</td>
+ <td>
+ &nbsp;<input id="txtHeight" type="text" maxlength="4" size="3" name="txtHeight" onkeypress="return IsDigit(event);" />&nbsp;<span
+ fcklang="DlgCellWidthPx">pixels</span></td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellWordWrap">Word Wrap</span>:</td>
+ <td>
+ &nbsp;<select id="selWordWrap" name="selAlignment">
+ <option fcklang="DlgCellWordWrapYes" value="true" selected="selected">Yes</option>
+ <option fcklang="DlgCellWordWrapNo" value="false">No</option>
+ </select></td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellHorAlign">Horizontal Alignment</span>:</td>
+ <td>
+ &nbsp;<select id="selHAlign" name="selAlignment">
+ <option fcklang="DlgCellHorAlignNotSet" value="" selected>&lt;Not set&gt;</option>
+ <option fcklang="DlgCellHorAlignLeft" value="left">Left</option>
+ <option fcklang="DlgCellHorAlignCenter" value="center">Center</option>
+ <option fcklang="DlgCellHorAlignRight" value="right">Right</option>
+ </select></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellVerAlign">Vertical Alignment</span>:</td>
+ <td>
+ &nbsp;<select id="selVAlign" name="selAlignment">
+ <option fcklang="DlgCellVerAlignNotSet" value="" selected>&lt;Not set&gt;</option>
+ <option fcklang="DlgCellVerAlignTop" value="top">Top</option>
+ <option fcklang="DlgCellVerAlignMiddle" value="middle">Middle</option>
+ <option fcklang="DlgCellVerAlignBottom" value="bottom">Bottom</option>
+ <option fcklang="DlgCellVerAlignBaseline" value="baseline">Baseline</option>
+ </select></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;</td>
+ <td align="right">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellRowSpan">Rows Span</span>:</td>
+ <td>
+ &nbsp;
+ <input onkeypress="return IsDigit(event);" id="txtRowSpan" type="text" maxlength="3" size="2"
+ name="txtRows"></td>
+ <td>
+ </td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellCollSpan">Columns Span</span>:</td>
+ <td>
+ &nbsp;
+ <input onkeypress="return IsDigit(event);" id="txtCollSpan" type="text" maxlength="2"
+ size="2" name="txtColumns"></td>
+ <td>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ <td>
+ &nbsp;</td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellBackColor">Background Color</span>:</td>
+ <td>
+ &nbsp;<input id="txtBackColor" type="text" size="8" name="txtCellSpacing"></td>
+ <td>
+ &nbsp;
+ <input type="button" fcklang="DlgCellBtnSelect" value="Select..." onclick="SelectColor( 'Back' )"></td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <span fcklang="DlgCellBorderColor">Border Color</span>:</td>
+ <td>
+ &nbsp;<input id="txtBorderColor" type="text" size="8" name="txtCellPadding" /></td>
+ <td>
+ &nbsp;
+ <input type="button" fcklang="DlgCellBtnSelect" value="Select..." onclick="SelectColor( 'Border' )" /></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_template.html b/httemplate/elements/fckeditor/editor/dialog/fck_template.html
new file mode 100644
index 000000000..418e9dff3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_template.html
@@ -0,0 +1,242 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Template selection dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <style type="text/css">
+ .TplList
+ {
+ border: #dcdcdc 2px solid;
+ background-color: #ffffff;
+ overflow: auto;
+ width: 90%;
+ }
+
+ .TplItem
+ {
+ margin: 5px;
+ padding: 7px;
+ border: #eeeeee 1px solid;
+ }
+
+ .TplItem TABLE
+ {
+ display: inline;
+ }
+
+ .TplTitle
+ {
+ font-weight: bold;
+ }
+ </style>
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCK = oEditor.FCK ;
+var FCKLang = oEditor.FCKLang ;
+var FCKConfig = oEditor.FCKConfig ;
+
+window.onload = function()
+{
+ // Set the right box height (browser dependent).
+ GetE('eList').style.height = document.all ? '100%' : '295px' ;
+
+ // Translate the dialog box texts.
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ GetE('xChkReplaceAll').checked = ( FCKConfig.TemplateReplaceAll !== false ) ;
+
+ if ( FCKConfig.TemplateReplaceCheckbox !== false )
+ GetE('xReplaceBlock').style.display = '' ;
+
+ window.parent.SetAutoSize( true ) ;
+
+ LoadTemplatesXml() ;
+}
+
+function LoadTemplatesXml()
+{
+ var oTemplate ;
+
+ if ( !FCK._Templates )
+ {
+ GetE('eLoading').style.display = '' ;
+
+ // Create the Templates array.
+ FCK._Templates = new Array() ;
+
+ // Load the XML file.
+ var oXml = new oEditor.FCKXml() ;
+ oXml.LoadUrl( FCKConfig.TemplatesXmlPath ) ;
+
+ // Get the Images Base Path.
+ var oAtt = oXml.SelectSingleNode( 'Templates/@imagesBasePath' ) ;
+ var sImagesBasePath = oAtt ? oAtt.value : '' ;
+
+ // Get the "Template" nodes defined in the XML file.
+ var aTplNodes = oXml.SelectNodes( 'Templates/Template' ) ;
+
+ for ( var i = 0 ; i < aTplNodes.length ; i++ )
+ {
+ var oNode = aTplNodes[i] ;
+
+ oTemplate = new Object() ;
+
+ var oPart ;
+
+ // Get the Template Title.
+ if ( (oPart = oNode.attributes.getNamedItem('title')) )
+ oTemplate.Title = oPart.value ;
+ else
+ oTemplate.Title = 'Template ' + ( i + 1 ) ;
+
+ // Get the Template Description.
+ if ( (oPart = oXml.SelectSingleNode( 'Description', oNode )) )
+ oTemplate.Description = oPart.text ? oPart.text : oPart.textContent ;
+
+ // Get the Template Image.
+ if ( (oPart = oNode.attributes.getNamedItem('image')) )
+ oTemplate.Image = sImagesBasePath + oPart.value ;
+
+ // Get the Template HTML.
+ if ( (oPart = oXml.SelectSingleNode( 'Html', oNode )) )
+ oTemplate.Html = oPart.text ? oPart.text : oPart.textContent ;
+ else
+ {
+ alert( 'No HTML defined for template index ' + i + '. Please review the "' + FCKConfig.TemplatesXmlPath + '" file.' ) ;
+ continue ;
+ }
+
+ FCK._Templates[ FCK._Templates.length ] = oTemplate ;
+ }
+
+ GetE('eLoading').style.display = 'none' ;
+ }
+
+ if ( FCK._Templates.length == 0 )
+ GetE('eEmpty').style.display = '' ;
+ else
+ {
+ for ( var j = 0 ; j < FCK._Templates.length ; j++ )
+ {
+ oTemplate = FCK._Templates[j] ;
+
+ var oItemDiv = GetE('eList').appendChild( document.createElement( 'DIV' ) ) ;
+ oItemDiv.TplIndex = j ;
+ oItemDiv.className = 'TplItem' ;
+
+ // Build the inner HTML of our new item DIV.
+ var sInner = '<table><tr>' ;
+
+ if ( oTemplate.Image )
+ sInner += '<td valign="top"><img src="' + oTemplate.Image + '"><\/td>' ;
+
+ sInner += '<td valign="top"><div class="TplTitle">' + oTemplate.Title + '<\/div>' ;
+
+ if ( oTemplate.Description )
+ sInner += '<div>' + oTemplate.Description + '<\/div>' ;
+
+ sInner += '<\/td><\/tr><\/table>' ;
+
+ oItemDiv.innerHTML = sInner ;
+
+ oItemDiv.onmouseover = ItemDiv_OnMouseOver ;
+ oItemDiv.onmouseout = ItemDiv_OnMouseOut ;
+ oItemDiv.onclick = ItemDiv_OnClick ;
+ }
+ }
+}
+
+function ItemDiv_OnMouseOver()
+{
+ this.className += ' PopupSelectionBox' ;
+}
+
+function ItemDiv_OnMouseOut()
+{
+ this.className = this.className.replace( /\s*PopupSelectionBox\s*/, '' ) ;
+}
+
+function ItemDiv_OnClick()
+{
+ SelectTemplate( this.TplIndex ) ;
+}
+
+function SelectTemplate( index )
+{
+ oEditor.FCKUndo.SaveUndoStep() ;
+
+ if ( GetE('xChkReplaceAll').checked )
+ FCK.SetHTML( FCK._Templates[index].Html ) ;
+ else
+ FCK.InsertHtml( FCK._Templates[index].Html ) ;
+
+ window.parent.Cancel( true ) ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table width="100%" style="height: 100%">
+ <tr>
+ <td align="center">
+ <span fcklang="DlgTemplatesSelMsg">Please select the template to open in the editor<br />
+ (the actual contents will be lost):</span>
+ </td>
+ </tr>
+ <tr>
+ <td height="100%" align="center">
+ <div id="eList" align="left" class="TplList">
+ <div id="eLoading" align="center" style="display: none">
+ <br />
+ <span fcklang="DlgTemplatesLoading">Loading templates list. Please wait...</span>
+ </div>
+ <div id="eEmpty" align="center" style="display: none">
+ <br />
+ <span fcklang="DlgTemplatesNoTpl">(No templates defined)</span>
+ </div>
+ </div>
+ </td>
+ </tr>
+ <tr id="xReplaceBlock" style="display: none">
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <input id="xChkReplaceAll" type="checkbox" /></td>
+ <td>
+ &nbsp;</td>
+ <td>
+ <label for="xChkReplaceAll" fcklang="DlgTemplatesReplace">
+ Replace actual contents</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template1.gif b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template1.gif
new file mode 100644
index 000000000..efdabbebd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template1.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template2.gif b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template2.gif
new file mode 100644
index 000000000..d1cebb3ae
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template2.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template3.gif b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template3.gif
new file mode 100644
index 000000000..db41cb4fb
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_template/images/template3.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_textarea.html b/httemplate/elements/fckeditor/editor/dialog/fck_textarea.html
new file mode 100644
index 000000000..b7de33af7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_textarea.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Text Area dialog window.
+-->
+<html>
+ <head>
+ <title>Text Area Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl && oActiveEl.tagName == 'TEXTAREA' )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtCols').value = GetAttribute( oActiveEl, 'cols' ) ;
+ GetE('txtRows').value = GetAttribute( oActiveEl, 'rows' ) ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'TEXTAREA' ) ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ oActiveEl.name = GetE('txtName').value ;
+ SetAttribute( oActiveEl, 'cols', GetE('txtCols').value ) ;
+ SetAttribute( oActiveEl, 'rows', GetE('txtRows').value ) ;
+
+ return true ;
+}
+
+ </script>
+ </head>
+ <body style='OVERFLOW: hidden' scroll='no'>
+ <table height="100%" width="100%">
+ <tr>
+ <td align="center">
+ <table border="0" cellpadding="0" cellspacing="0" width="80%">
+ <tr>
+ <td>
+ <span fckLang="DlgTextareaName">Name</span><br>
+ <input type="text" id="txtName" style="WIDTH: 100%">
+ <span fckLang="DlgTextareaCols">Collumns</span><br>
+ <input id="txtCols" type="text" size="5">
+ <br>
+ <span fckLang="DlgTextareaRows">Rows</span><br>
+ <input id="txtRows" type="text" size="5">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/dialog/fck_textfield.html b/httemplate/elements/fckeditor/editor/dialog/fck_textfield.html
new file mode 100644
index 000000000..7b4c8ef9a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/dialog/fck_textfield.html
@@ -0,0 +1,139 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Text field dialog window.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta content="noindex, nofollow" name="robots" />
+ <script src="common/fck_dialog_common.js" type="text/javascript"></script>
+ <script type="text/javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+
+// Gets the document DOM
+var oDOM = oEditor.FCK.EditorDocument ;
+
+var oActiveEl = oEditor.FCKSelection.GetSelectedElement() ;
+
+window.onload = function()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage(document) ;
+
+ if ( oActiveEl && oActiveEl.tagName == 'INPUT' && ( oActiveEl.type == 'text' || oActiveEl.type == 'password' ) )
+ {
+ GetE('txtName').value = oActiveEl.name ;
+ GetE('txtValue').value = oActiveEl.value ;
+ GetE('txtSize').value = GetAttribute( oActiveEl, 'size' ) ;
+ GetE('txtMax').value = GetAttribute( oActiveEl, 'maxLength' ) ;
+ GetE('txtType').value = oActiveEl.type ;
+
+ GetE('txtType').disabled = true ;
+ }
+ else
+ oActiveEl = null ;
+
+ window.parent.SetOkButton( true ) ;
+}
+
+function Ok()
+{
+ if ( isNaN( GetE('txtMax').value ) || GetE('txtMax').value < 0 )
+ {
+ alert( "Maximum characters must be a positive number." ) ;
+ GetE('txtMax').focus() ;
+ return false ;
+ }
+ else if( isNaN( GetE('txtSize').value ) || GetE('txtSize').value < 0 )
+ {
+ alert( "Width must be a positive number." ) ;
+ GetE('txtSize').focus() ;
+ return false ;
+ }
+
+ if ( !oActiveEl )
+ {
+ oActiveEl = oEditor.FCK.EditorDocument.createElement( 'INPUT' ) ;
+ oActiveEl.type = GetE('txtType').value ;
+ oActiveEl = oEditor.FCK.InsertElementAndGetIt( oActiveEl ) ;
+ }
+
+ oActiveEl.name = GetE('txtName').value ;
+ SetAttribute( oActiveEl, 'value' , GetE('txtValue').value ) ;
+ SetAttribute( oActiveEl, 'size' , GetE('txtSize').value ) ;
+ SetAttribute( oActiveEl, 'maxlength', GetE('txtMax').value ) ;
+
+ return true ;
+}
+
+ </script>
+</head>
+<body style="overflow: hidden">
+ <table width="100%" style="height: 100%">
+ <tr>
+ <td align="center">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <span fcklang="DlgTextName">Name</span><br />
+ <input id="txtName" type="text" size="20" />
+ </td>
+ <td>
+ </td>
+ <td>
+ <span fcklang="DlgTextValue">Value</span><br />
+ <input id="txtValue" type="text" size="25" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTextCharWidth">Character Width</span><br />
+ <input id="txtSize" type="text" size="5" />
+ </td>
+ <td>
+ </td>
+ <td>
+ <span fcklang="DlgTextMaxChars">Maximum Characters</span><br />
+ <input id="txtMax" type="text" size="5" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span fcklang="DlgTextType">Type</span><br />
+ <select id="txtType">
+ <option value="text" selected="selected" fcklang="DlgTextTypeText">Text</option>
+ <option value="password" fcklang="DlgTextTypePass">Password</option>
+ </select>
+ </td>
+ <td>
+ &nbsp;</td>
+ <td>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/fckdebug.html b/httemplate/elements/fckeditor/editor/fckdebug.html
new file mode 100644
index 000000000..db99d6055
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/fckdebug.html
@@ -0,0 +1,153 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the Debug window.
+ * It automatically popups if the Debug = true in the configuration file.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>FCKeditor Debug Window</title>
+ <meta name="robots" content="noindex, nofollow" />
+ <script type="text/javascript">
+
+var oWindow ;
+var oDiv ;
+
+if ( !window.FCKMessages )
+ window.FCKMessages = new Array() ;
+
+window.onload = function()
+{
+ oWindow = document.getElementById('xOutput').contentWindow ;
+ oWindow.document.open() ;
+ oWindow.document.write( '<div id="divMsg"><\/div>' ) ;
+ oWindow.document.close() ;
+ oDiv = oWindow.document.getElementById('divMsg') ;
+}
+
+function Output( message, color, noParse )
+{
+ if ( !noParse && message != null && isNaN( message ) )
+ message = message.replace(/</g, "&lt;") ;
+
+ if ( color )
+ message = '<font color="' + color + '">' + message + '<\/font>' ;
+
+ window.FCKMessages[ window.FCKMessages.length ] = message ;
+ StartTimer() ;
+}
+
+function OutputObject( anyObject, color )
+{
+ var message ;
+
+ if ( anyObject != null )
+ {
+ message = 'Properties of: ' + anyObject + '</b><blockquote>' ;
+
+ for (var prop in anyObject)
+ {
+ try
+ {
+ var sVal = anyObject[ prop ] != null ? anyObject[ prop ] + '' : '[null]' ;
+ message += '<b>' + prop + '</b> : ' + sVal.replace(/</g, '&lt;') + '<br>' ;
+ }
+ catch (e)
+ {
+ try
+ {
+ message += '<b>' + prop + '</b> : [' + typeof( anyObject[ prop ] ) + ']<br>' ;
+ }
+ catch (e)
+ {
+ message += '<b>' + prop + '</b> : [-error-]<br>' ;
+ }
+ }
+ }
+
+ message += '</blockquote><b>' ;
+ } else
+ message = 'OutputObject : Object is "null".' ;
+
+ Output( message, color, true ) ;
+}
+
+function StartTimer()
+{
+ window.setTimeout( 'CheckMessages()', 100 ) ;
+}
+
+function CheckMessages()
+{
+ if ( window.FCKMessages.length > 0 )
+ {
+ // Get the first item in the queue
+ var sMessage = window.FCKMessages[0] ;
+
+ // Removes the first item from the queue
+ var oTempArray = new Array() ;
+ for ( i = 1 ; i < window.FCKMessages.length ; i++ )
+ oTempArray[ i - 1 ] = window.FCKMessages[ i ] ;
+ window.FCKMessages = oTempArray ;
+
+ var d = new Date() ;
+ var sTime =
+ ( d.getHours() + 100 + '' ).substr( 1,2 ) + ':' +
+ ( d.getMinutes() + 100 + '' ).substr( 1,2 ) + ':' +
+ ( d.getSeconds() + 100 + '' ).substr( 1,2 ) + ':' +
+ ( d.getMilliseconds() + 1000 + '' ).substr( 1,3 ) ;
+
+ var oMsgDiv = oWindow.document.createElement( 'div' ) ;
+ oMsgDiv.innerHTML = sTime + ': <b>' + sMessage + '<\/b>' ;
+ oDiv.appendChild( oMsgDiv ) ;
+ oMsgDiv.scrollIntoView() ;
+ }
+}
+
+function Clear()
+{
+ oDiv.innerHTML = '' ;
+}
+ </script>
+</head>
+<body style="margin: 10px">
+ <table style="height: 100%" cellspacing="5" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td>
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td style="font-weight: bold; font-size: 1.2em;">
+ FCKeditor Debug Window</td>
+ <td align="right">
+ <input type="button" value="Clear" onclick="Clear();" /></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr style="height: 100%">
+ <td style="border: #696969 1px solid">
+ <iframe id="xOutput" width="100%" height="100%" scrolling="auto" src="javascript:void(0)"
+ frameborder="0"></iframe>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/fckdialog.html b/httemplate/elements/fckeditor/editor/fckdialog.html
new file mode 100644
index 000000000..7f26822e3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/fckdialog.html
@@ -0,0 +1,324 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page is used by all dialog box as the container.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="robots" content="noindex, nofollow" />
+ <script type="text/javascript">
+
+// On some Gecko browsers (probably over slow connections) the
+// "dialogArguments" are not set so we must get it from the opener window.
+if ( !window.dialogArguments )
+ window.dialogArguments = window.opener.FCKLastDialogInfo ;
+
+// Sets the Skin CSS
+document.write( '<link href="' + window.dialogArguments.Editor.FCKConfig.SkinPath + 'fck_dialog.css" type="text/css" rel="stylesheet">' ) ;
+
+// Sets the language direction.
+window.document.dir = window.dialogArguments.Editor.FCKLang.Dir ;
+
+var sTitle = window.dialogArguments.Title ;
+document.write( '<title>' + sTitle + '<\/title>' ) ;
+
+function LoadInnerDialog()
+{
+ if ( window.onresize )
+ window.onresize() ;
+
+ // First of all, translate the dialog box contents.
+ window.dialogArguments.Editor.FCKLanguageManager.TranslatePage( document ) ;
+
+ window.frames["frmMain"].document.location.href = window.dialogArguments.Page ;
+}
+
+function InnerDialogLoaded()
+{
+ var oInnerDoc = document.getElementById('frmMain').contentWindow.document ;
+
+ // Set the language direction.
+ oInnerDoc.dir = window.dialogArguments.Editor.FCKLang.Dir ;
+
+ // Sets the Skin CSS.
+ oInnerDoc.write( '<link href="' + window.dialogArguments.Editor.FCKConfig.SkinPath + 'fck_dialog.css" type="text/css" rel="stylesheet">' ) ;
+
+ SetOnKeyDown( oInnerDoc ) ;
+ DisableContextMenu( oInnerDoc ) ;
+
+ return window.dialogArguments.Editor ;
+}
+
+function SetOkButton( showIt )
+{
+ document.getElementById('btnOk').style.visibility = ( showIt ? '' : 'hidden' ) ;
+}
+
+var bAutoSize = false ;
+
+function SetAutoSize( autoSize )
+{
+ bAutoSize = autoSize ;
+ RefreshSize() ;
+}
+
+function RefreshSize()
+{
+ if ( bAutoSize )
+ {
+ var oInnerDoc = document.getElementById('frmMain').contentWindow.document ;
+
+ var iFrameHeight ;
+ if ( document.all )
+ iFrameHeight = oInnerDoc.body.offsetHeight ;
+ else
+ iFrameHeight = document.getElementById('frmMain').contentWindow.innerHeight ;
+
+ var iInnerHeight = oInnerDoc.body.scrollHeight ;
+
+ var iDiff = iInnerHeight - iFrameHeight ;
+
+ if ( iDiff > 0 )
+ {
+ if ( document.all )
+ window.dialogHeight = ( parseInt( window.dialogHeight, 10 ) + iDiff ) + 'px' ;
+ else
+ window.resizeBy( 0, iDiff ) ;
+ }
+ }
+}
+
+function Ok()
+{
+ if ( window.frames["frmMain"].Ok && window.frames["frmMain"].Ok() )
+ Cancel() ;
+}
+
+function Cancel( dontFireChange )
+{
+ if ( !dontFireChange )
+ {
+ // All dialog windows, by default, will fire the "OnSelectionChange"
+ // event, no matter the Ok or Cancel button has been pressed.
+ window.dialogArguments.Editor.FCK.Events.FireEvent( 'OnSelectionChange' ) ;
+ }
+ window.close() ;
+}
+
+// Object that holds all available tabs.
+var oTabs = new Object() ;
+
+function TabDiv_OnClick()
+{
+ SetSelectedTab( this.TabCode ) ;
+}
+
+function AddTab( tabCode, tabText, startHidden )
+{
+ if ( typeof( oTabs[ tabCode ] ) != 'undefined' )
+ return ;
+
+ var eTabsRow = document.getElementById( 'Tabs' ) ;
+
+ var oCell = eTabsRow.insertCell( eTabsRow.cells.length - 1 ) ;
+ oCell.noWrap = true ;
+
+ var oDiv = document.createElement( 'DIV' ) ;
+ oDiv.className = 'PopupTab' ;
+ oDiv.innerHTML = tabText ;
+ oDiv.TabCode = tabCode ;
+ oDiv.onclick = TabDiv_OnClick ;
+
+ if ( startHidden )
+ oDiv.style.display = 'none' ;
+
+ eTabsRow = document.getElementById( 'TabsRow' ) ;
+
+ oCell.appendChild( oDiv ) ;
+
+ if ( eTabsRow.style.display == 'none' )
+ {
+ var eTitleArea = document.getElementById( 'TitleArea' ) ;
+ eTitleArea.className = 'PopupTitle' ;
+
+ oDiv.className = 'PopupTabSelected' ;
+ eTabsRow.style.display = '' ;
+
+ if ( ! window.dialogArguments.Editor.FCKBrowserInfo.IsIE )
+ window.onresize() ;
+ }
+
+ oTabs[ tabCode ] = oDiv ;
+}
+
+function SetSelectedTab( tabCode )
+{
+ for ( var sCode in oTabs )
+ {
+ if ( sCode == tabCode )
+ oTabs[sCode].className = 'PopupTabSelected' ;
+ else
+ oTabs[sCode].className = 'PopupTab' ;
+ }
+
+ if ( typeof( window.frames["frmMain"].OnDialogTabChange ) == 'function' )
+ window.frames["frmMain"].OnDialogTabChange( tabCode ) ;
+}
+
+function SetTabVisibility( tabCode, isVisible )
+{
+ var oTab = oTabs[ tabCode ] ;
+ oTab.style.display = isVisible ? '' : 'none' ;
+
+ if ( ! isVisible && oTab.className == 'PopupTabSelected' )
+ {
+ for ( var sCode in oTabs )
+ {
+ if ( oTabs[sCode].style.display != 'none' )
+ {
+ SetSelectedTab( sCode ) ;
+ break ;
+ }
+ }
+ }
+}
+
+function SetOnKeyDown( targetDocument )
+{
+ targetDocument.onkeydown = function ( e )
+ {
+ e = e || event || this.parentWindow.event ;
+ switch ( e.keyCode )
+ {
+ case 13 : // ENTER
+ var oTarget = e.srcElement || e.target ;
+ if ( oTarget.tagName == 'TEXTAREA' )
+ return true ;
+ Ok() ;
+ return false ;
+ case 27 : // ESC
+ Cancel() ;
+ return false ;
+ break ;
+ }
+ return true ;
+ }
+}
+SetOnKeyDown( document ) ;
+
+function DisableContextMenu( targetDocument )
+{
+ if ( window.dialogArguments.Editor.FCKBrowserInfo.IsIE ) return ;
+
+ // Disable Right-Click
+ var oOnContextMenu = function( e )
+ {
+ var sTagName = e.target.tagName ;
+ if ( ! ( ( sTagName == "INPUT" && e.target.type == "text" ) || sTagName == "TEXTAREA" ) )
+ e.preventDefault() ;
+ }
+ targetDocument.addEventListener( 'contextmenu', oOnContextMenu, true ) ;
+}
+DisableContextMenu( document ) ;
+
+if ( ! window.dialogArguments.Editor.FCKBrowserInfo.IsIE )
+{
+ window.onresize = function()
+ {
+ var oFrame = document.getElementById("frmMain") ;
+
+ if ( ! oFrame )
+ return ;
+
+ oFrame.height = 0 ;
+
+ var oCell = document.getElementById("FrameCell") ;
+ var iHeight = oCell.offsetHeight ;
+
+ oFrame.height = iHeight - 2 ;
+ }
+}
+
+if ( window.dialogArguments.Editor.FCKBrowserInfo.IsIE )
+{
+ function Window_OnBeforeUnload()
+ {
+ for ( var t in oTabs )
+ oTabs[t] = null ;
+
+ window.dialogArguments.Editor = null ;
+ }
+ window.attachEvent( "onbeforeunload", Window_OnBeforeUnload ) ;
+}
+
+function Window_OnClose()
+{
+ window.dialogArguments.Editor.FCKFocusManager.Unlock() ;
+}
+
+if ( window.addEventListener )
+ window.addEventListener( 'unload', Window_OnClose, false ) ;
+
+ </script>
+ </head>
+ <body onload="LoadInnerDialog();" class="PopupBody">
+ <table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td id="TitleArea" class="PopupTitle PopupTitleBorder">
+ <script type="text/javascript">
+document.write( sTitle ) ;
+ </script>
+ </td>
+ </tr>
+ <tr id="TabsRow" style="DISPLAY: none">
+ <td class="PopupTabArea">
+ <table border="0" cellpadding="0" cellspacing="0" width="100%">
+ <tr id="Tabs" onselectstart="return false;">
+ <td class="PopupTabEmptyArea">&nbsp;</td>
+ <td class="PopupTabEmptyArea" width="100%">&nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="FrameCell" height="100%" valign="top">
+ <iframe id="frmMain" src="javascript:void(0)" name="frmMain" frameborder="0" height="100%" width="100%" scrolling="auto">
+ </iframe>
+ </td>
+ </tr>
+ <tr>
+ <td class="PopupButtons">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="100%">&nbsp;</td>
+ <td nowrap="nowrap">
+ <input id="btnOk" style="VISIBILITY: hidden;" type="button" value="Ok" class="Button" onclick="Ok();" fckLang="DlgBtnOK" />
+ &nbsp;
+ <input id="btnCancel" type="button" value="Cancel" class="Button" onclick="Cancel();" fckLang="DlgBtnCancel" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/fckeditor.html b/httemplate/elements/fckeditor/editor/fckeditor.html
new file mode 100644
index 000000000..25ad37e00
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/fckeditor.html
@@ -0,0 +1,227 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Main page that holds the editor.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>FCKeditor</title>
+ <meta name="robots" content="noindex, nofollow" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta http-equiv="Cache-Control" content="public" />
+ <script type="text/javascript">
+
+// Instead of loading scripts and CSSs using inline tags, all scripts are
+// loaded by code. In this way we can guarantee the correct processing order,
+// otherwise external scripts and inline scripts could be executed in an
+// unwanted order (IE).
+
+function LoadScript( url )
+{
+ document.write( '<scr' + 'ipt type="text/javascript" src="' + url + '" onerror="alert(\'Error loading \' + this.src);"><\/scr' + 'ipt>' ) ;
+}
+
+function LoadCss( url )
+{
+ document.write( '<link href="' + url + '" type="text/css" rel="stylesheet" onerror="alert(\'Error loading \' + this.src);" />' ) ;
+}
+
+// Main editor scripts.
+var sSuffix = /msie/.test( navigator.userAgent.toLowerCase() ) ? 'ie' : 'gecko' ;
+
+LoadScript( 'js/fckeditorcode_' + sSuffix + '.js' ) ;
+
+// Base configuration file.
+LoadScript( '../fckconfig.js' ) ;
+
+ </script>
+ <script type="text/javascript">
+
+if ( FCKBrowserInfo.IsIE )
+{
+ // Remove IE mouse flickering.
+ try
+ {
+ document.execCommand( 'BackgroundImageCache', false, true ) ;
+ }
+ catch (e)
+ {
+ // We have been reported about loading problems caused by the above
+ // line. For safety, let's just ignore errors.
+ }
+
+ // Create the default cleanup object used by the editor.
+ FCK.IECleanup = new FCKIECleanup( window ) ;
+ FCK.IECleanup.AddItem( FCKTempBin, FCKTempBin.Reset ) ;
+ FCK.IECleanup.AddItem( FCK, FCK_Cleanup ) ;
+}
+
+// The config hidden field is processed immediately, because
+// CustomConfigurationsPath may be set in the page.
+FCKConfig.ProcessHiddenField() ;
+
+// Load the custom configurations file (if defined).
+if ( FCKConfig.CustomConfigurationsPath.length > 0 )
+ LoadScript( FCKConfig.CustomConfigurationsPath ) ;
+
+ </script>
+ <script type="text/javascript">
+
+// Load configurations defined at page level.
+FCKConfig_LoadPageConfig() ;
+
+FCKConfig_PreProcess() ;
+
+// Load the active skin CSS.
+LoadCss( FCKConfig.SkinPath + 'fck_editor.css' ) ;
+
+// Load the language file.
+FCKLanguageManager.Initialize() ;
+LoadScript( 'lang/' + FCKLanguageManager.ActiveLanguage.Code + '.js' ) ;
+
+ </script>
+ <script type="text/javascript">
+
+// Initialize the editing area context menu.
+FCK_ContextMenu_Init() ;
+
+FCKPlugins.Load() ;
+
+ </script>
+ <script type="text/javascript">
+
+// Set the editor interface direction.
+window.document.dir = FCKLang.Dir ;
+
+// Activate pasting operations.
+if ( FCKConfig.ForcePasteAsPlainText || FCKConfig.AutoDetectPasteFromWord )
+ FCK.Events.AttachEvent( 'OnPaste', FCK.Paste ) ;
+
+ </script>
+ <script type="text/javascript">
+
+window.onload = function()
+{
+ InitializeAPI() ;
+
+ if ( FCKBrowserInfo.IsIE )
+ FCK_PreloadImages() ;
+ else
+ LoadToolbarSetup() ;
+}
+
+function LoadToolbarSetup()
+{
+ FCKeditorAPI._FunctionQueue.Add( LoadToolbar ) ;
+}
+
+function LoadToolbar()
+{
+ var oToolbarSet = FCK.ToolbarSet = FCKToolbarSet_Create() ;
+
+ if ( oToolbarSet.IsLoaded )
+ StartEditor() ;
+ else
+ {
+ oToolbarSet.OnLoad = StartEditor ;
+ oToolbarSet.Load( FCKURLParams['Toolbar'] || 'Default' ) ;
+ }
+}
+
+function StartEditor()
+{
+ // Remove the onload listener.
+ FCK.ToolbarSet.OnLoad = null ;
+
+ FCKeditorAPI._FunctionQueue.Remove( LoadToolbar ) ;
+
+ FCK.Events.AttachEvent( 'OnStatusChange', WaitForActive ) ;
+
+ // Start the editor.
+ FCK.StartEditor() ;
+}
+
+function WaitForActive( editorInstance, newStatus )
+{
+ if ( newStatus == FCK_STATUS_ACTIVE )
+ {
+ if ( FCKBrowserInfo.IsGecko )
+ FCKTools.RunFunction( window.onresize ) ;
+
+ _AttachFormSubmitToAPI() ;
+
+ FCK.SetStatus( FCK_STATUS_COMPLETE ) ;
+
+ // Call the special "FCKeditor_OnComplete" function that should be present in
+ // the HTML page where the editor is located.
+ if ( typeof( window.parent.FCKeditor_OnComplete ) == 'function' )
+ window.parent.FCKeditor_OnComplete( FCK ) ;
+ }
+}
+
+// Gecko browsers doens't calculate well that IFRAME size so we must
+// recalculate it every time the window size changes.
+if ( FCKBrowserInfo.IsGecko )
+{
+ function Window_OnResize()
+ {
+ if ( FCKBrowserInfo.IsOpera )
+ return ;
+
+ var oCell = document.getElementById( 'xEditingArea' ) ;
+
+ var eInnerElement = oCell.firstChild ;
+ if ( eInnerElement )
+ {
+ eInnerElement.style.height = 0 ;
+ eInnerElement.style.height = oCell.scrollHeight - 2 ;
+ }
+ }
+ window.onresize = Window_OnResize ;
+}
+
+ </script>
+</head>
+<body>
+ <table width="100%" cellpadding="0" cellspacing="0" style="height: 100%; table-layout: fixed">
+ <tr id="xToolbarRow" style="display: none">
+ <td id="xToolbarSpace" style="overflow: hidden">
+ <table width="100%" cellpadding="0" cellspacing="0">
+ <tr id="xCollapsed" style="display: none">
+ <td id="xExpandHandle" class="TB_Expand" colspan="3">
+ <img class="TB_ExpandImg" alt="" src="images/spacer.gif" width="8" height="4" /></td>
+ </tr>
+ <tr id="xExpanded" style="display: none">
+ <td id="xTBLeftBorder" class="TB_SideBorder" style="width: 1px; display: none;"></td>
+ <td id="xCollapseHandle" style="display: none" class="TB_Collapse" valign="bottom">
+ <img class="TB_CollapseImg" alt="" src="images/spacer.gif" width="8" height="4" /></td>
+ <td id="xToolbar" class="TB_ToolbarSet"></td>
+ <td class="TB_SideBorder" style="width: 1px"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="xEditingArea" valign="top" style="height: 100%"></td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/fckeditor.original.html b/httemplate/elements/fckeditor/editor/fckeditor.original.html
new file mode 100644
index 000000000..846eed991
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/fckeditor.original.html
@@ -0,0 +1,319 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Main page that holds the editor.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>FCKeditor</title>
+ <meta name="robots" content="noindex, nofollow" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <!-- @Packager.RemoveLine
+ <meta http-equiv="Cache-Control" content="public" />
+ @Packager.RemoveLine -->
+ <script type="text/javascript">
+
+// Instead of loading scripts and CSSs using inline tags, all scripts are
+// loaded by code. In this way we can guarantee the correct processing order,
+// otherwise external scripts and inline scripts could be executed in an
+// unwanted order (IE).
+
+function LoadScript( url )
+{
+ document.write( '<scr' + 'ipt type="text/javascript" src="' + url + '" onerror="alert(\'Error loading \' + this.src);"><\/scr' + 'ipt>' ) ;
+}
+
+function LoadCss( url )
+{
+ document.write( '<link href="' + url + '" type="text/css" rel="stylesheet" onerror="alert(\'Error loading \' + this.src);" />' ) ;
+}
+
+// Main editor scripts.
+var sSuffix = /msie/.test( navigator.userAgent.toLowerCase() ) ? 'ie' : 'gecko' ;
+
+/* @Packager.RemoveLine
+LoadScript( 'js/fckeditorcode_' + sSuffix + '.js' ) ;
+@Packager.RemoveLine */
+// @Packager.Remove.Start
+
+LoadScript( '_source/fckconstants.js' ) ;
+LoadScript( '_source/fckjscoreextensions.js' ) ;
+
+if ( sSuffix == 'ie' )
+ LoadScript( '_source/classes/fckiecleanup.js' ) ;
+
+LoadScript( '_source/internals/fckbrowserinfo.js' ) ;
+LoadScript( '_source/internals/fckurlparams.js' ) ;
+LoadScript( '_source/classes/fckevents.js' ) ;
+LoadScript( '_source/internals/fck.js' ) ;
+LoadScript( '_source/internals/fck_' + sSuffix + '.js' ) ;
+LoadScript( '_source/internals/fckconfig.js' ) ;
+
+LoadScript( '_source/internals/fckdebug.js' ) ;
+LoadScript( '_source/internals/fckdomtools.js' ) ;
+LoadScript( '_source/internals/fcktools.js' ) ;
+LoadScript( '_source/internals/fcktools_' + sSuffix + '.js' ) ;
+LoadScript( '_source/fckeditorapi.js' ) ;
+LoadScript( '_source/classes/fckimagepreloader.js' ) ;
+LoadScript( '_source/internals/fckregexlib.js' ) ;
+LoadScript( '_source/internals/fcklistslib.js' ) ;
+LoadScript( '_source/internals/fcklanguagemanager.js' ) ;
+LoadScript( '_source/internals/fckxhtmlentities.js' ) ;
+LoadScript( '_source/internals/fckxhtml.js' ) ;
+LoadScript( '_source/internals/fckxhtml_' + sSuffix + '.js' ) ;
+LoadScript( '_source/internals/fckcodeformatter.js' ) ;
+LoadScript( '_source/internals/fckundo_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckeditingarea.js' ) ;
+LoadScript( '_source/classes/fckkeystrokehandler.js' ) ;
+
+LoadScript( '_source/internals/fcklisthandler.js' ) ;
+LoadScript( '_source/classes/fckelementpath.js' ) ;
+LoadScript( '_source/classes/fckdomrange.js' ) ;
+LoadScript( '_source/classes/fckdocumentfragment_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckw3crange.js' ) ;
+LoadScript( '_source/classes/fckdomrange_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckenterkey.js' ) ;
+
+LoadScript( '_source/internals/fckdocumentprocessor.js' ) ;
+LoadScript( '_source/internals/fckselection.js' ) ;
+LoadScript( '_source/internals/fckselection_' + sSuffix + '.js' ) ;
+
+LoadScript( '_source/internals/fcktablehandler.js' ) ;
+LoadScript( '_source/internals/fcktablehandler_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckxml_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckstyledef.js' ) ;
+LoadScript( '_source/classes/fckstyledef_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckstylesloader.js' ) ;
+
+LoadScript( '_source/commandclasses/fcknamedcommand.js' ) ;
+LoadScript( '_source/commandclasses/fck_othercommands.js' ) ;
+LoadScript( '_source/commandclasses/fckspellcheckcommand_' + sSuffix + '.js' ) ;
+LoadScript( '_source/commandclasses/fcktextcolorcommand.js' ) ;
+LoadScript( '_source/commandclasses/fckpasteplaintextcommand.js' ) ;
+LoadScript( '_source/commandclasses/fckpastewordcommand.js' ) ;
+LoadScript( '_source/commandclasses/fcktablecommand.js' ) ;
+LoadScript( '_source/commandclasses/fckstylecommand.js' ) ;
+LoadScript( '_source/commandclasses/fckfitwindow.js' ) ;
+LoadScript( '_source/internals/fckcommands.js' ) ;
+
+LoadScript( '_source/classes/fckpanel.js' ) ;
+LoadScript( '_source/classes/fckicon.js' ) ;
+LoadScript( '_source/classes/fcktoolbarbuttonui.js' ) ;
+LoadScript( '_source/classes/fcktoolbarbutton.js' ) ;
+LoadScript( '_source/classes/fckspecialcombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarspecialcombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarfontscombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarfontsizecombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarfontformatcombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarstylecombo.js' ) ;
+LoadScript( '_source/classes/fcktoolbarpanelbutton.js' ) ;
+LoadScript( '_source/internals/fcktoolbaritems.js' ) ;
+LoadScript( '_source/classes/fcktoolbar.js' ) ;
+LoadScript( '_source/classes/fcktoolbarbreak_' + sSuffix + '.js' ) ;
+LoadScript( '_source/internals/fcktoolbarset.js' ) ;
+LoadScript( '_source/internals/fckdialog.js' ) ;
+LoadScript( '_source/internals/fckdialog_' + sSuffix + '.js' ) ;
+LoadScript( '_source/classes/fckmenuitem.js' ) ;
+LoadScript( '_source/classes/fckmenublock.js' ) ;
+LoadScript( '_source/classes/fckmenublockpanel.js' ) ;
+LoadScript( '_source/classes/fckcontextmenu.js' ) ;
+LoadScript( '_source/internals/fck_contextmenu.js' ) ;
+LoadScript( '_source/classes/fckplugin.js' ) ;
+LoadScript( '_source/internals/fckplugins.js' ) ;
+
+// @Packager.Remove.End
+
+// Base configuration file.
+LoadScript( '../fckconfig.js' ) ;
+
+ </script>
+ <script type="text/javascript">
+
+if ( FCKBrowserInfo.IsIE )
+{
+ // Remove IE mouse flickering.
+ try
+ {
+ document.execCommand( 'BackgroundImageCache', false, true ) ;
+ }
+ catch (e)
+ {
+ // We have been reported about loading problems caused by the above
+ // line. For safety, let's just ignore errors.
+ }
+
+ // Create the default cleanup object used by the editor.
+ FCK.IECleanup = new FCKIECleanup( window ) ;
+ FCK.IECleanup.AddItem( FCKTempBin, FCKTempBin.Reset ) ;
+ FCK.IECleanup.AddItem( FCK, FCK_Cleanup ) ;
+}
+
+// The config hidden field is processed immediately, because
+// CustomConfigurationsPath may be set in the page.
+FCKConfig.ProcessHiddenField() ;
+
+// Load the custom configurations file (if defined).
+if ( FCKConfig.CustomConfigurationsPath.length > 0 )
+ LoadScript( FCKConfig.CustomConfigurationsPath ) ;
+
+ </script>
+ <script type="text/javascript">
+
+// Load configurations defined at page level.
+FCKConfig_LoadPageConfig() ;
+
+FCKConfig_PreProcess() ;
+
+// Load the active skin CSS.
+LoadCss( FCKConfig.SkinPath + 'fck_editor.css' ) ;
+
+// Load the language file.
+FCKLanguageManager.Initialize() ;
+LoadScript( 'lang/' + FCKLanguageManager.ActiveLanguage.Code + '.js' ) ;
+
+ </script>
+ <script type="text/javascript">
+
+// Initialize the editing area context menu.
+FCK_ContextMenu_Init() ;
+
+FCKPlugins.Load() ;
+
+ </script>
+ <script type="text/javascript">
+
+// Set the editor interface direction.
+window.document.dir = FCKLang.Dir ;
+
+// Activate pasting operations.
+if ( FCKConfig.ForcePasteAsPlainText || FCKConfig.AutoDetectPasteFromWord )
+ FCK.Events.AttachEvent( 'OnPaste', FCK.Paste ) ;
+
+ </script>
+ <script type="text/javascript">
+
+window.onload = function()
+{
+ InitializeAPI() ;
+
+ if ( FCKBrowserInfo.IsIE )
+ FCK_PreloadImages() ;
+ else
+ LoadToolbarSetup() ;
+}
+
+function LoadToolbarSetup()
+{
+ FCKeditorAPI._FunctionQueue.Add( LoadToolbar ) ;
+}
+
+function LoadToolbar()
+{
+ var oToolbarSet = FCK.ToolbarSet = FCKToolbarSet_Create() ;
+
+ if ( oToolbarSet.IsLoaded )
+ StartEditor() ;
+ else
+ {
+ oToolbarSet.OnLoad = StartEditor ;
+ oToolbarSet.Load( FCKURLParams['Toolbar'] || 'Default' ) ;
+ }
+}
+
+function StartEditor()
+{
+ // Remove the onload listener.
+ FCK.ToolbarSet.OnLoad = null ;
+
+ FCKeditorAPI._FunctionQueue.Remove( LoadToolbar ) ;
+
+ FCK.Events.AttachEvent( 'OnStatusChange', WaitForActive ) ;
+
+ // Start the editor.
+ FCK.StartEditor() ;
+}
+
+function WaitForActive( editorInstance, newStatus )
+{
+ if ( newStatus == FCK_STATUS_ACTIVE )
+ {
+ if ( FCKBrowserInfo.IsGecko )
+ FCKTools.RunFunction( window.onresize ) ;
+
+ _AttachFormSubmitToAPI() ;
+
+ FCK.SetStatus( FCK_STATUS_COMPLETE ) ;
+
+ // Call the special "FCKeditor_OnComplete" function that should be present in
+ // the HTML page where the editor is located.
+ if ( typeof( window.parent.FCKeditor_OnComplete ) == 'function' )
+ window.parent.FCKeditor_OnComplete( FCK ) ;
+ }
+}
+
+// Gecko browsers doens't calculate well that IFRAME size so we must
+// recalculate it every time the window size changes.
+if ( FCKBrowserInfo.IsGecko )
+{
+ function Window_OnResize()
+ {
+ if ( FCKBrowserInfo.IsOpera )
+ return ;
+
+ var oCell = document.getElementById( 'xEditingArea' ) ;
+
+ var eInnerElement = oCell.firstChild ;
+ if ( eInnerElement )
+ {
+ eInnerElement.style.height = 0 ;
+ eInnerElement.style.height = oCell.scrollHeight - 2 ;
+ }
+ }
+ window.onresize = Window_OnResize ;
+}
+
+ </script>
+</head>
+<body>
+ <table width="100%" cellpadding="0" cellspacing="0" style="height: 100%; table-layout: fixed">
+ <tr id="xToolbarRow" style="display: none">
+ <td id="xToolbarSpace" style="overflow: hidden">
+ <table width="100%" cellpadding="0" cellspacing="0">
+ <tr id="xCollapsed" style="display: none">
+ <td id="xExpandHandle" class="TB_Expand" colspan="3">
+ <img class="TB_ExpandImg" alt="" src="images/spacer.gif" width="8" height="4" /></td>
+ </tr>
+ <tr id="xExpanded" style="display: none">
+ <td id="xTBLeftBorder" class="TB_SideBorder" style="width: 1px; display: none;"></td>
+ <td id="xCollapseHandle" style="display: none" class="TB_Collapse" valign="bottom">
+ <img class="TB_CollapseImg" alt="" src="images/spacer.gif" width="8" height="4" /></td>
+ <td id="xToolbar" class="TB_ToolbarSet"></td>
+ <td class="TB_SideBorder" style="width: 1px"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="xEditingArea" valign="top" style="height: 100%"></td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.css b/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.css
new file mode 100644
index 000000000..ba464ba2c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.css
@@ -0,0 +1,88 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * CSS styles used by all pages that compose the File Browser.
+ */
+
+body
+{
+ background-color: #f1f1e3;
+}
+
+form
+{
+ margin: 0px 0px 0px 0px ;
+ padding: 0px 0px 0px 0px ;
+}
+
+.Frame
+{
+ background-color: #f1f1e3;
+ border-color: #f1f1e3;
+ border-right: thin inset;
+ border-top: thin inset;
+ border-left: thin inset;
+ border-bottom: thin inset;
+}
+
+body.FileArea
+{
+
+ background-color: #ffffff;
+}
+
+body, td, input, select
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana;
+}
+
+.ActualFolder
+{
+ font-weight: bold;
+ font-size: 14px;
+}
+
+.PopupButtons
+{
+ border-top: #d5d59d 1px solid;
+ background-color: #e3e3c7;
+ padding: 7px 10px 7px 10px;
+}
+
+.Button, button
+{
+ border-right: #737357 1px solid;
+ border-top: #737357 1px solid;
+ border-left: #737357 1px solid;
+ color: #3b3b1f;
+ border-bottom: #737357 1px solid;
+ background-color: #c7c78f;
+}
+
+.FolderListCurrentFolder img
+{
+ background-image: url(images/FolderOpened.gif);
+}
+
+.FolderListFolder img
+{
+ background-image: url(images/Folder.gif);
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.html
new file mode 100644
index 000000000..8b776a281
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/browser.html
@@ -0,0 +1,154 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page compose the File Browser dialog frameset.
+-->
+<html>
+ <head>
+ <title>FCKeditor - Resources Browser</title>
+ <link href="browser.css" type="text/css" rel="stylesheet">
+ <script type="text/javascript" src="js/fckxml.js"></script>
+ <script language="javascript">
+
+function GetUrlParam( paramName )
+{
+ var oRegex = new RegExp( '[\?&]' + paramName + '=([^&]+)', 'i' ) ;
+ var oMatch = oRegex.exec( window.top.location.search ) ;
+
+ if ( oMatch && oMatch.length > 1 )
+ return decodeURIComponent( oMatch[1] ) ;
+ else
+ return '' ;
+}
+
+var oConnector = new Object() ;
+oConnector.CurrentFolder = '/' ;
+
+var sConnUrl = GetUrlParam( 'Connector' ) ;
+
+// Gecko has some problems when using relative URLs (not starting with slash).
+if ( sConnUrl.substr(0,1) != '/' && sConnUrl.indexOf( '://' ) < 0 )
+ sConnUrl = window.location.href.replace( /browser.html.*$/, '' ) + sConnUrl ;
+
+oConnector.ConnectorUrl = sConnUrl + ( sConnUrl.indexOf('?') != -1 ? '&' : '?' ) ;
+
+var sServerPath = GetUrlParam( 'ServerPath' ) ;
+if ( sServerPath.length > 0 )
+ oConnector.ConnectorUrl += 'ServerPath=' + encodeURIComponent( sServerPath ) + '&' ;
+
+oConnector.ResourceType = GetUrlParam( 'Type' ) ;
+oConnector.ShowAllTypes = ( oConnector.ResourceType.length == 0 ) ;
+
+if ( oConnector.ShowAllTypes )
+ oConnector.ResourceType = 'File' ;
+
+oConnector.SendCommand = function( command, params, callBackFunction )
+{
+ var sUrl = this.ConnectorUrl + 'Command=' + command ;
+ sUrl += '&Type=' + this.ResourceType ;
+ sUrl += '&CurrentFolder=' + encodeURIComponent( this.CurrentFolder ) ;
+
+ if ( params ) sUrl += '&' + params ;
+
+ var oXML = new FCKXml() ;
+
+ if ( callBackFunction )
+ oXML.LoadUrl( sUrl, callBackFunction ) ; // Asynchronous load.
+ else
+ return oXML.LoadUrl( sUrl ) ;
+
+ return null ;
+}
+
+oConnector.CheckError = function( responseXml )
+{
+ var iErrorNumber = 0 ;
+ var oErrorNode = responseXml.SelectSingleNode( 'Connector/Error' ) ;
+
+ if ( oErrorNode )
+ {
+ iErrorNumber = parseInt( oErrorNode.attributes.getNamedItem('number').value, 10 ) ;
+
+ switch ( iErrorNumber )
+ {
+ case 0 :
+ break ;
+ case 1 : // Custom error. Message placed in the "text" attribute.
+ alert( oErrorNode.attributes.getNamedItem('text').value ) ;
+ break ;
+ case 101 :
+ alert( 'Folder already exists' ) ;
+ break ;
+ case 102 :
+ alert( 'Invalid folder name' ) ;
+ break ;
+ case 103 :
+ alert( 'You have no permissions to create the folder' ) ;
+ break ;
+ case 110 :
+ alert( 'Unknown error creating folder' ) ;
+ break ;
+ default :
+ alert( 'Error on your request. Error number: ' + iErrorNumber ) ;
+ break ;
+ }
+ }
+ return iErrorNumber ;
+}
+
+var oIcons = new Object() ;
+
+oIcons.AvailableIconsArray = [
+ 'ai','avi','bmp','cs','dll','doc','exe','fla','gif','htm','html','jpg','js',
+ 'mdb','mp3','pdf','png','ppt','rdp','swf','swt','txt','vsd','xls','xml','zip' ] ;
+
+oIcons.AvailableIcons = new Object() ;
+
+for ( var i = 0 ; i < oIcons.AvailableIconsArray.length ; i++ )
+ oIcons.AvailableIcons[ oIcons.AvailableIconsArray[i] ] = true ;
+
+oIcons.GetIcon = function( fileName )
+{
+ var sExtension = fileName.substr( fileName.lastIndexOf('.') + 1 ).toLowerCase() ;
+
+ if ( this.AvailableIcons[ sExtension ] == true )
+ return sExtension ;
+ else
+ return 'default.icon' ;
+}
+ </script>
+ </head>
+ <frameset cols="150,*" class="Frame" framespacing="3" bordercolor="#f1f1e3" frameborder="1">
+ <frameset rows="50,*" framespacing="0">
+ <frame src="frmresourcetype.html" scrolling="no" frameborder="0">
+ <frame name="frmFolders" src="frmfolders.html" scrolling="auto" frameborder="1">
+ </frameset>
+ <frameset rows="50,*,50" framespacing="0">
+ <frame name="frmActualFolder" src="frmactualfolder.html" scrolling="no" frameborder="0">
+ <frame name="frmResourcesList" src="frmresourceslist.html" scrolling="auto" frameborder="1">
+ <frameset cols="150,*,0" framespacing="0" frameborder="0">
+ <frame name="frmCreateFolder" src="frmcreatefolder.html" scrolling="no" frameborder="0">
+ <frame name="frmUpload" src="frmupload.html" scrolling="no" frameborder="0">
+ <frame name="frmUploadWorker" src="javascript:void(0)" scrolling="no" frameborder="0">
+ </frameset>
+ </frameset>
+ </frameset>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl
new file mode 100644
index 000000000..f64b7c799
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl
@@ -0,0 +1,63 @@
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+sub CreateXmlHeader
+{
+ local($command,$resourceType,$currentFolder) = @_;
+
+ # Create the XML document header.
+ print '<?xml version="1.0" encoding="utf-8" ?>';
+
+ # Create the main "Connector" node.
+ print '<Connector command="' . $command . '" resourceType="' . $resourceType . '">';
+
+ # Add the current folder node.
+ print '<CurrentFolder path="' . ConvertToXmlAttribute($currentFolder) . '" url="' . ConvertToXmlAttribute(GetUrlFromPath($resourceType,$currentFolder)) . '" />';
+}
+
+sub CreateXmlFooter
+{
+ print '</Connector>';
+}
+
+sub SendError
+{
+ local( $number, $text ) = @_;
+
+ print << "_HTML_HEAD_";
+Content-Type:text/xml; charset=utf-8
+Pragma: no-cache
+Cache-Control: no-cache
+Expires: Thu, 01 Dec 1994 16:00:00 GMT
+
+_HTML_HEAD_
+
+ # Create the XML document header
+ print '<?xml version="1.0" encoding="utf-8" ?>' ;
+
+ print '<Connector><Error number="' . $number . '" text="' . &specialchar_cnv( $text ) . '" /></Connector>' ;
+
+ exit ;
+}
+
+1;
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl
new file mode 100644
index 000000000..2ed2e6292
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl
@@ -0,0 +1,158 @@
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+sub GetFolders
+{
+
+ local($resourceType, $currentFolder) = @_;
+
+ # Map the virtual path to the local server path.
+ $sServerDir = &ServerMapFolder($resourceType, $currentFolder);
+ print "<Folders>"; # Open the "Folders" node.
+
+ opendir(DIR,"$sServerDir");
+ @files = grep(!/^\.\.?$/,readdir(DIR));
+ closedir(DIR);
+
+ foreach $sFile (@files) {
+ if($sFile != '.' && $sFile != '..' && (-d "$sServerDir$sFile")) {
+ $cnv_filename = &ConvertToXmlAttribute($sFile);
+ print '<Folder name="' . $cnv_filename . '" />';
+ }
+ }
+ print "</Folders>"; # Close the "Folders" node.
+}
+
+sub GetFoldersAndFiles
+{
+
+ local($resourceType, $currentFolder) = @_;
+ # Map the virtual path to the local server path.
+ $sServerDir = &ServerMapFolder($resourceType,$currentFolder);
+
+ # Initialize the output buffers for "Folders" and "Files".
+ $sFolders = '<Folders>';
+ $sFiles = '<Files>';
+
+ opendir(DIR,"$sServerDir");
+ @files = grep(!/^\.\.?$/,readdir(DIR));
+ closedir(DIR);
+
+ foreach $sFile (@files) {
+ if($sFile ne '.' && $sFile ne '..') {
+ if(-d "$sServerDir$sFile") {
+ $cnv_filename = &ConvertToXmlAttribute($sFile);
+ $sFolders .= '<Folder name="' . $cnv_filename . '" />' ;
+ } else {
+ ($iFileSize,$refdate,$filedate,$fileperm) = (stat("$sServerDir$sFile"))[7,8,9,2];
+ if($iFileSize > 0) {
+ $iFileSize = int($iFileSize / 1024);
+ if($iFileSize < 1) {
+ $iFileSize = 1;
+ }
+ }
+ $cnv_filename = &ConvertToXmlAttribute($sFile);
+ $sFiles .= '<File name="' . $cnv_filename . '" size="' . $iFileSize . '" />' ;
+ }
+ }
+ }
+ print $sFolders ;
+ print '</Folders>'; # Close the "Folders" node.
+ print $sFiles ;
+ print '</Files>'; # Close the "Files" node.
+}
+
+sub CreateFolder
+{
+
+ local($resourceType, $currentFolder) = @_;
+ $sErrorNumber = '0' ;
+ $sErrorMsg = '' ;
+
+ if($FORM{'NewFolderName'} ne "") {
+ $sNewFolderName = $FORM{'NewFolderName'};
+ # Map the virtual path to the local server path of the current folder.
+ $sServerDir = &ServerMapFolder($resourceType, $currentFolder);
+ if(-w $sServerDir) {
+ $sServerDir .= $sNewFolderName;
+ $sErrorMsg = &CreateServerFolder($sServerDir);
+ if($sErrorMsg == 0) {
+ $sErrorNumber = '0';
+ } elsif($sErrorMsg eq 'Invalid argument' || $sErrorMsg eq 'No such file or directory') {
+ $sErrorNumber = '102'; #// Path too long.
+ } else {
+ $sErrorNumber = '110';
+ }
+ } else {
+ $sErrorNumber = '103';
+ }
+ } else {
+ $sErrorNumber = '102' ;
+ }
+ # Create the "Error" node.
+ $cnv_errmsg = &ConvertToXmlAttribute($sErrorMsg);
+ print '<Error number="' . $sErrorNumber . '" originalDescription="' . $cnv_errmsg . '" />';
+}
+
+sub FileUpload
+{
+eval("use File::Copy;");
+
+ local($resourceType, $currentFolder) = @_;
+
+ $sErrorNumber = '0' ;
+ $sFileName = '' ;
+ if($new_fname) {
+ # Map the virtual path to the local server path.
+ $sServerDir = &ServerMapFolder($resourceType,$currentFolder);
+
+ # Get the uploaded file name.
+ $sFileName = $new_fname;
+ $sOriginalFileName = $sFileName;
+
+ $iCounter = 0;
+ while(1) {
+ $sFilePath = $sServerDir . $sFileName;
+ if(-e $sFilePath) {
+ $iCounter++ ;
+ ($path,$BaseName,$ext) = &RemoveExtension($sOriginalFileName);
+ $sFileName = $BaseName . '(' . $iCounter . ').' . $ext;
+ $sErrorNumber = '201';
+ } else {
+ copy("$img_dir/$new_fname","$sFilePath");
+ chmod(0777,$sFilePath);
+ unlink("$img_dir/$new_fname");
+ last;
+ }
+ }
+ } else {
+ $sErrorNumber = '202' ;
+ }
+ $sFileName =~ s/"/\\"/g;
+ print "Content-type: text/html\n\n";
+ print '<script type="text/javascript">';
+ print 'window.parent.frames["frmUpload"].OnUploadCompleted(' . $sErrorNumber . ',"' . $sFileName . '") ;';
+ print '</script>';
+ exit ;
+}
+1;
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi
new file mode 100644
index 000000000..a74121572
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi
@@ -0,0 +1,137 @@
+#!/usr/bin/env perl
+
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+##
+# ATTENTION: To enable this connector, look for the "SECURITY" comment in this file.
+##
+
+## START: Hack for Windows (Not important to understand the editor code... Perl specific).
+if(Windows_check()) {
+ chdir(GetScriptPath($0));
+}
+
+sub Windows_check
+{
+ # IIS,PWS(NT/95)
+ $www_server_os = $^O;
+ # Win98 & NT(SP4)
+ if($www_server_os eq "") { $www_server_os= $ENV{'OS'}; }
+ # AnHTTPd/Omni/IIS
+ if($ENV{'SERVER_SOFTWARE'} =~ /AnWeb|Omni|IIS\//i) { $www_server_os= 'win'; }
+ # Win Apache
+ if($ENV{'WINDIR'} ne "") { $www_server_os= 'win'; }
+ if($www_server_os=~ /win/i) { return(1); }
+ return(0);
+}
+
+sub GetScriptPath {
+ local($path) = @_;
+ if($path =~ /[\:\/\\]/) { $path =~ s/(.*?)[\/\\][^\/\\]+$/$1/; } else { $path = '.'; }
+ $path;
+}
+## END: Hack for IIS
+
+require 'util.pl';
+require 'io.pl';
+require 'basexml.pl';
+require 'commands.pl';
+require 'upload_fck.pl';
+
+##
+# SECURITY: REMOVE/COMMENT THE FOLLOWING LINE TO ENABLE THIS CONNECTOR.
+##
+&SendError( 1, 'This connector is disabled. Please check the "editor/filemanager/browser/default/connectors/perl/connector.cgi" file' ) ;
+
+ &read_input();
+
+ if($FORM{'ServerPath'} ne "") {
+ $GLOBALS{'UserFilesPath'} = $FORM{'ServerPath'};
+ if(!($GLOBALS{'UserFilesPath'} =~ /\/$/)) {
+ $GLOBALS{'UserFilesPath'} .= '/' ;
+ }
+ } else {
+ $GLOBALS{'UserFilesPath'} = '/userfiles/';
+ }
+
+ # Map the "UserFiles" path to a local directory.
+ $rootpath = &GetRootPath();
+ $GLOBALS{'UserFilesDirectory'} = $rootpath . $GLOBALS{'UserFilesPath'};
+
+ &DoResponse();
+
+sub DoResponse
+{
+
+ if($FORM{'Command'} eq "" || $FORM{'Type'} eq "" || $FORM{'CurrentFolder'} eq "") {
+ return ;
+ }
+ # Get the main request informaiton.
+ $sCommand = $FORM{'Command'};
+ $sResourceType = $FORM{'Type'};
+ $sCurrentFolder = $FORM{'CurrentFolder'};
+
+ # Check the current folder syntax (must begin and start with a slash).
+ if(!($sCurrentFolder =~ /\/$/)) {
+ $sCurrentFolder .= '/';
+ }
+ if(!($sCurrentFolder =~ /^\//)) {
+ $sCurrentFolder = '/' . $sCurrentFolder;
+ }
+
+ # Check for invalid folder paths (..)
+ if ( $sCurrentFolder =~ /\.\./ ) {
+ SendError( 102, "" ) ;
+ }
+
+ # File Upload doesn't have to Return XML, so it must be intercepted before anything.
+ if($sCommand eq 'FileUpload') {
+ FileUpload($sResourceType,$sCurrentFolder);
+ return ;
+ }
+
+ print << "_HTML_HEAD_";
+Content-Type:text/xml; charset=utf-8
+Pragma: no-cache
+Cache-Control: no-cache
+Expires: Thu, 01 Dec 1994 16:00:00 GMT
+
+_HTML_HEAD_
+
+ &CreateXmlHeader($sCommand,$sResourceType,$sCurrentFolder);
+
+ # Execute the required command.
+ if($sCommand eq 'GetFolders') {
+ &GetFolders($sResourceType,$sCurrentFolder);
+ } elsif($sCommand eq 'GetFoldersAndFiles') {
+ &GetFoldersAndFiles($sResourceType,$sCurrentFolder);
+ } elsif($sCommand eq 'CreateFolder') {
+ &CreateFolder($sResourceType,$sCurrentFolder);
+ }
+
+ &CreateXmlFooter();
+
+ exit ;
+}
+
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl
new file mode 100644
index 000000000..c1dbccf93
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl
@@ -0,0 +1,131 @@
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+sub GetUrlFromPath
+{
+ local($resourceType, $folderPath) = @_;
+
+ if($resourceType eq '') {
+ $rmpath = &RemoveFromEnd($GLOBALS{'UserFilesPath'},'/');
+ return("$rmpath$folderPath");
+ } else {
+ return("$GLOBALS{'UserFilesPath'}$resourceType$folderPath");
+ }
+}
+
+sub RemoveExtension
+{
+ local($fileName) = @_;
+ local($path, $base, $ext);
+ if($fileName !~ /\./) {
+ $fileName .= '.';
+ }
+ if($fileName =~ /([^\\\/]*)\.(.*)$/) {
+ $base = $1;
+ $ext = $2;
+ if($fileName =~ /(.*)$base\.$ext$/) {
+ $path = $1;
+ }
+ }
+ return($path,$base,$ext);
+
+}
+
+sub ServerMapFolder
+{
+ local($resourceType,$folderPath) = @_;
+
+ # Get the resource type directory.
+ $sResourceTypePath = $GLOBALS{'UserFilesDirectory'} . $resourceType . '/';
+
+ # Ensure that the directory exists.
+ &CreateServerFolder($sResourceTypePath);
+
+ # Return the resource type directory combined with the required path.
+ $rmpath = &RemoveFromStart($folderPath,'/');
+ return("$sResourceTypePath$rmpath");
+}
+
+sub GetParentFolder
+{
+ local($folderPath) = @_;
+
+ $folderPath =~ s/[\/][^\/]+[\/]?$//g;
+ return $folderPath;
+}
+
+sub CreateServerFolder
+{
+ local($folderPath) = @_;
+
+ $sParent = &GetParentFolder($folderPath);
+ # Check if the parent exists, or create it.
+ if(!(-e $sParent)) {
+ $sErrorMsg = &CreateServerFolder($sParent);
+ if($sErrorMsg == 1) {
+ return(1);
+ }
+ }
+ if(!(-e $folderPath)) {
+ umask(000);
+ mkdir("$folderPath",0777);
+ chmod(0777,"$folderPath");
+ return(0);
+ } else {
+ return(1);
+ }
+}
+
+sub GetRootPath
+{
+#use Cwd;
+
+# my $dir = getcwd;
+# print $dir;
+# $dir =~ s/$ENV{'DOCUMENT_ROOT'}//g;
+# print $dir;
+# return($dir);
+
+# $wk = $0;
+# $wk =~ s/\/connector\.cgi//g;
+# if($wk) {
+# $current_dir = $wk;
+# } else {
+# $current_dir = `pwd`;
+# }
+# return($current_dir);
+use Cwd;
+
+ if($ENV{'DOCUMENT_ROOT'}) {
+ $dir = $ENV{'DOCUMENT_ROOT'};
+ } else {
+ my $dir = getcwd;
+ $workdir =~ s/\/connector\.cgi//g;
+ $dir =~ s/$workdir//g;
+ }
+ return($dir);
+
+
+
+}
+1;
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl
new file mode 100644
index 000000000..1c3f4e29c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl
@@ -0,0 +1,667 @@
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+# image data save dir
+$img_dir = './temp/';
+
+
+# File size max(unit KB)
+$MAX_CONTENT_SIZE = 30000;
+
+# Filelock (1=use,0=not use)
+$PM{'flock'} = '1';
+
+
+# upload Content-Type list
+my %UPLOAD_CONTENT_TYPE_LIST = (
+ 'image/(x-)?png' => 'png', # PNG image
+ 'image/p?jpe?g' => 'jpg', # JPEG image
+ 'image/gif' => 'gif', # GIF image
+ 'image/x-xbitmap' => 'xbm', # XBM image
+
+ 'image/(x-(MS-)?)?bmp' => 'bmp', # Windows BMP image
+ 'image/pict' => 'pict', # Macintosh PICT image
+ 'image/tiff' => 'tif', # TIFF image
+ 'application/pdf' => 'pdf', # PDF image
+ 'application/x-shockwave-flash' => 'swf', # Shockwave Flash
+
+ 'video/(x-)?msvideo' => 'avi', # Microsoft Video
+ 'video/quicktime' => 'mov', # QuickTime Video
+ 'video/mpeg' => 'mpeg', # MPEG Video
+ 'video/x-mpeg2' => 'mpv2', # MPEG2 Video
+
+ 'audio/(x-)?midi?' => 'mid', # MIDI Audio
+ 'audio/(x-)?wav' => 'wav', # WAV Audio
+ 'audio/basic' => 'au', # ULAW Audio
+ 'audio/mpeg' => 'mpga', # MPEG Audio
+
+ 'application/(x-)?zip(-compressed)?' => 'zip', # ZIP Compress
+
+ 'text/html' => 'html', # HTML
+ 'text/plain' => 'txt', # TEXT
+ '(?:application|text)/(?:rtf|richtext)' => 'rtf', # RichText
+
+ 'application/msword' => 'doc', # Microsoft Word
+ 'application/vnd.ms-excel' => 'xls', # Microsoft Excel
+
+ ''
+);
+
+# Upload is permitted.
+# A regular expression is possible.
+my %UPLOAD_EXT_LIST = (
+ 'png' => 'PNG image',
+ 'p?jpe?g|jpe|jfif|pjp' => 'JPEG image',
+ 'gif' => 'GIF image',
+ 'xbm' => 'XBM image',
+
+ 'bmp|dib|rle' => 'Windows BMP image',
+ 'pi?ct' => 'Macintosh PICT image',
+ 'tiff?' => 'TIFF image',
+ 'pdf' => 'PDF image',
+ 'swf' => 'Shockwave Flash',
+
+ 'avi' => 'Microsoft Video',
+ 'moo?v|qt' => 'QuickTime Video',
+ 'm(p(e?gv?|e|v)|1v)' => 'MPEG Video',
+ 'mp(v2|2v)' => 'MPEG2 Video',
+
+ 'midi?|kar|smf|rmi|mff' => 'MIDI Audio',
+ 'wav' => 'WAVE Audio',
+ 'au|snd' => 'ULAW Audio',
+ 'mp(e?ga|2|a|3)|abs' => 'MPEG Audio',
+
+ 'zip' => 'ZIP Compress',
+ 'lzh' => 'LZH Compress',
+ 'cab' => 'CAB Compress',
+
+ 'd?html?' => 'HTML',
+ 'rtf|rtx' => 'RichText',
+ 'txt|text' => 'Text',
+
+ ''
+);
+
+
+# sjis or euc
+my $CHARCODE = 'sjis';
+
+$TRANS_2BYTE_CODE = 0;
+
+##############################################################################
+# Summary
+#
+# Form Read input
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+sub read_input
+{
+eval("use File::Copy;");
+eval("use File::Path;");
+
+ my ($FORM) = @_;
+
+
+ mkdir($img_dir,0777);
+ chmod(0777,$img_dir);
+
+ undef $img_data_exists;
+ undef @NEWFNAMES;
+ undef @NEWFNAME_DATA;
+
+ if($ENV{'CONTENT_LENGTH'} > 10000000 || $ENV{'CONTENT_LENGTH'} > $MAX_CONTENT_SIZE * 1024) {
+ &upload_error(
+ 'Size Error',
+ sprintf(
+ "Transmitting size is too large.MAX <strong>%d KB</strong> Now Size <strong>%d KB</strong>(<strong>%d bytes</strong> Over)",
+ $MAX_CONTENT_SIZE,
+ int($ENV{'CONTENT_LENGTH'} / 1024),
+ $ENV{'CONTENT_LENGTH'} - $MAX_CONTENT_SIZE * 1024
+ )
+ );
+ }
+
+ my $Buffer;
+ if($ENV{'CONTENT_TYPE'} =~ /multipart\/form-data/) {
+ # METHOD POST only
+ return unless($ENV{'CONTENT_LENGTH'});
+
+ binmode(STDIN);
+ # STDIN A pause character is detected.'(MacIE3.0 boundary of $ENV{'CONTENT_TYPE'} cannot be trusted.)
+ my $Boundary = <STDIN>;
+ $Boundary =~ s/\x0D\x0A//;
+ $Boundary = quotemeta($Boundary);
+ while(<STDIN>) {
+ if(/^\s*Content-Disposition:/i) {
+ my($name,$ContentType,$FileName);
+ # form data get
+ if(/\bname="([^"]+)"/i || /\bname=([^\s:;]+)/i) {
+ $name = $1;
+ $name =~ tr/+/ /;
+ $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ &Encode(\$name);
+ }
+ if(/\bfilename="([^"]*)"/i || /\bfilename=([^\s:;]*)/i) {
+ $FileName = $1 || 'unknown';
+ }
+ # head read
+ while(<STDIN>) {
+ last if(! /\w/);
+ if(/^\s*Content-Type:\s*"([^"]+)"/i || /^\s*Content-Type:\s*([^\s:;]+)/i) {
+ $ContentType = $1;
+ }
+ }
+ # body read
+ $value = "";
+ while(<STDIN>) {
+ last if(/^$Boundary/o);
+ $value .= $_;
+ };
+ $lastline = $_;
+ $value =~s /\x0D\x0A$//;
+ if($value ne '') {
+ if($FileName || $ContentType) {
+ $img_data_exists = 1;
+ (
+ $FileName, #
+ $Ext, #
+ $Length, #
+ $ImageWidth, #
+ $ImageHeight, #
+ $ContentName #
+ ) = &CheckContentType(\$value,$FileName,$ContentType);
+
+ $FORM{$name} = $FileName;
+ $new_fname = $FileName;
+ push(@NEWFNAME_DATA,"$FileName\t$Ext\t$Length\t$ImageWidth\t$ImageHeight\t$ContentName");
+
+ # Multi-upload correspondence
+ push(@NEWFNAMES,$new_fname);
+ open(OUT,">$img_dir/$new_fname");
+ binmode(OUT);
+ eval "flock(OUT,2);" if($PM{'flock'} == 1);
+ print OUT $value;
+ eval "flock(OUT,8);" if($PM{'flock'} == 1);
+ close(OUT);
+
+ } elsif($name) {
+ $value =~ tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ &Encode(\$value,'trans');
+ $FORM{$name} .= "\0" if(defined($FORM{$name}));
+ $FORM{$name} .= $value;
+ }
+ }
+ };
+ last if($lastline =~ /^$Boundary\-\-/o);
+ }
+ } elsif($ENV{'CONTENT_LENGTH'}) {
+ read(STDIN,$Buffer,$ENV{'CONTENT_LENGTH'});
+ }
+ foreach(split(/&/,$Buffer),split(/&/,$ENV{'QUERY_STRING'})) {
+ my($name, $value) = split(/=/);
+ $name =~ tr/+/ /;
+ $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ $value =~ tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+
+ &Encode(\$name);
+ &Encode(\$value,'trans');
+ $FORM{$name} .= "\0" if(defined($FORM{$name}));
+ $FORM{$name} .= $value;
+
+ }
+
+}
+
+##############################################################################
+# Summary
+#
+# CheckContentType
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+sub CheckContentType
+{
+
+ my($DATA,$FileName,$ContentType) = @_;
+ my($Ext,$ImageWidth,$ImageHeight,$ContentName,$Infomation);
+ my $DataLength = length($$DATA);
+
+ # An unknown file type
+
+ $_ = $ContentType;
+ my $UnknownType = (
+ !$_
+ || /^application\/(x-)?macbinary$/i
+ || /^application\/applefile$/i
+ || /^application\/octet-stream$/i
+ || /^text\/plane$/i
+ || /^x-unknown-content-type/i
+ );
+
+ # MacBinary(Mac Unnecessary data are deleted.)
+ if($UnknownType || $ENV{'HTTP_USER_AGENT'} =~ /Macintosh|Mac_/) {
+ if($DataLength > 128 && !unpack("C",substr($$DATA,0,1)) && !unpack("C",substr($$DATA,74,1)) && !unpack("C",substr($$DATA,82,1)) ) {
+ my $MacBinary_ForkLength = unpack("N", substr($$DATA, 83, 4)); # ForkLength Get
+ my $MacBinary_FileName = quotemeta(substr($$DATA, 2, unpack("C",substr($$DATA, 1, 1))));
+ if($MacBinary_FileName && $MacBinary_ForkLength && $DataLength >= $MacBinary_ForkLength + 128
+ && ($FileName =~ /$MacBinary_FileName/i || substr($$DATA,102,4) eq 'mBIN')) { # DATA TOP 128byte MacBinary!!
+ $$DATA = substr($$DATA,128,$MacBinary_ForkLength);
+ my $ResourceLength = $DataLength - $MacBinary_ForkLength - 128;
+ $DataLength = $MacBinary_ForkLength;
+ }
+ }
+ }
+
+ # A file name is changed into EUC.
+# &jcode::convert(\$FileName,'euc',$FormCodeDefault);
+# &jcode::h2z_euc(\$FileName);
+ $FileName =~ s/^.*\\//; # Windows, Mac
+ $FileName =~ s/^.*\///; # UNIX
+ $FileName =~ s/&/&amp;/g;
+ $FileName =~ s/"/&quot;/g;
+ $FileName =~ s/</&lt;/g;
+ $FileName =~ s/>/&gt;/g;
+#
+# if($CHARCODE ne 'euc') {
+# &jcode::convert(\$FileName,$CHARCODE,'euc');
+# }
+
+ # An extension is extracted and it changes into a small letter.
+ my $FileExt;
+ if($FileName =~ /\.(\w+)$/) {
+ $FileExt = $1;
+ $FileExt =~ tr/A-Z/a-z/;
+ }
+
+ # Executable file detection (ban on upload)
+ if($$DATA =~ /^MZ/) {
+ $Ext = 'exe';
+ }
+ # text
+ if(!$Ext && ($UnknownType || $ContentType =~ /^text\//i || $ContentType =~ /^application\/(?:rtf|richtext)$/i || $ContentType =~ /^image\/x-xbitmap$/i)
+ && ! $$DATA =~ /[\000-\006\177\377]/) {
+# $$DATA =~ s/\x0D\x0A/\n/g;
+# $$DATA =~ tr/\x0D\x0A/\n\n/;
+#
+# if(
+# $$DATA =~ /<\s*SCRIPT(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*(?:.|\n)*?\bONLOAD\s*=(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*(?:.|\n)*?\bONCLICK\s*=(?:.|\n)*?>/i
+# ) {
+# $Infomation = '(JavaScript contains)';
+# }
+# if($$DATA =~ /<\s*TABLE(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*BLINK(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*MARQUEE(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*OBJECT(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*EMBED(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*FRAME(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*APPLET(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*FORM(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*(?:.|\n)*?\bSRC\s*=(?:.|\n)*?>/i
+# || $$DATA =~ /<\s*(?:.|\n)*?\bDYNSRC\s*=(?:.|\n)*?>/i
+# ) {
+# $Infomation = '(the HTML tag which is not safe is included)';
+# }
+
+ if($FileExt =~ /^txt$/i || $FileExt =~ /^cgi$/i || $FileExt =~ /^pl$/i) { # Text File
+ $Ext = 'txt';
+ } elsif($ContentType =~ /^text\/html$/i || $FileExt =~ /html?/i || $$DATA =~ /<\s*HTML(?:.|\n)*?>/i) { # HTML File
+ $Ext = 'html';
+ } elsif($ContentType =~ /^image\/x-xbitmap$/i || $FileExt =~ /^xbm$/i) { # XBM(x-BitMap) Image
+ my $XbmName = $1;
+ my ($XbmWidth, $XbmHeight);
+ if($$DATA =~ /\#define\s*$XbmName\_width\s*(\d+)/i) {
+ $XbmWidth = $1;
+ }
+ if($$DATA =~ /\#define\s*$XbmName\_height\s*(\d+)/i) {
+ $XbmHeight = $1;
+ }
+ if($XbmWidth && $XbmHeight) {
+ $Ext = 'xbm';
+ $ImageWidth = $XbmWidth;
+ $ImageHeight = $XbmHeight;
+ }
+ } else { #
+ $Ext = 'txt';
+ }
+ }
+
+ # image
+ if(!$Ext && ($UnknownType || $ContentType =~ /^image\//i)) {
+ # PNG
+ if($$DATA =~ /^\x89PNG\x0D\x0A\x1A\x0A/) {
+ if(substr($$DATA, 12, 4) eq 'IHDR') {
+ $Ext = 'png';
+ ($ImageWidth, $ImageHeight) = unpack("N2", substr($$DATA, 16, 8));
+ }
+ } elsif($$DATA =~ /^GIF8(?:9|7)a/) { # GIF89a(modified), GIF89a, GIF87a
+ $Ext = 'gif';
+ ($ImageWidth, $ImageHeight) = unpack("v2", substr($$DATA, 6, 4));
+ } elsif($$DATA =~ /^II\x2a\x00\x08\x00\x00\x00/ || $$DATA =~ /^MM\x00\x2a\x00\x00\x00\x08/) { # TIFF
+ $Ext = 'tif';
+ } elsif($$DATA =~ /^BM/) { # BMP
+ $Ext = 'bmp';
+ } elsif($$DATA =~ /^\xFF\xD8\xFF/ || $$DATA =~ /JFIF/) { # JPEG
+ my $HeaderPoint = index($$DATA, "\xFF\xD8\xFF", 0);
+ my $Point = $HeaderPoint + 2;
+ while($Point < $DataLength) {
+ my($Maker, $MakerType, $MakerLength) = unpack("C2n",substr($$DATA,$Point,4));
+ if($Maker != 0xFF || $MakerType == 0xd9 || $MakerType == 0xda) {
+ last;
+ } elsif($MakerType >= 0xC0 && $MakerType <= 0xC3) {
+ $Ext = 'jpg';
+ ($ImageHeight, $ImageWidth) = unpack("n2", substr($$DATA, $Point + 5, 4));
+ if($HeaderPoint > 0) {
+ $$DATA = substr($$DATA, $HeaderPoint);
+ $DataLength = length($$DATA);
+ }
+ last;
+ } else {
+ $Point += $MakerLength + 2;
+ }
+ }
+ }
+ }
+
+ # audio
+ if(!$Ext && ($UnknownType || $ContentType =~ /^audio\//i)) {
+ # MIDI Audio
+ if($$DATA =~ /^MThd/) {
+ $Ext = 'mid';
+ } elsif($$DATA =~ /^\x2esnd/) { # ULAW Audio
+ $Ext = 'au';
+ } elsif($$DATA =~ /^RIFF/ || $$DATA =~ /^ID3/ && $$DATA =~ /RIFF/) {
+ my $HeaderPoint = index($$DATA, "RIFF", 0);
+ $_ = substr($$DATA, $HeaderPoint + 8, 8);
+ if(/^WAVEfmt $/) {
+ # WAVE
+ if(unpack("V",substr($$DATA, $HeaderPoint + 16, 4)) == 16) {
+ $Ext = 'wav';
+ } else { # RIFF WAVE MP3
+ $Ext = 'mp3';
+ }
+ } elsif(/^RMIDdata$/) { # RIFF MIDI
+ $Ext = 'rmi';
+ } elsif(/^RMP3data$/) { # RIFF MP3
+ $Ext = 'rmp';
+ }
+ if($ContentType =~ /^audio\//i) {
+ $Infomation .= '(RIFF '. substr($$DATA, $HeaderPoint + 8, 4). ')';
+ }
+ }
+ }
+
+ # a binary file
+ unless ($Ext) {
+ # PDF image
+ if($$DATA =~ /^\%PDF/) {
+ # Picture size is not measured.
+ $Ext = 'pdf';
+ } elsif($$DATA =~ /^FWS/) { # Shockwave Flash
+ $Ext = 'swf';
+ } elsif($$DATA =~ /^RIFF/ || $$DATA =~ /^ID3/ && $$DATA =~ /RIFF/) {
+ my $HeaderPoint = index($$DATA, "RIFF", 0);
+ $_ = substr($$DATA,$HeaderPoint + 8, 8);
+ # AVI
+ if(/^AVI LIST$/) {
+ $Ext = 'avi';
+ }
+ if($ContentType =~ /^video\//i) {
+ $Infomation .= '(RIFF '. substr($$DATA, $HeaderPoint + 8, 4). ')';
+ }
+ } elsif($$DATA =~ /^PK/) { # ZIP Compress File
+ $Ext = 'zip';
+ } elsif($$DATA =~ /^MSCF/) { # CAB Compress File
+ $Ext = 'cab';
+ } elsif($$DATA =~ /^Rar\!/) { # RAR Compress File
+ $Ext = 'rar';
+ } elsif(substr($$DATA, 2, 5) =~ /^\-lh(\d+|d)\-$/) { # LHA Compress File
+ $Infomation .= "(lh$1)";
+ $Ext = 'lzh';
+ } elsif(substr($$DATA, 325, 25) eq "Apple Video Media Handler" || substr($$DATA, 325, 30) eq "Apple \x83\x72\x83\x66\x83\x49\x81\x45\x83\x81\x83\x66\x83\x42\x83\x41\x83\x6E\x83\x93\x83\x68\x83\x89") {
+ # QuickTime
+ $Ext = 'mov';
+ }
+ }
+
+ # Header analysis failure
+ unless ($Ext) {
+ # It will be followed if it applies for the MIME type from the browser.
+ foreach (keys %UPLOAD_CONTENT_TYPE_LIST) {
+ next unless ($_);
+ if($ContentType =~ /^$_$/i) {
+ $Ext = $UPLOAD_CONTENT_TYPE_LIST{$_};
+ $ContentName = &CheckContentExt($Ext);
+ if(
+ grep {$_ eq $Ext;} (
+ 'png',
+ 'gif',
+ 'jpg',
+ 'xbm',
+ 'tif',
+ 'bmp',
+ 'pdf',
+ 'swf',
+ 'mov',
+ 'zip',
+ 'cab',
+ 'lzh',
+ 'rar',
+ 'mid',
+ 'rmi',
+ 'au',
+ 'wav',
+ 'avi',
+ 'exe'
+ )
+ ) {
+ $Infomation .= ' / Header analysis failure';
+ }
+ if($Ext ne $FileExt && &CheckContentExt($FileExt) eq $ContentName) {
+ $Ext = $FileExt;
+ }
+ last;
+ }
+ }
+ # a MIME type is unknown--It judges from an extension.
+ unless ($Ext) {
+ $ContentName = &CheckContentExt($FileExt);
+ if($ContentName) {
+ $Ext = $FileExt;
+ $Infomation .= ' / MIME type is unknown('. $ContentType. ')';
+ last;
+ }
+ }
+ }
+
+# $ContentName = &CheckContentExt($Ext) unless($ContentName);
+# if($Ext && $ContentName) {
+# $ContentName .= $Infomation;
+# } else {
+# &upload_error(
+# 'Extension Error',
+# "$FileName A not corresponding extension ($Ext)<BR>The extension which can be responded ". join(',', sort values(%UPLOAD_EXT_LIST))
+# );
+# }
+
+# # SSI Tag Deletion
+# if($Ext =~ /.?html?/ && $$DATA =~ /<\!/) {
+# foreach (
+# 'config',
+# 'echo',
+# 'exec',
+# 'flastmod',
+# 'fsize',
+# 'include'
+# ) {
+# $$DATA =~ s/\#\s*$_/\&\#35\;$_/ig
+# }
+# }
+
+ return (
+ $FileName,
+ $Ext,
+ int($DataLength / 1024 + 1),
+ $ImageWidth,
+ $ImageHeight,
+ $ContentName
+ );
+}
+
+##############################################################################
+# Summary
+#
+# Extension discernment
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+
+sub CheckContentExt
+{
+
+ my($Ext) = @_;
+ my $ContentName;
+ foreach (keys %UPLOAD_EXT_LIST) {
+ next unless ($_);
+ if($_ && $Ext =~ /^$_$/) {
+ $ContentName = $UPLOAD_EXT_LIST{$_};
+ last;
+ }
+ }
+ return $ContentName;
+
+}
+
+##############################################################################
+# Summary
+#
+# Form decode
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+sub Encode
+{
+
+ my($value,$Trans) = @_;
+
+# my $FormCode = &jcode::getcode($value) || $FormCodeDefault;
+# $FormCodeDefault ||= $FormCode;
+#
+# if($Trans && $TRANS_2BYTE_CODE) {
+# if($FormCode ne 'euc') {
+# &jcode::convert($value, 'euc', $FormCode);
+# }
+# &jcode::tr(
+# $value,
+# "\xA3\xB0-\xA3\xB9\xA3\xC1-\xA3\xDA\xA3\xE1-\xA3\xFA",
+# '0-9A-Za-z'
+# );
+# if($CHARCODE ne 'euc') {
+# &jcode::convert($value,$CHARCODE,'euc');
+# }
+# } else {
+# if($CHARCODE ne $FormCode) {
+# &jcode::convert($value,$CHARCODE,$FormCode);
+# }
+# }
+# if($CHARCODE eq 'euc') {
+# &jcode::h2z_euc($value);
+# } elsif($CHARCODE eq 'sjis') {
+# &jcode::h2z_sjis($value);
+# }
+
+}
+
+##############################################################################
+# Summary
+#
+# Error Msg
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+
+sub upload_error
+{
+
+ local($error_message) = $_[0];
+ local($error_message2) = $_[1];
+
+ print "Content-type: text/html\n\n";
+ print<<EOF;
+<HTML>
+<HEAD>
+<TITLE>Error Message</TITLE></HEAD>
+<BODY>
+<table border="1" cellspacing="10" cellpadding="10">
+ <TR bgcolor="#0000B0">
+ <TD bgcolor="#0000B0" NOWRAP><font size="-1" color="white"><B>Error Message</B></font></TD>
+ </TR>
+</table>
+<UL>
+<H4> $error_message </H4>
+$error_message2 <BR>
+</UL>
+</BODY>
+</HTML>
+EOF
+ &rm_tmp_uploaded_files; # Image Temporary deletion
+ exit;
+}
+
+##############################################################################
+# Summary
+#
+# Image Temporary deletion
+#
+# Parameters
+# Returns
+# Memo
+##############################################################################
+
+sub rm_tmp_uploaded_files
+{
+ if($img_data_exists == 1){
+ sleep 1;
+ foreach $fname_list(@NEWFNAMES) {
+ if(-e "$img_dir/$fname_list") {
+ unlink("$img_dir/$fname_list");
+ }
+ }
+ }
+
+}
+1;
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl
new file mode 100644
index 000000000..e86029221
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl
@@ -0,0 +1,60 @@
+#####
+# FCKeditor - The text editor for Internet - http://www.fckeditor.net
+# Copyright (C) 2003-2007 Frederico Caldeira Knabben
+#
+# == BEGIN LICENSE ==
+#
+# Licensed under the terms of any of the following licenses at your
+# choice:
+#
+# - GNU General Public License Version 2 or later (the "GPL")
+# http://www.gnu.org/licenses/gpl.html
+#
+# - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+# http://www.gnu.org/licenses/lgpl.html
+#
+# - Mozilla Public License Version 1.1 or later (the "MPL")
+# http://www.mozilla.org/MPL/MPL-1.1.html
+#
+# == END LICENSE ==
+#
+# This is the File Manager Connector for Perl.
+#####
+
+sub RemoveFromStart
+{
+ local($sourceString, $charToRemove) = @_;
+ $sPattern = '^' . $charToRemove . '+' ;
+ $sourceString =~ s/^$charToRemove+//g;
+ return $sourceString;
+}
+
+sub RemoveFromEnd
+{
+ local($sourceString, $charToRemove) = @_;
+ $sPattern = $charToRemove . '+$' ;
+ $sourceString =~ s/$charToRemove+$//g;
+ return $sourceString;
+}
+
+sub ConvertToXmlAttribute
+{
+ local($value) = @_;
+ return $value;
+# return utf8_encode(htmlspecialchars($value));
+
+}
+
+sub specialchar_cnv
+{
+ local($ch) = @_;
+
+ $ch =~ s/&/&amp;/g; # &
+ $ch =~ s/\"/&quot;/g; #"
+ $ch =~ s/\'/&#39;/g; # '
+ $ch =~ s/</&lt;/g; # <
+ $ch =~ s/>/&gt;/g; # >
+ return($ch);
+}
+
+1;
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmactualfolder.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmactualfolder.html
new file mode 100644
index 000000000..90653d6ed
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmactualfolder.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page shows the actual folder path.
+-->
+<html>
+ <head>
+ <link href="browser.css" type="text/css" rel="stylesheet">
+ <script type="text/javascript">
+
+function OnResize()
+{
+ divName.style.width = "1px" ;
+ divName.style.width = tdName.offsetWidth + "px" ;
+}
+
+function SetCurrentFolder( resourceType, folderPath )
+{
+ document.getElementById('tdName').innerHTML = folderPath ;
+}
+
+window.onload = function()
+{
+ window.top.IsLoadedActualFolder = true ;
+}
+
+ </script>
+ </head>
+ <body bottomMargin="0" topMargin="0">
+ <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td>
+ <button style="WIDTH: 100%" type="button">
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td><img height="32" alt="" src="images/FolderOpened32.gif" width="32"></td>
+ <td>&nbsp;</td>
+ <td id="tdName" width="100%" nowrap class="ActualFolder">/</td>
+ <td>&nbsp;</td>
+ <td><img height="8" src="images/ButtonArrow.gif" width="12"></td>
+ <td>&nbsp;</td>
+ </tr>
+ </table>
+ </button>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html
new file mode 100644
index 000000000..8f72ff564
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Page used to create new folders in the current folder.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link href="browser.css" type="text/css" rel="stylesheet">
+ <script type="text/javascript" src="js/common.js"></script>
+ <script language="javascript">
+
+function SetCurrentFolder( resourceType, folderPath )
+{
+ oConnector.ResourceType = resourceType ;
+ oConnector.CurrentFolder = folderPath ;
+}
+
+function CreateFolder()
+{
+ var sFolderName ;
+
+ while ( true )
+ {
+ sFolderName = prompt( 'Type the name of the new folder:', '' ) ;
+
+ if ( sFolderName == null )
+ return ;
+ else if ( sFolderName.length == 0 )
+ alert( 'Please type the folder name' ) ;
+ else
+ break ;
+ }
+
+ oConnector.SendCommand( 'CreateFolder', 'NewFolderName=' + encodeURIComponent( sFolderName) , CreateFolderCallBack ) ;
+}
+
+function CreateFolderCallBack( fckXml )
+{
+ if ( oConnector.CheckError( fckXml ) == 0 )
+ window.parent.frames['frmResourcesList'].Refresh() ;
+
+ /*
+ // Get the current folder path.
+ var oNode = fckXml.SelectSingleNode( 'Connector/Error' ) ;
+ var iErrorNumber = parseInt( oNode.attributes.getNamedItem('number').value ) ;
+
+ switch ( iErrorNumber )
+ {
+ case 0 :
+ window.parent.frames['frmResourcesList'].Refresh() ;
+ break ;
+ case 101 :
+ alert( 'Folder already exists' ) ;
+ break ;
+ case 102 :
+ alert( 'Invalid folder name' ) ;
+ break ;
+ case 103 :
+ alert( 'You have no permissions to create the folder' ) ;
+ break ;
+ case 110 :
+ alert( 'Unknown error creating folder' ) ;
+ break ;
+ default :
+ alert( 'Error creating folder. Error number: ' + iErrorNumber ) ;
+ break ;
+ }
+ */
+}
+
+window.onload = function()
+{
+ window.top.IsLoadedCreateFolder = true ;
+}
+ </script>
+ </head>
+ <body bottomMargin="0" topMargin="0">
+ <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td>
+ <button type="button" style="WIDTH: 100%" onclick="CreateFolder();">
+ <table cellSpacing="0" cellPadding="0" border="0">
+ <tr>
+ <td><img height="16" alt="" src="images/Folder.gif" width="16"></td>
+ <td>&nbsp;</td>
+ <td nowrap>Create New Folder</td>
+ </tr>
+ </table>
+ </button>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmfolders.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmfolders.html
new file mode 100644
index 000000000..2dc0eb0dd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmfolders.html
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page shows the list of folders available in the parent folder
+ * of the current folder.
+-->
+<html>
+ <head>
+ <link href="browser.css" type="text/css" rel="stylesheet">
+ <script type="text/javascript" src="js/common.js"></script>
+ <script language="javascript">
+
+var sActiveFolder ;
+
+var bIsLoaded = false ;
+var iIntervalId ;
+
+var oListManager = new Object() ;
+
+oListManager.Init = function()
+{
+ this.Table = document.getElementById('tableFiles') ;
+ this.UpRow = document.getElementById('trUp') ;
+
+ this.TableRows = new Object() ;
+}
+
+oListManager.Clear = function()
+{
+ // Remove all other rows available.
+ while ( this.Table.rows.length > 1 )
+ this.Table.deleteRow(1) ;
+
+ // Reset the TableRows collection.
+ this.TableRows = new Object() ;
+}
+
+oListManager.AddItem = function( folderName, folderPath )
+{
+ // Create the new row.
+ var oRow = this.Table.insertRow(-1) ;
+ oRow.className = 'FolderListFolder' ;
+
+ // Build the link to view the folder.
+ var sLink = '<a href="#" onclick="OpenFolder(\'' + folderPath + '\');return false;">' ;
+
+ // Add the folder icon cell.
+ var oCell = oRow.insertCell(-1) ;
+ oCell.width = 16 ;
+ oCell.innerHTML = sLink + '<img alt="" src="images/spacer.gif" width="16" height="16" border="0"></a>' ;
+
+ // Add the folder name cell.
+ oCell = oRow.insertCell(-1) ;
+ oCell.noWrap = true ;
+ oCell.innerHTML = '&nbsp;' + sLink + folderName + '</a>' ;
+
+ this.TableRows[ folderPath ] = oRow ;
+}
+
+oListManager.ShowUpFolder = function( upFolderPath )
+{
+ this.UpRow.style.display = ( upFolderPath != null ? '' : 'none' ) ;
+
+ if ( upFolderPath != null )
+ {
+ document.getElementById('linkUpIcon').onclick = document.getElementById('linkUp').onclick = function()
+ {
+ LoadFolders( upFolderPath ) ;
+ return false ;
+ }
+ }
+}
+
+function CheckLoaded()
+{
+ if ( window.top.IsLoadedActualFolder
+ && window.top.IsLoadedCreateFolder
+ && window.top.IsLoadedUpload
+ && window.top.IsLoadedResourcesList )
+ {
+ window.clearInterval( iIntervalId ) ;
+ bIsLoaded = true ;
+ OpenFolder( sActiveFolder ) ;
+ }
+}
+
+function OpenFolder( folderPath )
+{
+ sActiveFolder = folderPath ;
+
+ if ( ! bIsLoaded )
+ {
+ if ( ! iIntervalId )
+ iIntervalId = window.setInterval( CheckLoaded, 100 ) ;
+ return ;
+ }
+
+ // Change the style for the select row (to show the opened folder).
+ for ( var sFolderPath in oListManager.TableRows )
+ {
+ oListManager.TableRows[ sFolderPath ].className =
+ ( sFolderPath == folderPath ? 'FolderListCurrentFolder' : 'FolderListFolder' ) ;
+ }
+
+ // Set the current folder in all frames.
+ window.parent.frames['frmActualFolder'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ;
+ window.parent.frames['frmCreateFolder'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ;
+ window.parent.frames['frmUpload'].SetCurrentFolder( oConnector.ResourceType, folderPath ) ;
+
+ // Load the resources list for this folder.
+ window.parent.frames['frmResourcesList'].LoadResources( oConnector.ResourceType, folderPath ) ;
+}
+
+function LoadFolders( folderPath )
+{
+ // Clear the folders list.
+ oListManager.Clear() ;
+
+ // Get the parent folder path.
+ var sParentFolderPath ;
+ if ( folderPath != '/' )
+ sParentFolderPath = folderPath.substring( 0, folderPath.lastIndexOf( '/', folderPath.length - 2 ) + 1 ) ;
+
+ // Show/Hide the Up Folder.
+ oListManager.ShowUpFolder( sParentFolderPath ) ;
+
+ if ( folderPath != '/' )
+ {
+ sActiveFolder = folderPath ;
+ oConnector.CurrentFolder = sParentFolderPath ;
+ oConnector.SendCommand( 'GetFolders', null, GetFoldersCallBack ) ;
+ }
+ else
+ OpenFolder( '/' ) ;
+}
+
+function GetFoldersCallBack( fckXml )
+{
+ if ( oConnector.CheckError( fckXml ) != 0 )
+ return ;
+
+ // Get the current folder path.
+ var oNode = fckXml.SelectSingleNode( 'Connector/CurrentFolder' ) ;
+ var sCurrentFolderPath = oNode.attributes.getNamedItem('path').value ;
+
+ var oNodes = fckXml.SelectNodes( 'Connector/Folders/Folder' ) ;
+
+ for ( var i = 0 ; i < oNodes.length ; i++ )
+ {
+ var sFolderName = oNodes[i].attributes.getNamedItem('name').value ;
+ oListManager.AddItem( sFolderName, sCurrentFolderPath + sFolderName + "/" ) ;
+ }
+
+ OpenFolder( sActiveFolder ) ;
+}
+
+function SetResourceType( type )
+{
+ oConnector.ResourceType = type ;
+ LoadFolders( '/' ) ;
+}
+
+window.onload = function()
+{
+ oListManager.Init() ;
+ LoadFolders( '/' ) ;
+}
+ </script>
+ </head>
+ <body class="FileArea" bottomMargin="10" leftMargin="10" topMargin="10" rightMargin="10">
+ <table id="tableFiles" cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr id="trUp" style="DISPLAY: none">
+ <td width="16"><a id="linkUpIcon" href="#"><img alt="" src="images/FolderUp.gif" width="16" height="16" border="0"></a></td>
+ <td nowrap width="100%">&nbsp;<a id="linkUp" href="#">..</a></td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourceslist.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourceslist.html
new file mode 100644
index 000000000..3f041f78d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourceslist.html
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page shows all resources available in a folder in the File Browser.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <link href="browser.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="js/common.js"></script>
+ <script type="text/javascript">
+
+var oListManager = new Object() ;
+
+oListManager.Clear = function()
+{
+ document.body.innerHTML = '' ;
+}
+
+oListManager.GetFolderRowHtml = function( folderName, folderPath )
+{
+ // Build the link to view the folder.
+ var sLink = '<a href="#" onclick="OpenFolder(\'' + folderPath.replace( /'/g, '\\\'') + '\');return false;">' ;
+
+ return '<tr>' +
+ '<td width="16">' +
+ sLink +
+ '<img alt="" src="images/Folder.gif" width="16" height="16" border="0"></a>' +
+ '</td><td nowrap colspan="2">&nbsp;' +
+ sLink +
+ folderName +
+ '</a>' +
+ '</td></tr>' ;
+}
+
+oListManager.GetFileRowHtml = function( fileName, fileUrl, fileSize )
+{
+ // Build the link to view the folder.
+ var sLink = '<a href="#" onclick="OpenFile(\'' + fileUrl.replace( /'/g, '\\\'') + '\');return false;">' ;
+
+ // Get the file icon.
+ var sIcon = oIcons.GetIcon( fileName ) ;
+
+ return '<tr>' +
+ '<td width="16">' +
+ sLink +
+ '<img alt="" src="images/icons/' + sIcon + '.gif" width="16" height="16" border="0"></a>' +
+ '</td><td>&nbsp;' +
+ sLink +
+ fileName +
+ '</a>' +
+ '</td><td align="right" nowrap>&nbsp;' +
+ fileSize +
+ ' KB' +
+ '</td></tr>' ;
+}
+
+function OpenFolder( folderPath )
+{
+ // Load the resources list for this folder.
+ window.parent.frames['frmFolders'].LoadFolders( folderPath ) ;
+}
+
+function OpenFile( fileUrl )
+{
+ window.top.opener.SetUrl( encodeURI( fileUrl ) ) ;
+ window.top.close() ;
+ window.top.opener.focus() ;
+}
+
+function LoadResources( resourceType, folderPath )
+{
+ oListManager.Clear() ;
+ oConnector.ResourceType = resourceType ;
+ oConnector.CurrentFolder = folderPath ;
+ oConnector.SendCommand( 'GetFoldersAndFiles', null, GetFoldersAndFilesCallBack ) ;
+}
+
+function Refresh()
+{
+ LoadResources( oConnector.ResourceType, oConnector.CurrentFolder ) ;
+}
+
+function GetFoldersAndFilesCallBack( fckXml )
+{
+ if ( oConnector.CheckError( fckXml ) != 0 )
+ return ;
+
+ // Get the current folder path.
+ var oFolderNode = fckXml.SelectSingleNode( 'Connector/CurrentFolder' ) ;
+ if ( oFolderNode == null )
+ {
+ alert( 'The server didn\'t reply with a proper XML data. Please check your configuration.' ) ;
+ return ;
+ }
+ var sCurrentFolderPath = oFolderNode.attributes.getNamedItem('path').value ;
+ var sCurrentFolderUrl = oFolderNode.attributes.getNamedItem('url').value ;
+
+// var dTimer = new Date() ;
+
+ var oHtml = new StringBuilder( '<table id="tableFiles" cellspacing="1" cellpadding="0" width="100%" border="0">' ) ;
+
+ // Add the Folders.
+ var oNodes ;
+ oNodes = fckXml.SelectNodes( 'Connector/Folders/Folder' ) ;
+ for ( var i = 0 ; i < oNodes.length ; i++ )
+ {
+ var sFolderName = oNodes[i].attributes.getNamedItem('name').value ;
+ oHtml.Append( oListManager.GetFolderRowHtml( sFolderName, sCurrentFolderPath + sFolderName + "/" ) ) ;
+ }
+
+ // Add the Files.
+ oNodes = fckXml.SelectNodes( 'Connector/Files/File' ) ;
+ for ( var j = 0 ; j < oNodes.length ; j++ )
+ {
+ var oNode = oNodes[j] ;
+ var sFileName = oNode.attributes.getNamedItem('name').value ;
+ var sFileSize = oNode.attributes.getNamedItem('size').value ;
+
+ // Get the optional "url" attribute. If not available, build the url.
+ var oFileUrlAtt = oNodes[j].attributes.getNamedItem('url') ;
+ var sFileUrl = oFileUrlAtt != null ? oFileUrlAtt.value : sCurrentFolderUrl + sFileName ;
+
+ oHtml.Append( oListManager.GetFileRowHtml( sFileName, sFileUrl, sFileSize ) ) ;
+ }
+
+ oHtml.Append( '<\/table>' ) ;
+
+ document.body.innerHTML = oHtml.ToString() ;
+
+// window.top.document.title = 'Finished processing in ' + ( ( ( new Date() ) - dTimer ) / 1000 ) + ' seconds' ;
+
+}
+
+window.onload = function()
+{
+ window.top.IsLoadedResourcesList = true ;
+}
+ </script>
+</head>
+<body class="FileArea" bottommargin="10" leftmargin="10" topmargin="10" rightmargin="10">
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourcetype.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourcetype.html
new file mode 100644
index 000000000..933e85550
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmresourcetype.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This page shows the list of available resource types.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link href="browser.css" type="text/css" rel="stylesheet">
+ <script type="text/javascript" src="js/common.js"></script>
+ <script language="javascript">
+
+function SetResourceType( type )
+{
+ window.parent.frames["frmFolders"].SetResourceType( type ) ;
+}
+
+var aTypes = [
+ ['File','File'],
+ ['Image','Image'],
+ ['Flash','Flash'],
+ ['Media','Media']
+] ;
+
+window.onload = function()
+{
+ for ( var i = 0 ; i < aTypes.length ; i++ )
+ {
+ if ( oConnector.ShowAllTypes || aTypes[i][0] == oConnector.ResourceType )
+ AddSelectOption( document.getElementById('cmbType'), aTypes[i][1], aTypes[i][0] ) ;
+ }
+}
+
+ </script>
+ </head>
+ <body bottomMargin="0" topMargin="0">
+ <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td nowrap>
+ Resource Type<BR>
+ <select id="cmbType" style="WIDTH: 100%" onchange="SetResourceType(this.value);">
+ </select>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmupload.html b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmupload.html
new file mode 100644
index 000000000..b84882dcd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/frmupload.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Page used to upload new files in the current folder.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link href="browser.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="js/common.js"></script>
+ <script type="text/javascript">
+
+function SetCurrentFolder( resourceType, folderPath )
+{
+ var sUrl = oConnector.ConnectorUrl + 'Command=FileUpload' ;
+ sUrl += '&Type=' + resourceType ;
+ sUrl += '&CurrentFolder=' + encodeURIComponent( folderPath ) ;
+
+ document.getElementById('frmUpload').action = sUrl ;
+}
+
+function OnSubmit()
+{
+ if ( document.getElementById('NewFile').value.length == 0 )
+ {
+ alert( 'Please select a file from your computer' ) ;
+ return false ;
+ }
+
+ // Set the interface elements.
+ document.getElementById('eUploadMessage').innerHTML = 'Upload a new file in this folder (Upload in progress, please wait...)' ;
+ document.getElementById('btnUpload').disabled = true ;
+
+ return true ;
+}
+
+function OnUploadCompleted( errorNumber, data )
+{
+ // Reset the Upload Worker Frame.
+ window.parent.frames['frmUploadWorker'].location = 'javascript:void(0)' ;
+
+ // Reset the upload form (On IE we must do a little trick to avout problems).
+ if ( document.all )
+ document.getElementById('NewFile').outerHTML = '<input id="NewFile" name="NewFile" style="WIDTH: 100%" type="file">' ;
+ else
+ document.getElementById('frmUpload').reset() ;
+
+ // Reset the interface elements.
+ document.getElementById('eUploadMessage').innerHTML = 'Upload a new file in this folder' ;
+ document.getElementById('btnUpload').disabled = false ;
+
+ switch ( errorNumber )
+ {
+ case 0 :
+ window.parent.frames['frmResourcesList'].Refresh() ;
+ break ;
+ case 1 : // Custom error.
+ alert( data ) ;
+ break ;
+ case 201 :
+ window.parent.frames['frmResourcesList'].Refresh() ;
+ alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + data + '"' ) ;
+ break ;
+ case 202 :
+ alert( 'Invalid file' ) ;
+ break ;
+ default :
+ alert( 'Error on file upload. Error number: ' + errorNumber ) ;
+ break ;
+ }
+}
+
+window.onload = function()
+{
+ window.top.IsLoadedUpload = true ;
+}
+ </script>
+ </head>
+ <body bottommargin="0" topmargin="0">
+ <form id="frmUpload" action="" target="frmUploadWorker" method="post" enctype="multipart/form-data" onsubmit="return OnSubmit();">
+ <table height="100%" cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td nowrap="nowrap">
+ <span id="eUploadMessage">Upload a new file in this folder</span><br>
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tr>
+ <td width="100%"><input id="NewFile" name="NewFile" style="WIDTH: 100%" type="file"></td>
+ <td nowrap="nowrap">&nbsp;<input id="btnUpload" type="submit" value="Upload"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif
new file mode 100644
index 000000000..a355e5a44
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder.gif
new file mode 100644
index 000000000..ab6824d7f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder32.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder32.gif
new file mode 100644
index 000000000..b93b752cb
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/Folder32.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif
new file mode 100644
index 000000000..0c5dd413e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif
new file mode 100644
index 000000000..3e3fcf56c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif
new file mode 100644
index 000000000..ad5bc2026
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif
new file mode 100644
index 000000000..699e6a387
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif
new file mode 100644
index 000000000..97025bb6e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif
new file mode 100644
index 000000000..f3c7f82ab
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif
new file mode 100644
index 000000000..b62bd0260
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif
new file mode 100644
index 000000000..976997b1b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif
new file mode 100644
index 000000000..9b5496457
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif
new file mode 100644
index 000000000..b557568b3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif
new file mode 100644
index 000000000..758499394
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif
new file mode 100644
index 000000000..923079fc6
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif
new file mode 100644
index 000000000..df5f5795c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif
new file mode 100644
index 000000000..a9bdf0030
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif
new file mode 100644
index 000000000..a9bdf0030
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif
new file mode 100644
index 000000000..de78363f2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif
new file mode 100644
index 000000000..fe0c98e97
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif
new file mode 100644
index 000000000..d3af9e87b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif
new file mode 100644
index 000000000..7d6360f2a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif
new file mode 100644
index 000000000..4950ec87c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif
new file mode 100644
index 000000000..0a79ebfdf
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/png.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif
new file mode 100644
index 000000000..023431c16
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif
new file mode 100644
index 000000000..b9eace7ed
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif
new file mode 100644
index 000000000..5df7de574
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif
new file mode 100644
index 000000000..7807c075c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif
new file mode 100644
index 000000000..4e2c2e3ce
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif
new file mode 100644
index 000000000..7624697cc
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif
new file mode 100644
index 000000000..afe724a3d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif
new file mode 100644
index 000000000..4fae35662
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif
new file mode 100644
index 000000000..7157f72ad
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif
new file mode 100644
index 000000000..ba5a91312
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif
new file mode 100644
index 000000000..6f3bac9bf
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif
new file mode 100644
index 000000000..7708dd895
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif
new file mode 100644
index 000000000..4d927230b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif
new file mode 100644
index 000000000..6ce26a4dc
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif
new file mode 100644
index 000000000..48d445acd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif
new file mode 100644
index 000000000..6535b4c0e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif
new file mode 100644
index 000000000..315817f5d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif
new file mode 100644
index 000000000..8f91a98ec
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif
new file mode 100644
index 000000000..a5e3e6cfb
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif
new file mode 100644
index 000000000..0b5d6ba1f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/html.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/html.gif
new file mode 100644
index 000000000..0b5d6ba1f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/html.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif
new file mode 100644
index 000000000..634b38613
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/js.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/js.gif
new file mode 100644
index 000000000..4ea17d452
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/js.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif
new file mode 100644
index 000000000..0d7c10210
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif
new file mode 100644
index 000000000..6f3bac9bf
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif
new file mode 100644
index 000000000..ca1f94acd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/png.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/png.gif
new file mode 100644
index 000000000..b6d1b3201
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/png.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif
new file mode 100644
index 000000000..877a8c867
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif
new file mode 100644
index 000000000..916cd7e63
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif
new file mode 100644
index 000000000..314469da1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif
new file mode 100644
index 000000000..314469da1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif
new file mode 100644
index 000000000..1511ba3e9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif
new file mode 100644
index 000000000..9be3daaed
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif
new file mode 100644
index 000000000..f57715d6a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif
new file mode 100644
index 000000000..455992877
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif
new file mode 100644
index 000000000..b1e24921e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/spacer.gif b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/spacer.gif
new file mode 100644
index 000000000..35d42e808
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/images/spacer.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/common.js b/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/common.js
new file mode 100644
index 000000000..2f472171b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/common.js
@@ -0,0 +1,55 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Common objects and functions shared by all pages that compose the
+ * File Browser dialog window.
+ */
+
+function AddSelectOption( selectElement, optionText, optionValue )
+{
+ var oOption = document.createElement("OPTION") ;
+
+ oOption.text = optionText ;
+ oOption.value = optionValue ;
+
+ selectElement.options.add(oOption) ;
+
+ return oOption ;
+}
+
+var oConnector = window.parent.oConnector ;
+var oIcons = window.parent.oIcons ;
+
+
+function StringBuilder( value )
+{
+ this._Strings = new Array( value || '' ) ;
+}
+
+StringBuilder.prototype.Append = function( value )
+{
+ if ( value )
+ this._Strings.push( value ) ;
+}
+
+StringBuilder.prototype.ToString = function()
+{
+ return this._Strings.join( '' ) ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/fckxml.js b/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/fckxml.js
new file mode 100644
index 000000000..043ca84f5
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/browser/default/js/fckxml.js
@@ -0,0 +1,129 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Defines the FCKXml object that is used for XML data calls
+ * and XML processing.
+ *
+ * This script is shared by almost all pages that compose the
+ * File Browser frameset.
+ */
+
+var FCKXml = function()
+{}
+
+FCKXml.prototype.GetHttpRequest = function()
+{
+ // Gecko / IE7
+ if ( typeof(XMLHttpRequest) != 'undefined' )
+ return new XMLHttpRequest() ;
+
+ // IE6
+ try { return new ActiveXObject( 'Msxml2.XMLHTTP' ) ; }
+ catch(e) {}
+
+ // IE5
+ try { return new ActiveXObject( 'Microsoft.XMLHTTP' ) ; }
+ catch(e) {}
+
+ return null ;
+}
+
+FCKXml.prototype.LoadUrl = function( urlToCall, asyncFunctionPointer )
+{
+ var oFCKXml = this ;
+
+ var bAsync = ( typeof(asyncFunctionPointer) == 'function' ) ;
+
+ var oXmlHttp = this.GetHttpRequest() ;
+
+ oXmlHttp.open( "GET", urlToCall, bAsync ) ;
+
+ if ( bAsync )
+ {
+ oXmlHttp.onreadystatechange = function()
+ {
+ if ( oXmlHttp.readyState == 4 )
+ {
+ if ( ( oXmlHttp.status != 200 && oXmlHttp.status != 304 ) || oXmlHttp.responseXML == null || oXmlHttp.responseXML.firstChild == null )
+ {
+ alert( 'The server didn\'t send back a proper XML response. Please contact your system administrator.\n\n' +
+ 'XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')\n\n' +
+ 'Requested URL:\n' + urlToCall + '\n\n' +
+ 'Response text:\n' + oXmlHttp.responseText ) ;
+ return ;
+ }
+
+ oFCKXml.DOMDocument = oXmlHttp.responseXML ;
+ asyncFunctionPointer( oFCKXml ) ;
+ }
+ }
+ }
+
+ oXmlHttp.send( null ) ;
+
+ if ( ! bAsync )
+ {
+ if ( oXmlHttp.status == 200 || oXmlHttp.status == 304 )
+ this.DOMDocument = oXmlHttp.responseXML ;
+ else
+ {
+ alert( 'XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')' ) ;
+ }
+ }
+}
+
+FCKXml.prototype.SelectNodes = function( xpath )
+{
+ if ( navigator.userAgent.indexOf('MSIE') >= 0 ) // IE
+ return this.DOMDocument.selectNodes( xpath ) ;
+ else // Gecko
+ {
+ var aNodeArray = new Array();
+
+ var xPathResult = this.DOMDocument.evaluate( xpath, this.DOMDocument,
+ this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null) ;
+ if ( xPathResult )
+ {
+ var oNode = xPathResult.iterateNext() ;
+ while( oNode )
+ {
+ aNodeArray[aNodeArray.length] = oNode ;
+ oNode = xPathResult.iterateNext();
+ }
+ }
+ return aNodeArray ;
+ }
+}
+
+FCKXml.prototype.SelectSingleNode = function( xpath )
+{
+ if ( navigator.userAgent.indexOf('MSIE') >= 0 ) // IE
+ return this.DOMDocument.selectSingleNode( xpath ) ;
+ else // Gecko
+ {
+ var xPathResult = this.DOMDocument.evaluate( xpath, this.DOMDocument,
+ this.DOMDocument.createNSResolver(this.DOMDocument.documentElement), 9, null);
+
+ if ( xPathResult && xPathResult.singleNodeValue )
+ return xPathResult.singleNodeValue ;
+ else
+ return null ;
+ }
+}
diff --git a/httemplate/elements/fckeditor/editor/filemanager/upload/test.html b/httemplate/elements/fckeditor/editor/filemanager/upload/test.html
new file mode 100644
index 000000000..cf29e9761
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/filemanager/upload/test.html
@@ -0,0 +1,133 @@
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Test page for the "File Uploaders".
+-->
+<html>
+ <head>
+ <title>FCKeditor - Uploaders Tests</title>
+ <script language="javascript">
+
+function SendFile()
+{
+ var sUploaderUrl = cmbUploaderUrl.value ;
+
+ if ( sUploaderUrl.length == 0 )
+ sUploaderUrl = txtCustomUrl.value ;
+
+ if ( sUploaderUrl.length == 0 )
+ {
+ alert( 'Please provide your custom URL or select a default one' ) ;
+ return ;
+ }
+
+ eURL.innerHTML = sUploaderUrl ;
+ txtUrl.value = '' ;
+
+ frmUpload.action = sUploaderUrl ;
+ frmUpload.submit() ;
+}
+
+function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg )
+{
+ switch ( errorNumber )
+ {
+ case 0 : // No errors
+ txtUrl.value = fileUrl ;
+ alert( 'File uploaded with no errors' ) ;
+ break ;
+ case 1 : // Custom error
+ alert( customMsg ) ;
+ break ;
+ case 10 : // Custom warning
+ txtUrl.value = fileUrl ;
+ alert( customMsg ) ;
+ break ;
+ case 201 :
+ txtUrl.value = fileUrl ;
+ alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ;
+ break ;
+ case 202 :
+ alert( 'Invalid file' ) ;
+ break ;
+ case 203 :
+ alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ;
+ break ;
+ default :
+ alert( 'Error on file upload. Error number: ' + errorNumber ) ;
+ break ;
+ }
+}
+
+ </script>
+ </head>
+ <body>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0" height="100%">
+ <tr>
+ <td>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td nowrap>
+ Select the "File Uploader" to use:<br>
+ <select id="cmbUploaderUrl">
+ <option selected value="asp/upload.asp">ASP</option>
+ <option value="aspx/upload.aspx">ASP.Net</option>
+ <option value="cfm/upload.cfm">ColdFusion</option>
+ <option value="lasso/upload.lasso">Lasso</option>
+ <option value="php/upload.php">PHP</option>
+ <option value="">(Custom)</option>
+ </select>
+ </td>
+ <td nowrap>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td width="100%">
+ Custom Uploader URL:<BR>
+ <input id="txtCustomUrl" style="WIDTH: 100%; BACKGROUND-COLOR: #dcdcdc" disabled type="text">
+ </td>
+ </tr>
+ </table>
+ <br>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td noWrap>
+ <form id="frmUpload" target="UploadWindow" enctype="multipart/form-data" action="" method="post">
+ Upload a new file:<br>
+ <input type="file" name="NewFile"><br>
+ <input type="button" value="Send it to the Server" onclick="SendFile();">
+ </form>
+ </td>
+ <td style="WIDTH: 16px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td vAlign="top" width="100%">
+ Uploaded File URL:<br>
+ <INPUT id="txtUrl" style="WIDTH: 100%" readonly type="text">
+ </td>
+ </tr>
+ </table>
+ <br>
+ Post URL: <span id="eURL">&nbsp;</span>
+ </td>
+ </tr>
+ <tr>
+ <td height="100%">
+ <iframe name="UploadWindow" width="100%" height="100%" src="javascript:void(0)"></iframe>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/images/anchor.gif b/httemplate/elements/fckeditor/editor/images/anchor.gif
new file mode 100644
index 000000000..5aa797b22
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/anchor.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/arrow_ltr.gif b/httemplate/elements/fckeditor/editor/images/arrow_ltr.gif
new file mode 100644
index 000000000..9c59bfe0b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/arrow_ltr.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/arrow_rtl.gif b/httemplate/elements/fckeditor/editor/images/arrow_rtl.gif
new file mode 100644
index 000000000..22e864984
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/arrow_rtl.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/angel_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/angel_smile.gif
new file mode 100644
index 000000000..a95e05371
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/angel_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/angry_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/angry_smile.gif
new file mode 100644
index 000000000..c667c5d6a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/angry_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/broken_heart.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/broken_heart.gif
new file mode 100644
index 000000000..938cce190
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/broken_heart.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/cake.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/cake.gif
new file mode 100644
index 000000000..f6489d7d5
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/cake.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/confused_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/confused_smile.gif
new file mode 100644
index 000000000..aeb05393d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/confused_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/cry_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/cry_smile.gif
new file mode 100644
index 000000000..0758f429e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/cry_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/devil_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/devil_smile.gif
new file mode 100644
index 000000000..15518d7f0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/devil_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/embaressed_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/embaressed_smile.gif
new file mode 100644
index 000000000..c43194617
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/embaressed_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/envelope.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/envelope.gif
new file mode 100644
index 000000000..66d365614
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/envelope.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/heart.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/heart.gif
new file mode 100644
index 000000000..305714f88
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/heart.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/kiss.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/kiss.gif
new file mode 100644
index 000000000..f840ea602
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/kiss.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/lightbulb.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/lightbulb.gif
new file mode 100644
index 000000000..863be6e51
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/lightbulb.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/omg_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/omg_smile.gif
new file mode 100644
index 000000000..aabc7fd17
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/omg_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/regular_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/regular_smile.gif
new file mode 100644
index 000000000..33f297e81
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/regular_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/sad_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/sad_smile.gif
new file mode 100644
index 000000000..dfb78efea
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/sad_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/shades_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/shades_smile.gif
new file mode 100644
index 000000000..157df770a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/shades_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/teeth_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/teeth_smile.gif
new file mode 100644
index 000000000..26b5a555f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/teeth_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_down.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_down.gif
new file mode 100644
index 000000000..f53ee7249
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_down.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_up.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_up.gif
new file mode 100644
index 000000000..7e8c74627
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/thumbs_up.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/tounge_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/tounge_smile.gif
new file mode 100644
index 000000000..b87ec4465
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/tounge_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif
new file mode 100644
index 000000000..c0741223d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/smiley/msn/wink_smile.gif b/httemplate/elements/fckeditor/editor/images/smiley/msn/wink_smile.gif
new file mode 100644
index 000000000..eefe61dfa
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/smiley/msn/wink_smile.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/images/spacer.gif b/httemplate/elements/fckeditor/editor/images/spacer.gif
new file mode 100644
index 000000000..5bfd67a2d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/images/spacer.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/js/fckeditorcode_gecko.js b/httemplate/elements/fckeditor/editor/js/fckeditorcode_gecko.js
new file mode 100644
index 000000000..8d5d31ada
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/js/fckeditorcode_gecko.js
@@ -0,0 +1,98 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This file has been compressed for better performance. The original source
+ * can be found at "editor/_source".
+ */
+
+var FCK_STATUS_NOTLOADED=window.parent.FCK_STATUS_NOTLOADED=0;var FCK_STATUS_ACTIVE=window.parent.FCK_STATUS_ACTIVE=1;var FCK_STATUS_COMPLETE=window.parent.FCK_STATUS_COMPLETE=2;var FCK_TRISTATE_OFF=window.parent.FCK_TRISTATE_OFF=0;var FCK_TRISTATE_ON=window.parent.FCK_TRISTATE_ON=1;var FCK_TRISTATE_DISABLED=window.parent.FCK_TRISTATE_DISABLED=-1;var FCK_UNKNOWN=window.parent.FCK_UNKNOWN=-9;var FCK_TOOLBARITEM_ONLYICON=window.parent.FCK_TOOLBARITEM_ONLYICON=0;var FCK_TOOLBARITEM_ONLYTEXT=window.parent.FCK_TOOLBARITEM_ONLYTEXT=1;var FCK_TOOLBARITEM_ICONTEXT=window.parent.FCK_TOOLBARITEM_ICONTEXT=2;var FCK_EDITMODE_WYSIWYG=window.parent.FCK_EDITMODE_WYSIWYG=0;var FCK_EDITMODE_SOURCE=window.parent.FCK_EDITMODE_SOURCE=1;var FCK_IMAGES_PATH='images/';var FCK_SPACER_PATH='images/spacer.gif';var CTRL=1000;var SHIFT=2000;var ALT=4000;
+String.prototype.Contains=function(A){return (this.indexOf(A)>-1);};String.prototype.Equals=function(){var A=arguments;if (A.length==1&&A[0].pop) A=A[0];for (var i=0;i<A.length;i++){if (this==A[i]) return true;};return false;};String.prototype.IEquals=function(){var A=this.toUpperCase();var B=arguments;if (B.length==1&&B[0].pop) B=B[0];for (var i=0;i<B.length;i++){if (A==B[i].toUpperCase()) return true;};return false;};String.prototype.ReplaceAll=function(A,B){var C=this;for (var i=0;i<A.length;i++){C=C.replace(A[i],B[i]);};return C;};Array.prototype.AddItem=function(A){var i=this.length;this[i]=A;return i;};Array.prototype.IndexOf=function(A){for (var i=0;i<this.length;i++){if (this[i]==A) return i;};return-1;};String.prototype.StartsWith=function(A){return (this.substr(0,A.length)==A);};String.prototype.EndsWith=function(A,B){var C=this.length;var D=A.length;if (D>C) return false;if (B){var E=new RegExp(A+'$','i');return E.test(this);}else return (D==0||this.substr(C-D,D)==A);};String.prototype.Remove=function(A,B){var s='';if (A>0) s=this.substring(0,A);if (A+B<this.length) s+=this.substring(A+B,this.length);return s;};String.prototype.Trim=function(){return this.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g,'');};String.prototype.LTrim=function(){return this.replace(/^[ \t\n\r]*/g,'');};String.prototype.RTrim=function(){return this.replace(/[ \t\n\r]*$/g,'');};String.prototype.ReplaceNewLineChars=function(A){return this.replace(/\n/g,A);}
+var s=navigator.userAgent.toLowerCase();var FCKBrowserInfo={IsIE:s.Contains('msie'),IsIE7:s.Contains('msie 7'),IsGecko:s.Contains('gecko/'),IsSafari:s.Contains('safari'),IsOpera:s.Contains('opera'),IsMac:s.Contains('macintosh')};(function(A){A.IsGeckoLike=(A.IsGecko||A.IsSafari||A.IsOpera);if (A.IsGecko){var B=s.match(/gecko\/(\d+)/)[1];A.IsGecko10=((B<20051111)||(/rv:1\.7/.test(s)));}else A.IsGecko10=false;})(FCKBrowserInfo);
+var FCKURLParams={};(function(){var A=document.location.search.substr(1).split('&');for (var i=0;i<A.length;i++){var B=A[i].split('=');var C=decodeURIComponent(B[0]);var D=decodeURIComponent(B[1]);FCKURLParams[C]=D;}})();
+var FCKEvents=function(A){this.Owner=A;this._RegisteredEvents={};};FCKEvents.prototype.AttachEvent=function(A,B){var C;if (!(C=this._RegisteredEvents[A])) this._RegisteredEvents[A]=[B];else C.push(B);};FCKEvents.prototype.FireEvent=function(A,B){var C=true;var D=this._RegisteredEvents[A];if (D){for (var i=0;i<D.length;i++) C=(D[i](this.Owner,B)&&C);};return C;};
+var FCK={Name:FCKURLParams['InstanceName'],Status:0,EditMode:0,Toolbar:null,HasFocus:false,AttachToOnSelectionChange:function(A){this.Events.AttachEvent('OnSelectionChange',A);},GetLinkedFieldValue:function(){return this.LinkedField.value;},GetParentForm:function(){return this.LinkedField.form;},StartupValue:'',IsDirty:function(){if (this.EditMode==1) return (this.StartupValue!=this.EditingArea.Textarea.value);else return (this.StartupValue!=this.EditorDocument.body.innerHTML);},ResetIsDirty:function(){if (this.EditMode==1) this.StartupValue=this.EditingArea.Textarea.value;else if (this.EditorDocument.body) this.StartupValue=this.EditorDocument.body.innerHTML;},StartEditor:function(){this.TempBaseTag=FCKConfig.BaseHref.length>0?'<base href="'+FCKConfig.BaseHref+'" _fcktemp="true"></base>':'';var A=FCK.KeystrokeHandler=new FCKKeystrokeHandler();A.OnKeystroke=_FCK_KeystrokeHandler_OnKeystroke;A.SetKeystrokes(FCKConfig.Keystrokes);if (FCKBrowserInfo.IsIE7){if ((CTRL+86/*V*/) in A.Keystrokes) A.SetKeystrokes([CTRL+86,true]);if ((SHIFT+45/*INS*/) in A.Keystrokes) A.SetKeystrokes([SHIFT+45,true]);};this.EditingArea=new FCKEditingArea(document.getElementById('xEditingArea'));this.EditingArea.FFSpellChecker=FCKConfig.FirefoxSpellChecker;FCKListsLib.Setup();this.SetHTML(this.GetLinkedFieldValue(),true);},Focus:function(){FCK.EditingArea.Focus();},SetStatus:function(A){this.Status=A;if (A==1){FCKFocusManager.AddWindow(window,true);if (FCKBrowserInfo.IsIE) FCKFocusManager.AddWindow(window.frameElement,true);if (FCKConfig.StartupFocus) FCK.Focus();};this.Events.FireEvent('OnStatusChange',A);},FixBody:function(){var A=FCKConfig.EnterMode;if (A!='p'&&A!='div') return;var B=this.EditorDocument;if (!B) return;var C=B.body;if (!C) return;FCKDomTools.TrimNode(C);var D=C.firstChild;var E;while (D){var F=false;switch (D.nodeType){case 1:if (!FCKListsLib.BlockElements[D.nodeName.toLowerCase()]) F=true;break;case 3:if (E||D.nodeValue.Trim().length>0) F=true;};if (F){var G=D.parentNode;if (!E) E=G.insertBefore(B.createElement(A),D);E.appendChild(G.removeChild(D));D=E.nextSibling;}else{if (E){FCKDomTools.TrimNode(E);E=null;};D=D.nextSibling;}};if (E) FCKDomTools.TrimNode(E);},GetXHTML:function(A){if (FCK.EditMode==1) return FCK.EditingArea.Textarea.value;this.FixBody();var B;var C=FCK.EditorDocument;if (!C) return null;if (FCKConfig.FullPage){B=FCKXHtml.GetXHTML(C.getElementsByTagName('html')[0],true,A);if (FCK.DocTypeDeclaration&&FCK.DocTypeDeclaration.length>0) B=FCK.DocTypeDeclaration+'\n'+B;if (FCK.XmlDeclaration&&FCK.XmlDeclaration.length>0) B=FCK.XmlDeclaration+'\n'+B;}else{B=FCKXHtml.GetXHTML(C.body,false,A);if (FCKConfig.IgnoreEmptyParagraphValue&&FCKRegexLib.EmptyOutParagraph.test(B)) B='';};B=FCK.ProtectEventsRestore(B);if (FCKBrowserInfo.IsIE) B=B.replace(FCKRegexLib.ToReplace,'$1');return FCKConfig.ProtectedSource.Revert(B);},UpdateLinkedField:function(){FCK.LinkedField.value=FCK.GetXHTML(FCKConfig.FormatOutput);FCK.Events.FireEvent('OnAfterLinkedFieldUpdate');},RegisteredDoubleClickHandlers:{},OnDoubleClick:function(A){var B=FCK.RegisteredDoubleClickHandlers[A.tagName];if (B) B(A);},RegisterDoubleClickHandler:function(A,B){FCK.RegisteredDoubleClickHandlers[B.toUpperCase()]=A;},OnAfterSetHTML:function(){FCKDocumentProcessor.Process(FCK.EditorDocument);FCKUndo.SaveUndoStep();FCK.Events.FireEvent('OnSelectionChange');FCK.Events.FireEvent('OnAfterSetHTML');},ProtectUrls:function(A){A=A.replace(FCKRegexLib.ProtectUrlsA,'$& _fcksavedurl=$1');A=A.replace(FCKRegexLib.ProtectUrlsImg,'$& _fcksavedurl=$1');return A;},ProtectEvents:function(A){return A.replace(FCKRegexLib.TagsWithEvent,_FCK_ProtectEvents_ReplaceTags);},ProtectEventsRestore:function(A){return A.replace(FCKRegexLib.ProtectedEvents,_FCK_ProtectEvents_RestoreEvents);},ProtectTags:function(A){var B=FCKConfig.ProtectedTags;if (FCKBrowserInfo.IsIE) B+=B.length>0?'|ABBR|XML':'ABBR|XML';var C;if (B.length>0){C=new RegExp('<('+B+')(?!\w|:)','gi');A=A.replace(C,'<FCK:$1');C=new RegExp('<\/('+B+')>','gi');A=A.replace(C,'<\/FCK:$1>');};B='META';if (FCKBrowserInfo.IsIE) B+='|HR';C=new RegExp('<(('+B+')(?=\\s|>|/)[\\s\\S]*?)/?>','gi');A=A.replace(C,'<FCK:$1 />');return A;},SetHTML:function(A,B){this.EditingArea.Mode=FCK.EditMode;if (FCK.EditMode==0){A=FCKConfig.ProtectedSource.Protect(A);A=A.replace(FCKRegexLib.InvalidSelfCloseTags,'$1></$2>');A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);if (FCKBrowserInfo.IsGecko){A=A.replace(FCKRegexLib.StrongOpener,'<b$1');A=A.replace(FCKRegexLib.StrongCloser,'<\/b>');A=A.replace(FCKRegexLib.EmOpener,'<i$1');A=A.replace(FCKRegexLib.EmCloser,'<\/i>');};this._ForceResetIsDirty=(B===true);var C='';if (FCKConfig.FullPage){if (!FCKRegexLib.HeadOpener.test(A)){if (!FCKRegexLib.HtmlOpener.test(A)) A='<html dir="'+FCKConfig.ContentLangDirection+'">'+A+'</html>';A=A.replace(FCKRegexLib.HtmlOpener,'$&<head></head>');};FCK.DocTypeDeclaration=A.match(FCKRegexLib.DocTypeTag);if (FCKBrowserInfo.IsIE) C=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C='<link href="'+FCKConfig.FullBasePath+'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C+='<link href="'+FCKConfig.FullBasePath+'css/fck_internal.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C=A.replace(FCKRegexLib.HeadCloser,C+'$&');if (FCK.TempBaseTag.length>0&&!FCKRegexLib.HasBaseTag.test(A)) C=C.replace(FCKRegexLib.HeadOpener,'$&'+FCK.TempBaseTag);}else{C=FCKConfig.DocType+'<html dir="'+FCKConfig.ContentLangDirection+'"';if (FCKBrowserInfo.IsIE&&!FCKRegexLib.Html4DocType.test(FCKConfig.DocType)) C+=' style="overflow-y: scroll"';C+='><head><title></title>'+_FCK_GetEditorAreaStyleTags()+'<link href="'+FCKConfig.FullBasePath+'css/fck_internal.css" rel="stylesheet" type="text/css" _fcktemp="true" />';if (FCKBrowserInfo.IsIE) C+=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C+='<link href="'+FCKConfig.FullBasePath+'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C+=FCK.TempBaseTag;var D='<body';if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) D+=' id="'+FCKConfig.BodyId+'"';if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) D+=' class="'+FCKConfig.BodyClass+'"';C+='</head>'+D+'>';if (FCKBrowserInfo.IsGecko&&(A.length==0||FCKRegexLib.EmptyParagraph.test(A))) C+=GECKO_BOGUS;else C+=A;C+='</body></html>';};this.EditingArea.OnLoad=_FCK_EditingArea_OnLoad;this.EditingArea.Start(C);}else{FCK.EditorWindow=null;FCK.EditorDocument=null;this.EditingArea.OnLoad=null;this.EditingArea.Start(A);this.EditingArea.Textarea._FCKShowContextMenu=true;FCK.EnterKeyHandler=null;if (B) this.ResetIsDirty();FCK.KeystrokeHandler.AttachToElement(this.EditingArea.Textarea);this.EditingArea.Textarea.focus();FCK.Events.FireEvent('OnAfterSetHTML');};if (FCKBrowserInfo.IsGecko) window.onresize();},HasFocus:false,RedirectNamedCommands:{},ExecuteNamedCommand:function(A,B,C){FCKUndo.SaveUndoStep();if (!C&&FCK.RedirectNamedCommands[A]!=null) FCK.ExecuteRedirectedNamedCommand(A,B);else{FCK.Focus();FCK.EditorDocument.execCommand(A,false,B);FCK.Events.FireEvent('OnSelectionChange');};FCKUndo.SaveUndoStep();},GetNamedCommandState:function(A){try{if (!FCK.EditorDocument.queryCommandEnabled(A)) return -1;else return FCK.EditorDocument.queryCommandState(A)?1:0;}catch (e){return 0;}},GetNamedCommandValue:function(A){var B='';var C=FCK.GetNamedCommandState(A);if (C==-1) return null;try{B=this.EditorDocument.queryCommandValue(A);}catch(e) {};return B?B:'';},PasteFromWord:function(){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteFromWord,'dialog/fck_paste.html',400,330,'Word');},Preview:function(){var A=FCKConfig.ScreenWidth*0.8;var B=FCKConfig.ScreenHeight*0.7;var C=(FCKConfig.ScreenWidth-A)/2;var D=window.open('',null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+A+',height='+B+',left='+C);var E;if (FCKConfig.FullPage){if (FCK.TempBaseTag.length>0) E=FCK.TempBaseTag+FCK.GetXHTML();else E=FCK.GetXHTML();}else{E=FCKConfig.DocType+'<html dir="'+FCKConfig.ContentLangDirection+'"><head>'+FCK.TempBaseTag+'<title>'+FCKLang.Preview+'</title>'+_FCK_GetEditorAreaStyleTags()+'</head><body>'+FCK.GetXHTML()+'</body></html>';};D.document.write(E);D.document.close();},SwitchEditMode:function(A){var B=(FCK.EditMode==0);var C=FCK.IsDirty();var D;if (B){if (!A&&FCKBrowserInfo.IsIE) FCKUndo.SaveUndoStep();D=FCK.GetXHTML(FCKConfig.FormatSource);if (D==null) return false;}else D=this.EditingArea.Textarea.value;FCK.EditMode=B?1:0;FCK.SetHTML(D,!C);FCK.Focus();FCKTools.RunFunction(FCK.ToolbarSet.RefreshModeState,FCK.ToolbarSet);return true;},CreateElement:function(A){var e=FCK.EditorDocument.createElement(A);return FCK.InsertElementAndGetIt(e);},InsertElementAndGetIt:function(e){e.setAttribute('FCKTempLabel','true');this.InsertElement(e);var A=FCK.EditorDocument.getElementsByTagName(e.tagName);for (var i=0;i<A.length;i++){if (A[i].getAttribute('FCKTempLabel')){A[i].removeAttribute('FCKTempLabel');return A[i];}};return null;}};FCK.Events=new FCKEvents(FCK);FCK.GetHTML=FCK.GetXHTML;function _FCK_ProtectEvents_ReplaceTags(A){return A.replace(FCKRegexLib.EventAttributes,_FCK_ProtectEvents_ReplaceEvents);};function _FCK_ProtectEvents_ReplaceEvents(A,B){return ' '+B+'_fckprotectedatt="'+A.ReplaceAll([/&/g,/'/g,/"/g,/=/g,/</g,/>/g,/\r/g,/\n/g],['&apos;','&#39;','&quot;','&#61;','&lt;','&gt;','&#10;','&#13;'])+'"';};function _FCK_ProtectEvents_RestoreEvents(A,B){return B.ReplaceAll([/&#39;/g,/&quot;/g,/&#61;/g,/&lt;/g,/&gt;/g,/&#10;/g,/&#13;/g,/&apos;/g],["'",'"','=','<','>','\r','\n','&']);};function _FCK_EditingArea_OnLoad(){FCK.EditorWindow=FCK.EditingArea.Window;FCK.EditorDocument=FCK.EditingArea.Document;FCK.InitializeBehaviors();if (!FCKConfig.DisableEnterKeyHandler) FCK.EnterKeyHandler=new FCKEnterKey(FCK.EditorWindow,FCKConfig.EnterMode,FCKConfig.ShiftEnterMode);FCK.KeystrokeHandler.AttachToElement(FCK.EditorDocument);if (FCK._ForceResetIsDirty) FCK.ResetIsDirty();if (FCKBrowserInfo.IsIE&&FCK.HasFocus) FCK.EditorDocument.body.setActive();FCK.OnAfterSetHTML();if (FCK.Status!=0) return;FCK.SetStatus(1);};function _FCK_GetEditorAreaStyleTags(){var A='';var B=FCKConfig.EditorAreaCSS;for (var i=0;i<B.length;i++) A+='<link href="'+B[i]+'" rel="stylesheet" type="text/css" />';return A;};function _FCK_KeystrokeHandler_OnKeystroke(A,B){if (FCK.Status!=2) return false;if (FCK.EditMode==0){if (B=='Paste') return!FCK.Events.FireEvent('OnPaste');}else{if (B.Equals('Paste','Undo','Redo','SelectAll')) return false;};var C=FCK.Commands.GetCommand(B);return (C.Execute.apply(C,FCKTools.ArgumentsToArray(arguments,2))!==false);};(function(){var A=window.parent.document;var B=A.getElementById(FCK.Name);var i=0;while (B||i==0){if (B&&B.tagName.toLowerCase().Equals('input','textarea')){FCK.LinkedField=B;break;};B=A.getElementsByName(FCK.Name)[i++];}})();var FCKTempBin={Elements:[],AddElement:function(A){var B=this.Elements.length;this.Elements[B]=A;return B;},RemoveElement:function(A){var e=this.Elements[A];this.Elements[A]=null;return e;},Reset:function(){var i=0;while (i<this.Elements.length) this.Elements[i++]=null;this.Elements.length=0;}};var FCKFocusManager=FCK.FocusManager={IsLocked:false,AddWindow:function(A,B){var C;if (FCKBrowserInfo.IsIE) C=A.nodeType==1?A:A.frameElement?A.frameElement:A.document;else C=A.document;FCKTools.AddEventListener(C,'blur',FCKFocusManager_Win_OnBlur);FCKTools.AddEventListener(C,'focus',B?FCKFocusManager_Win_OnFocus_Area:FCKFocusManager_Win_OnFocus);},RemoveWindow:function(A){if (FCKBrowserInfo.IsIE) oTarget=A.nodeType==1?A:A.frameElement?A.frameElement:A.document;else oTarget=A.document;FCKTools.RemoveEventListener(oTarget,'blur',FCKFocusManager_Win_OnBlur);FCKTools.RemoveEventListener(oTarget,'focus',FCKFocusManager_Win_OnFocus_Area);FCKTools.RemoveEventListener(oTarget,'focus',FCKFocusManager_Win_OnFocus);},Lock:function(){this.IsLocked=true;},Unlock:function(){if (this._HasPendingBlur) FCKFocusManager._Timer=window.setTimeout(FCKFocusManager_FireOnBlur,100);this.IsLocked=false;},_ResetTimer:function(){this._HasPendingBlur=false;if (this._Timer){window.clearTimeout(this._Timer);delete this._Timer;}}};function FCKFocusManager_Win_OnBlur(){if (typeof(FCK)!='undefined'&&FCK.HasFocus){FCKFocusManager._ResetTimer();FCKFocusManager._Timer=window.setTimeout(FCKFocusManager_FireOnBlur,100);}};function FCKFocusManager_FireOnBlur(){if (FCKFocusManager.IsLocked) FCKFocusManager._HasPendingBlur=true;else{FCK.HasFocus=false;FCK.Events.FireEvent("OnBlur");}};function FCKFocusManager_Win_OnFocus_Area(){FCK.Focus();FCKFocusManager_Win_OnFocus();};function FCKFocusManager_Win_OnFocus(){FCKFocusManager._ResetTimer();if (!FCK.HasFocus&&!FCKFocusManager.IsLocked){FCK.HasFocus=true;FCK.Events.FireEvent("OnFocus");}};
+FCK.Description="FCKeditor for Gecko Browsers";FCK.InitializeBehaviors=function(){if (FCKBrowserInfo.IsGecko) Window_OnResize();FCKFocusManager.AddWindow(this.EditorWindow);this.ExecOnSelectionChange=function(){FCK.Events.FireEvent("OnSelectionChange");};this.ExecOnSelectionChangeTimer=function(){if (FCK.LastOnChangeTimer) window.clearTimeout(FCK.LastOnChangeTimer);FCK.LastOnChangeTimer=window.setTimeout(FCK.ExecOnSelectionChange,100);};this.EditorDocument.addEventListener('mouseup',this.ExecOnSelectionChange,false);this.EditorDocument.addEventListener('keyup',this.ExecOnSelectionChangeTimer,false);this._DblClickListener=function(e){FCK.OnDoubleClick(e.target);e.stopPropagation();};this.EditorDocument.addEventListener('dblclick',this._DblClickListener,true);FCK.ContextMenu._InnerContextMenu.SetMouseClickWindow(FCK.EditorWindow);FCK.ContextMenu._InnerContextMenu.AttachToElement(FCK.EditorDocument);};FCK.MakeEditable=function(){this.EditingArea.MakeEditable();};function Document_OnContextMenu(e){if (!e.target._FCKShowContextMenu) e.preventDefault();};document.oncontextmenu=Document_OnContextMenu;FCK._BaseGetNamedCommandState=FCK.GetNamedCommandState;FCK.GetNamedCommandState=function(A){switch (A){case 'Unlink':return FCKSelection.HasAncestorNode('A')?0:-1;default:return FCK._BaseGetNamedCommandState(A);}};FCK.RedirectNamedCommands={Print:true,Paste:true,Cut:true,Copy:true};FCK.ExecuteRedirectedNamedCommand=function(A,B){switch (A){case 'Print':FCK.EditorWindow.print();break;case 'Paste':try { if (FCK.Paste()) FCK.ExecuteNamedCommand('Paste',null,true);}catch (e) { FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.Paste,'dialog/fck_paste.html',400,330,'Security');};break;case 'Cut':try { FCK.ExecuteNamedCommand('Cut',null,true);}catch (e) { alert(FCKLang.PasteErrorCut);};break;case 'Copy':try { FCK.ExecuteNamedCommand('Copy',null,true);}catch (e) { alert(FCKLang.PasteErrorCopy);};break;default:FCK.ExecuteNamedCommand(A,B);}};FCK.Paste=function(){if (FCKConfig.ForcePasteAsPlainText){FCK.PasteAsPlainText();return false;};return true;};FCK.InsertHtml=function(A){A=FCKConfig.ProtectedSource.Protect(A);A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);A=A.replace(FCKRegexLib.StrongOpener,'<b$1');A=A.replace(FCKRegexLib.StrongCloser,'<\/b>');A=A.replace(FCKRegexLib.EmOpener,'<i$1');A=A.replace(FCKRegexLib.EmCloser,'<\/i>');var B=FCKSelection.Delete();var C=B.getRangeAt(0);var D=C.createContextualFragment(A);var E=D.lastChild;C.insertNode(D);FCKSelection.SelectNode(E);FCKSelection.Collapse(false);this.Focus();};FCK.InsertElement=function(A){var B=FCKSelection.Delete();var C=B.getRangeAt(0);C.insertNode(A);FCKSelection.SelectNode(A);FCKSelection.Collapse(false);this.Focus();};FCK.PasteAsPlainText=function(){FCKTools.RunFunction(FCKDialog.OpenDialog,FCKDialog,['FCKDialog_Paste',FCKLang.PasteAsText,'dialog/fck_paste.html',400,330,'PlainText']);};FCK.GetClipboardHTML=function(){return '';};FCK.CreateLink=function(A){var B=[];FCK.ExecuteNamedCommand('Unlink');if (A.length>0){var C='javascript:void(0);/*'+(new Date().getTime())+'*/';FCK.ExecuteNamedCommand('CreateLink',C);var D=this.EditorDocument.evaluate("//a[@href='"+C+"']",this.EditorDocument.body,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for (var i=0;i<D.snapshotLength;i++){var E=D.snapshotItem(i);E.href=A;B.push(E);}};return B;};
+var FCKConfig=FCK.Config={};if (document.location.protocol=='file:'){FCKConfig.BasePath=decodeURIComponent(document.location.pathname.substr(1));FCKConfig.BasePath=FCKConfig.BasePath.replace(/\\/gi, '/');FCKConfig.BasePath='file://'+FCKConfig.BasePath.substring(0,FCKConfig.BasePath.lastIndexOf('/')+1);FCKConfig.FullBasePath=FCKConfig.BasePath;}else{FCKConfig.BasePath=document.location.pathname.substring(0,document.location.pathname.lastIndexOf('/')+1);FCKConfig.FullBasePath=document.location.protocol+'//'+document.location.host+FCKConfig.BasePath;};FCKConfig.EditorPath=FCKConfig.BasePath.replace(/editor\/$/,'');try{FCKConfig.ScreenWidth=screen.width;FCKConfig.ScreenHeight=screen.height;}catch (e){FCKConfig.ScreenWidth=800;FCKConfig.ScreenHeight=600;};FCKConfig.ProcessHiddenField=function(){this.PageConfig={};var A=window.parent.document.getElementById(FCK.Name+'___Config');if (!A) return;var B=A.value.split('&');for (var i=0;i<B.length;i++){if (B[i].length==0) continue;var C=B[i].split('=');var D=decodeURIComponent(C[0]);var E=decodeURIComponent(C[1]);if (D=='CustomConfigurationsPath') FCKConfig[D]=E;else if (E.toLowerCase()=="true") this.PageConfig[D]=true;else if (E.toLowerCase()=="false") this.PageConfig[D]=false;else if (E.length>0&&!isNaN(E)) this.PageConfig[D]=parseInt(E,10);else this.PageConfig[D]=E;}};function FCKConfig_LoadPageConfig(){var A=FCKConfig.PageConfig;for (var B in A) FCKConfig[B]=A[B];};function FCKConfig_PreProcess(){var A=FCKConfig;if (A.AllowQueryStringDebug){try{if ((/fckdebug=true/i).test(window.top.location.search)) A.Debug=true;}catch (e) {/*Ignore it. Much probably we are inside a FRAME where the "top" is in another domain (security error).*/}};if (!A.PluginsPath.EndsWith('/')) A.PluginsPath+='/';if (typeof(A.EditorAreaCSS)=='string') A.EditorAreaCSS=[A.EditorAreaCSS];var B=A.ToolbarComboPreviewCSS;if (!B||B.length==0) A.ToolbarComboPreviewCSS=A.EditorAreaCSS;else if (typeof(B)=='string') A.ToolbarComboPreviewCSS=[B];};FCKConfig.ToolbarSets={};FCKConfig.Plugins={};FCKConfig.Plugins.Items=[];FCKConfig.Plugins.Add=function(A,B,C){FCKConfig.Plugins.Items.AddItem([A,B,C]);};FCKConfig.ProtectedSource={};FCKConfig.ProtectedSource.RegexEntries=[/<!--[\s\S]*?-->/g,/<script[\s\S]*?<\/script>/gi,/<noscript[\s\S]*?<\/noscript>/gi,/<object[\s\S]+?<\/object>/gi];FCKConfig.ProtectedSource.Add=function(A){this.RegexEntries.AddItem(A);};FCKConfig.ProtectedSource.Protect=function(A){function _Replace(protectedSource){var B=FCKTempBin.AddElement(protectedSource);return '<!--{PS..'+B+'}-->';};for (var i=0;i<this.RegexEntries.length;i++){A=A.replace(this.RegexEntries[i],_Replace);};return A;};FCKConfig.ProtectedSource.Revert=function(A,B){function _Replace(m,opener,index){var C=B?FCKTempBin.RemoveElement(index):FCKTempBin.Elements[index];return FCKConfig.ProtectedSource.Revert(C,B);};return A.replace(/(<|&lt;)!--\{PS..(\d+)\}--(>|&gt;)/g,_Replace);}
+var FCKDebug={};FCKDebug._GetWindow=function(){if (!this.DebugWindow||this.DebugWindow.closed) this.DebugWindow=window.open(FCKConfig.BasePath+'fckdebug.html','FCKeditorDebug','menubar=no,scrollbars=yes,resizable=yes,location=no,toolbar=no,width=600,height=500',true);return this.DebugWindow;};FCKDebug.Output=function(A,B,C){if (!FCKConfig.Debug) return;try{this._GetWindow().Output(A,B);}catch (e) {}};FCKDebug.OutputObject=function(A,B){if (!FCKConfig.Debug) return;try{this._GetWindow().OutputObject(A,B);}catch (e) {}}
+var FCKDomTools={MoveChildren:function(A,B){if (A==B) return;var C;while ((C=A.firstChild)) B.appendChild(A.removeChild(C));},TrimNode:function(A,B){this.LTrimNode(A);this.RTrimNode(A,B);},LTrimNode:function(A){var B;while ((B=A.firstChild)){if (B.nodeType==3){var C=B.nodeValue.LTrim();var D=B.nodeValue.length;if (C.length==0){A.removeChild(B);continue;}else if (C.length<D){B.splitText(D-C.length);A.removeChild(A.firstChild);}};break;}},RTrimNode:function(A,B){var C;while ((C=A.lastChild)){switch (C.nodeType){case 1:if (C.nodeName.toUpperCase()=='BR'&&(B||C.getAttribute('type',2)=='_moz')){C.parentNode.removeChild(C);continue;};break;case 3:var D=C.nodeValue.RTrim();var E=C.nodeValue.length;if (D.length==0){C.parentNode.removeChild(C);continue;}else if (D.length<E){C.splitText(D.length);A.lastChild.parentNode.removeChild(A.lastChild);}};break;}},RemoveNode:function(A,B){if (B){var C;while ((C=A.firstChild)) A.parentNode.insertBefore(A.removeChild(C),A);};return A.parentNode.removeChild(A);},GetFirstChild:function(A,B){if (typeof (B)=='string') B=[B];var C=A.firstChild;while(C){if (C.nodeType==1&&C.tagName.Equals.apply(C.tagName,B)) return C;C=C.nextSibling;};return null;},GetLastChild:function(A,B){if (typeof (B)=='string') B=[B];var C=A.lastChild;while(C){if (C.nodeType==1&&(!B||C.tagName.Equals(B))) return C;C=C.previousSibling;};return null;},GetPreviousSourceElement:function(A,B,C,D){if (!A) return null;if (C&&A.nodeType==1&&A.nodeName.IEquals(C)) return null;if (A.previousSibling) A=A.previousSibling;else return this.GetPreviousSourceElement(A.parentNode,B,C,D);while (A){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (!D||!A.nodeName.IEquals(D)) return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;if (A.lastChild) A=A.lastChild;else return this.GetPreviousSourceElement(A,B,C,D);};return null;},GetNextSourceElement:function(A,B,C,D){if (!A) return null;if (A.nextSibling) A=A.nextSibling;else return this.GetNextSourceElement(A.parentNode,B,C,D);while (A){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (!D||!A.nodeName.IEquals(D)) return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;if (A.firstChild) A=A.firstChild;else return this.GetNextSourceElement(A,B,C,D);};return null;},InsertAfterNode:function(A,B){return A.parentNode.insertBefore(B,A.nextSibling);},GetParents:function(A){var B=[];while (A){B.splice(0,0,A);A=A.parentNode;};return B;},GetIndexOf:function(A){var B=A.parentNode?A.parentNode.firstChild:null;var C=-1;while (B){C++;if (B==A) return C;B=B.nextSibling;};return-1;}};
+var GECKO_BOGUS='<br type="_moz">';var FCKTools={};FCKTools.CreateBogusBR=function(A){var B=A.createElement('br');B.setAttribute('type','_moz');return B;};FCKTools.AppendStyleSheet=function(A,B){if (typeof(B)=='string') return this._AppendStyleSheet(A,B);else{var C=[];for (var i=0;i<B.length;i++) C.push(this._AppendStyleSheet(A,B[i]));return C;}};FCKTools.GetElementDocument=function (A){return A.ownerDocument||A.document;};FCKTools.GetElementWindow=function(A){return this.GetDocumentWindow(this.GetElementDocument(A));};FCKTools.GetDocumentWindow=function(A){if (FCKBrowserInfo.IsSafari&&!A.parentWindow) this.FixDocumentParentWindow(window.top);return A.parentWindow||A.defaultView;};FCKTools.FixDocumentParentWindow=function(A){A.document.parentWindow=A;for (var i=0;i<A.frames.length;i++) FCKTools.FixDocumentParentWindow(A.frames[i]);};FCKTools.HTMLEncode=function(A){if (!A) return '';A=A.replace(/&/g,'&amp;');A=A.replace(/</g,'&lt;');A=A.replace(/>/g,'&gt;');return A;};FCKTools.HTMLDecode=function(A){if (!A) return '';A=A.replace(/&gt;/g,'>');A=A.replace(/&lt;/g,'<');A=A.replace(/&amp;/g,'&');return A;};FCKTools.AddSelectOption=function(A,B,C){var D=FCKTools.GetElementDocument(A).createElement("OPTION");D.text=B;D.value=C;A.options.add(D);return D;};FCKTools.RunFunction=function(A,B,C,D){if (A) this.SetTimeout(A,0,B,C,D);};FCKTools.SetTimeout=function(A,B,C,D,E){return (E||window).setTimeout(function(){if (D) A.apply(C,[].concat(D));else A.apply(C);},B);};FCKTools.SetInterval=function(A,B,C,D,E){return (E||window).setInterval(function(){A.apply(C,D||[]);},B);};FCKTools.ConvertStyleSizeToHtml=function(A){return A.EndsWith('%')?A:parseInt(A,10);};FCKTools.ConvertHtmlSizeToStyle=function(A){return A.EndsWith('%')?A:(A+'px');};FCKTools.GetElementAscensor=function(A,B){var e=A;var C=","+B.toUpperCase()+",";while (e){if (C.indexOf(","+e.nodeName.toUpperCase()+",")!=-1) return e;e=e.parentNode;};return null;};FCKTools.CreateEventListener=function(A,B){var f=function(){var C=[];for (var i=0;i<arguments.length;i++) C.push(arguments[i]);A.apply(this,C.concat(B));};return f;};FCKTools.IsStrictMode=function(A){return ('CSS1Compat'==(A.compatMode||'CSS1Compat'));};FCKTools.ArgumentsToArray=function(A,B,C){B=B||0;C=C||A.length;var D=[];for (var i=B;i<B+C&&i<A.length;i++) D.push(A[i]);return D;};FCKTools.CloneObject=function(A){var B=function() {};B.prototype=A;return new B;};FCKTools.GetLastItem=function(A){if (A.length>0) return A[A.length-1];return null;};
+FCKTools.CancelEvent=function(e){if (e) e.preventDefault();};FCKTools.DisableSelection=function(A){if (FCKBrowserInfo.IsGecko) A.style.MozUserSelect='none';else A.style.userSelect='none';};FCKTools._AppendStyleSheet=function(A,B){var e=A.createElement('LINK');e.rel='stylesheet';e.type='text/css';e.href=B;A.getElementsByTagName("HEAD")[0].appendChild(e);return e;};FCKTools.ClearElementAttributes=function(A){for (var i=0;i<A.attributes.length;i++){A.removeAttribute(A.attributes[i].name,0);}};FCKTools.GetAllChildrenIds=function(A){var B=[];var C=function(parent){for (var i=0;i<parent.childNodes.length;i++){var D=parent.childNodes[i].id;if (D&&D.length>0) B[B.length]=D;C(parent.childNodes[i]);}};C(A);return B;};FCKTools.RemoveOuterTags=function(e){var A=e.ownerDocument.createDocumentFragment();for (var i=0;i<e.childNodes.length;i++) A.appendChild(e.childNodes[i].cloneNode(true));e.parentNode.replaceChild(A,e);};FCKTools.CreateXmlObject=function(A){switch (A){case 'XmlHttp':return new XMLHttpRequest();case 'DOMDocument':return document.implementation.createDocument('','',null);};return null;};FCKTools.GetScrollPosition=function(A){return { X:A.pageXOffset,Y:A.pageYOffset };};FCKTools.AddEventListener=function(A,B,C){A.addEventListener(B,C,false);};FCKTools.RemoveEventListener=function(A,B,C){A.removeEventListener(B,C,false);};FCKTools.AddEventListenerEx=function(A,B,C,D){A.addEventListener(B,function(e){C.apply(A,[e].concat(D||[]));},false);};FCKTools.GetViewPaneSize=function(A){return { Width:A.innerWidth,Height:A.innerHeight };};FCKTools.SaveStyles=function(A){var B={};if (A.className.length>0){B.Class=A.className;A.className='';};var C=A.getAttribute('style');if (C&&C.length>0){B.Inline=C;A.setAttribute('style','',0);};return B;};FCKTools.RestoreStyles=function(A,B){A.className=B.Class||'';if (B.Inline) A.setAttribute('style',B.Inline,0);else A.removeAttribute('style',0);};FCKTools.RegisterDollarFunction=function(A){A.$=function(id){return this.document.getElementById(id);};};FCKTools.AppendElement=function(A,B){return A.appendChild(A.ownerDocument.createElement(B));};FCKTools.GetElementPosition=function(A,B){var c={ X:0,Y:0 };var C=B||window;var D=FCKTools.GetElementWindow(A);while (A){var E=D.getComputedStyle(A,'').position;if (E&&E!='static'&&A.style.zIndex!=FCKConfig.FloatingPanelsZIndex) break;c.X+=A.offsetLeft-A.scrollLeft;c.Y+=A.offsetTop-A.scrollTop;if (A.offsetParent) A=A.offsetParent;else{if (D!=C){A=D.frameElement;if (A) D=FCKTools.GetElementWindow(A);}else{c.X+=A.scrollLeft;c.Y+=A.scrollTop;break;}}};return c;}
+var FCKeditorAPI;function InitializeAPI(){var A=window.parent;if (!(FCKeditorAPI=A.FCKeditorAPI)){var B='var FCKeditorAPI = {Version : "2.4.3",VersionBuild : "15657",__Instances : new Object(),GetInstance : function( name ){return this.__Instances[ name ];},_FormSubmit : function(){for ( var name in FCKeditorAPI.__Instances ){var oEditor = FCKeditorAPI.__Instances[ name ] ;if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )oEditor.UpdateLinkedField() ;}this._FCKOriginalSubmit() ;},_FunctionQueue : {Functions : new Array(),IsRunning : false,Add : function( f ){this.Functions.push( f );if ( !this.IsRunning )this.StartNext();},StartNext : function(){var aQueue = this.Functions ;if ( aQueue.length > 0 ){this.IsRunning = true;aQueue[0].call();}else this.IsRunning = false;},Remove : function( f ){var aQueue = this.Functions;var i = 0, fFunc;while( (fFunc = aQueue[ i ]) ){if ( fFunc == f )aQueue.splice( i,1 );i++ ;}this.StartNext();}}}';if (A.execScript) A.execScript(B,'JavaScript');else{if (FCKBrowserInfo.IsGecko10){eval.call(A,B);}else if (FCKBrowserInfo.IsSafari){var C=A.document;var D=C.createElement('script');D.appendChild(C.createTextNode(B));C.documentElement.appendChild(D);}else A.eval(B);};FCKeditorAPI=A.FCKeditorAPI;};FCKeditorAPI.__Instances[FCK.Name]=FCK;};function _AttachFormSubmitToAPI(){var A=FCK.GetParentForm();if (A){FCKTools.AddEventListener(A,'submit',FCK.UpdateLinkedField);if (!A._FCKOriginalSubmit&&(typeof(A.submit)=='function'||(!A.submit.tagName&&!A.submit.length))){A._FCKOriginalSubmit=A.submit;A.submit=FCKeditorAPI._FormSubmit;}}};function FCKeditorAPI_Cleanup(){delete FCKeditorAPI.__Instances[FCK.Name];};FCKTools.AddEventListener(window,'unload',FCKeditorAPI_Cleanup);
+var FCKImagePreloader=function(){this._Images=[];};FCKImagePreloader.prototype={AddImages:function(A){if (typeof(A)=='string') A=A.split(';');this._Images=this._Images.concat(A);},Start:function(){var A=this._Images;this._PreloadCount=A.length;for (var i=0;i<A.length;i++){var B=document.createElement('img');B.onload=B.onerror=_FCKImagePreloader_OnImage;B._FCKImagePreloader=this;B.src=A[i];_FCKImagePreloader_ImageCache.push(B);}}};var _FCKImagePreloader_ImageCache=[];function _FCKImagePreloader_OnImage(){var A=this._FCKImagePreloader;if ((--A._PreloadCount)==0&&A.OnComplete) A.OnComplete();this._FCKImagePreloader=null;}
+var FCKRegexLib={AposEntity:/&apos;/gi,ObjectElements:/^(?:IMG|TABLE|TR|TD|TH|INPUT|SELECT|TEXTAREA|HR|OBJECT|A|UL|OL|LI)$/i,NamedCommands:/^(?:Cut|Copy|Paste|Print|SelectAll|RemoveFormat|Unlink|Undo|Redo|Bold|Italic|Underline|StrikeThrough|Subscript|Superscript|JustifyLeft|JustifyCenter|JustifyRight|JustifyFull|Outdent|Indent|InsertOrderedList|InsertUnorderedList|InsertHorizontalRule)$/i,BodyContents:/([\s\S]*\<body[^\>]*\>)([\s\S]*)(\<\/body\>[\s\S]*)/i,ToReplace:/___fcktoreplace:([\w]+)/ig,MetaHttpEquiv:/http-equiv\s*=\s*["']?([^"' ]+)/i,HasBaseTag:/<base /i,HtmlOpener:/<html\s?[^>]*>/i,HeadOpener:/<head\s?[^>]*>/i,HeadCloser:/<\/head\s*>/i,FCK_Class:/(\s*FCK__[A-Za-z]*\s*)/,ElementName:/(^[a-z_:][\w.\-:]*\w$)|(^[a-z_]$)/,ForceSimpleAmpersand:/___FCKAmp___/g,SpaceNoClose:/\/>/g,EmptyParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>\s*(<\/\1>)?$/,EmptyOutParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>(?:\s*|&nbsp;)(<\/\1>)?$/,TagBody:/></,StrongOpener:/<STRONG([ \>])/gi,StrongCloser:/<\/STRONG>/gi,EmOpener:/<EM([ \>])/gi,EmCloser:/<\/EM>/gi,GeckoEntitiesMarker:/#\?-\:/g,ProtectUrlsImg:/<img(?=\s).*?\ssrc=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi,ProtectUrlsA:/<a(?=\s).*?\shref=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi,Html4DocType:/HTML 4\.0 Transitional/i,DocTypeTag:/<!DOCTYPE[^>]*>/i,TagsWithEvent:/<[^\>]+ on\w+[\s\r\n]*=[\s\r\n]*?('|")[\s\S]+?\>/g,EventAttributes:/\s(on\w+)[\s\r\n]*=[\s\r\n]*?('|")([\s\S]*?)\2/g,ProtectedEvents:/\s\w+_fckprotectedatt="([^"]+)"/g,StyleProperties:/\S+\s*:/g,InvalidSelfCloseTags:/(<(?!base|meta|link|hr|br|param|img|area|input)([a-zA-Z0-9:]+)[^>]*)\/>/gi};
+var FCKListsLib={BlockElements:{ address:1,blockquote:1,center:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,marquee:1,noscript:1,ol:1,p:1,pre:1,script:1,table:1,ul:1 },NonEmptyBlockElements:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,address:1,pre:1,ol:1,ul:1,li:1,td:1,th:1 },InlineChildReqElements:{ abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },EmptyElements:{ base:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 },PathBlockElements:{ address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1 },PathBlockLimitElements:{ body:1,td:1,th:1,caption:1,form:1 },Setup:function(){if (FCKConfig.EnterMode=='div') this.PathBlockElements.div=1;else this.PathBlockLimitElements.div=1;}};
+var FCKLanguageManager=FCK.Language={AvailableLanguages:{af:'Afrikaans',ar:'Arabic',bg:'Bulgarian',bn:'Bengali/Bangla',bs:'Bosnian',ca:'Catalan',cs:'Czech',da:'Danish',de:'German',el:'Greek',en:'English','en-au':'English (Australia)','en-ca':'English (Canadian)','en-uk':'English (United Kingdom)',eo:'Esperanto',es:'Spanish',et:'Estonian',eu:'Basque',fa:'Persian',fi:'Finnish',fo:'Faroese',fr:'French',gl:'Galician',he:'Hebrew',hi:'Hindi',hr:'Croatian',hu:'Hungarian',it:'Italian',ja:'Japanese',km:'Khmer',ko:'Korean',lt:'Lithuanian',lv:'Latvian',mn:'Mongolian',ms:'Malay',nb:'Norwegian Bokmal',nl:'Dutch',no:'Norwegian',pl:'Polish',pt:'Portuguese (Portugal)','pt-br':'Portuguese (Brazil)',ro:'Romanian',ru:'Russian',sk:'Slovak',sl:'Slovenian',sr:'Serbian (Cyrillic)','sr-latn':'Serbian (Latin)',sv:'Swedish',th:'Thai',tr:'Turkish',uk:'Ukrainian',vi:'Vietnamese',zh:'Chinese Traditional','zh-cn':'Chinese Simplified'},GetActiveLanguage:function(){if (FCKConfig.AutoDetectLanguage){var A;if (navigator.userLanguage) A=navigator.userLanguage.toLowerCase();else if (navigator.language) A=navigator.language.toLowerCase();else{return FCKConfig.DefaultLanguage;};if (A.length>=5){A=A.substr(0,5);if (this.AvailableLanguages[A]) return A;};if (A.length>=2){A=A.substr(0,2);if (this.AvailableLanguages[A]) return A;}};return this.DefaultLanguage;},TranslateElements:function(A,B,C,D){var e=A.getElementsByTagName(B);var E,s;for (var i=0;i<e.length;i++){if ((E=e[i].getAttribute('fckLang'))){if ((s=FCKLang[E])){if (D) s=FCKTools.HTMLEncode(s);eval('e[i].'+C+' = s');}}}},TranslatePage:function(A){this.TranslateElements(A,'INPUT','value');this.TranslateElements(A,'SPAN','innerHTML');this.TranslateElements(A,'LABEL','innerHTML');this.TranslateElements(A,'OPTION','innerHTML',true);},Initialize:function(){if (this.AvailableLanguages[FCKConfig.DefaultLanguage]) this.DefaultLanguage=FCKConfig.DefaultLanguage;else this.DefaultLanguage='en';this.ActiveLanguage={};this.ActiveLanguage.Code=this.GetActiveLanguage();this.ActiveLanguage.Name=this.AvailableLanguages[this.ActiveLanguage.Code];}};
+var FCKXHtmlEntities={};FCKXHtmlEntities.Initialize=function(){if (FCKXHtmlEntities.Entities) return;var A='';var B,e;if (FCKConfig.ProcessHTMLEntities){FCKXHtmlEntities.Entities={' ':'nbsp','¡':'iexcl','¢':'cent','£':'pound','¤':'curren','¥':'yen','¦':'brvbar','§':'sect','¨':'uml','©':'copy','ª':'ordf','«':'laquo','¬':'not','­':'shy','®':'reg','¯':'macr','°':'deg','±':'plusmn','²':'sup2','³':'sup3','´':'acute','µ':'micro','¶':'para','·':'middot','¸':'cedil','¹':'sup1','º':'ordm','»':'raquo','¼':'frac14','½':'frac12','¾':'frac34','¿':'iquest','×':'times','÷':'divide','ƒ':'fnof','•':'bull','…':'hellip','′':'prime','″':'Prime','‾':'oline','⁄':'frasl','℘':'weierp','ℑ':'image','ℜ':'real','™':'trade','ℵ':'alefsym','←':'larr','↑':'uarr','→':'rarr','↓':'darr','↔':'harr','↵':'crarr','⇐':'lArr','⇑':'uArr','⇒':'rArr','⇓':'dArr','⇔':'hArr','∀':'forall','∂':'part','∃':'exist','∅':'empty','∇':'nabla','∈':'isin','∉':'notin','∋':'ni','∏':'prod','∑':'sum','−':'minus','∗':'lowast','√':'radic','∝':'prop','∞':'infin','∠':'ang','∧':'and','∨':'or','∩':'cap','∪':'cup','∫':'int','∴':'there4','∼':'sim','≅':'cong','≈':'asymp','≠':'ne','≡':'equiv','≤':'le','≥':'ge','⊂':'sub','⊃':'sup','⊄':'nsub','⊆':'sube','⊇':'supe','⊕':'oplus','⊗':'otimes','⊥':'perp','⋅':'sdot','◊':'loz','♠':'spades','♣':'clubs','♥':'hearts','♦':'diams','"':'quot','ˆ':'circ','˜':'tilde',' ':'ensp',' ':'emsp',' ':'thinsp','‌':'zwnj','‍':'zwj','‎':'lrm','‏':'rlm','–':'ndash','—':'mdash','‘':'lsquo','’':'rsquo','‚':'sbquo','“':'ldquo','”':'rdquo','„':'bdquo','†':'dagger','‡':'Dagger','‰':'permil','‹':'lsaquo','›':'rsaquo','€':'euro'};for (e in FCKXHtmlEntities.Entities) A+=e;if (FCKConfig.IncludeLatinEntities){B={'À':'Agrave','Á':'Aacute','Â':'Acirc','Ã':'Atilde','Ä':'Auml','Å':'Aring','Æ':'AElig','Ç':'Ccedil','È':'Egrave','É':'Eacute','Ê':'Ecirc','Ë':'Euml','Ì':'Igrave','Í':'Iacute','Î':'Icirc','Ï':'Iuml','Ð':'ETH','Ñ':'Ntilde','Ò':'Ograve','Ó':'Oacute','Ô':'Ocirc','Õ':'Otilde','Ö':'Ouml','Ø':'Oslash','Ù':'Ugrave','Ú':'Uacute','Û':'Ucirc','Ü':'Uuml','Ý':'Yacute','Þ':'THORN','ß':'szlig','à':'agrave','á':'aacute','â':'acirc','ã':'atilde','ä':'auml','å':'aring','æ':'aelig','ç':'ccedil','è':'egrave','é':'eacute','ê':'ecirc','ë':'euml','ì':'igrave','í':'iacute','î':'icirc','ï':'iuml','ð':'eth','ñ':'ntilde','ò':'ograve','ó':'oacute','ô':'ocirc','õ':'otilde','ö':'ouml','ø':'oslash','ù':'ugrave','ú':'uacute','û':'ucirc','ü':'uuml','ý':'yacute','þ':'thorn','ÿ':'yuml','Œ':'OElig','œ':'oelig','Š':'Scaron','š':'scaron','Ÿ':'Yuml'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;};if (FCKConfig.IncludeGreekEntities){B={'Α':'Alpha','Β':'Beta','Γ':'Gamma','Δ':'Delta','Ε':'Epsilon','Ζ':'Zeta','Η':'Eta','Θ':'Theta','Ι':'Iota','Κ':'Kappa','Λ':'Lambda','Μ':'Mu','Ν':'Nu','Ξ':'Xi','Ο':'Omicron','Π':'Pi','Ρ':'Rho','Σ':'Sigma','Τ':'Tau','Υ':'Upsilon','Φ':'Phi','Χ':'Chi','Ψ':'Psi','Ω':'Omega','α':'alpha','β':'beta','γ':'gamma','δ':'delta','ε':'epsilon','ζ':'zeta','η':'eta','θ':'theta','ι':'iota','κ':'kappa','λ':'lambda','μ':'mu','ν':'nu','ξ':'xi','ο':'omicron','π':'pi','ρ':'rho','ς':'sigmaf','σ':'sigma','τ':'tau','υ':'upsilon','φ':'phi','χ':'chi','ψ':'psi','ω':'omega'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;}}else{FCKXHtmlEntities.Entities={};A=' ';};var C='['+A+']';if (FCKConfig.ProcessNumericEntities) C='[^ -~]|'+C;var D=FCKConfig.AdditionalNumericEntities;if (D&&D.length>0) C+='|'+FCKConfig.AdditionalNumericEntities;FCKXHtmlEntities.EntitiesRegex=new RegExp(C,'g');}
+var FCKXHtml={};FCKXHtml.CurrentJobNum=0;FCKXHtml.GetXHTML=function(A,B,C){FCKXHtmlEntities.Initialize();this._NbspEntity=(FCKConfig.ProcessHTMLEntities?'nbsp':'#160');var D=FCK.IsDirty();this._CreateNode=FCKConfig.ForceStrongEm?FCKXHtml_CreateNode_StrongEm:FCKXHtml_CreateNode_Normal;FCKXHtml.SpecialBlocks=[];this.XML=FCKTools.CreateXmlObject('DOMDocument');this.MainNode=this.XML.appendChild(this.XML.createElement('xhtml'));FCKXHtml.CurrentJobNum++;if (B) this._AppendNode(this.MainNode,A);else this._AppendChildNodes(this.MainNode,A,false);var E=this._GetMainXmlString();this.XML=null;E=E.substr(7,E.length-15).Trim();if (FCKBrowserInfo.IsGecko) E=E.replace(/<br\/>$/,'');E=E.replace(FCKRegexLib.SpaceNoClose,' />');if (FCKConfig.ForceSimpleAmpersand) E=E.replace(FCKRegexLib.ForceSimpleAmpersand,'&');if (C) E=FCKCodeFormatter.Format(E);for (var i=0;i<FCKXHtml.SpecialBlocks.length;i++){var F=new RegExp('___FCKsi___'+i);E=E.replace(F,FCKXHtml.SpecialBlocks[i]);};E=E.replace(FCKRegexLib.GeckoEntitiesMarker,'&');if (!D) FCK.ResetIsDirty();return E;};FCKXHtml._AppendAttribute=function(A,B,C){try{if (C==undefined||C==null) C='';else if (C.replace){if (FCKConfig.ForceSimpleAmpersand) C=C.replace(/&/g,'___FCKAmp___');C=C.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity);};var D=this.XML.createAttribute(B);D.value=C;A.attributes.setNamedItem(D);}catch (e){}};FCKXHtml._AppendChildNodes=function(A,B,C){var D=B.firstChild;while (D){this._AppendNode(A,D);D=D.nextSibling;};if (C) FCKDomTools.TrimNode(A,true);if (A.childNodes.length==0){if (C&&FCKConfig.FillEmptyBlocks){this._AppendEntity(A,this._NbspEntity);return A;};var E=A.nodeName;if (FCKListsLib.InlineChildReqElements[E]) return null;if (!FCKListsLib.EmptyElements[E]) A.appendChild(this.XML.createTextNode(''));};return A;};FCKXHtml._AppendNode=function(A,B){if (!B) return false;switch (B.nodeType){case 1:if (B.getAttribute('_fckfakelement')) return FCKXHtml._AppendNode(A,FCK.GetRealElement(B));if (FCKBrowserInfo.IsGecko&&B.hasAttribute('_moz_editor_bogus_node')) return false;if (B.getAttribute('_fcktemp')) return false;var C=B.tagName.toLowerCase();if (FCKBrowserInfo.IsIE){if (B.scopeName&&B.scopeName!='HTML'&&B.scopeName!='FCK') C=B.scopeName.toLowerCase()+':'+C;}else{if (C.StartsWith('fck:')) C=C.Remove(0,4);};if (!FCKRegexLib.ElementName.test(C)) return false;if (C=='br'&&B.getAttribute('type',2)=='_moz') return false;if (B._fckxhtmljob&&B._fckxhtmljob==FCKXHtml.CurrentJobNum) return false;var D=this._CreateNode(C);FCKXHtml._AppendAttributes(A,B,D,C);B._fckxhtmljob=FCKXHtml.CurrentJobNum;var E=FCKXHtml.TagProcessors[C];if (E) D=E(D,B,A);else D=this._AppendChildNodes(D,B,Boolean(FCKListsLib.NonEmptyBlockElements[C]));if (!D) return false;A.appendChild(D);break;case 3:return this._AppendTextNode(A,B.nodeValue.ReplaceNewLineChars(' '));case 8:if (FCKBrowserInfo.IsIE&&!B.innerHTML) break;try { A.appendChild(this.XML.createComment(B.nodeValue));}catch (e) {/*Do nothing... probably this is a wrong format comment.*/};break;default:A.appendChild(this.XML.createComment("Element not supported - Type: "+B.nodeType+" Name: "+B.nodeName));break;};return true;};function FCKXHtml_CreateNode_StrongEm(A){switch (A){case 'b':A='strong';break;case 'i':A='em';break;};return this.XML.createElement(A);};function FCKXHtml_CreateNode_Normal(A){return this.XML.createElement(A);};FCKXHtml._AppendSpecialItem=function(A){return '___FCKsi___'+FCKXHtml.SpecialBlocks.AddItem(A);};FCKXHtml._AppendEntity=function(A,B){A.appendChild(this.XML.createTextNode('#?-:'+B+';'));};FCKXHtml._AppendTextNode=function(A,B){var C=B.length>0;if (C) A.appendChild(this.XML.createTextNode(B.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity)));return C;};function FCKXHtml_GetEntity(A){var B=FCKXHtmlEntities.Entities[A]||('#'+A.charCodeAt(0));return '#?-:'+B+';';};FCKXHtml._RemoveAttribute=function(A,B,C){var D=A.attributes.getNamedItem(C);if (D&&B.test(D.nodeValue)){var E=D.nodeValue.replace(B,'');if (E.length==0) A.attributes.removeNamedItem(C);else D.nodeValue=E;}};FCKXHtml.TagProcessors={img:function(A,B){if (!A.attributes.getNamedItem('alt')) FCKXHtml._AppendAttribute(A,'alt','');var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'src',C);return A;},a:function(A,B){if (B.innerHTML.Trim().length==0&&!B.name) return false;var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){FCKXHtml._RemoveAttribute(A,FCKRegexLib.FCK_Class,'class');if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);};A=FCKXHtml._AppendChildNodes(A,B,false);return A;},script:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/javascript');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.text)));return A;},style:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/css');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.innerHTML)));return A;},title:function(A,B){A.appendChild(FCKXHtml.XML.createTextNode(FCK.EditorDocument.title));return A;},table:function(A,B){if (FCKBrowserInfo.IsIE) FCKXHtml._RemoveAttribute(A,FCKRegexLib.FCK_Class,'class');A=FCKXHtml._AppendChildNodes(A,B,false);return A;},ol:function(A,B,C){if (B.innerHTML.Trim().length==0) return false;var D=C.lastChild;if (D&&D.nodeType==3) D=D.previousSibling;if (D&&D.nodeName.toUpperCase()=='LI'){B._fckxhtmljob=null;FCKXHtml._AppendNode(D,B);return false;};A=FCKXHtml._AppendChildNodes(A,B);return A;},span:function(A,B){if (B.innerHTML.length==0) return false;A=FCKXHtml._AppendChildNodes(A,B,false);return A;},iframe:function(A,B){var C=B.innerHTML;if (FCKBrowserInfo.IsGecko) C=FCKTools.HTMLDecode(C);C=C.replace(/\s_fcksavedurl="[^"]*"/g,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;}};FCKXHtml.TagProcessors.ul=FCKXHtml.TagProcessors.ol;
+FCKXHtml._GetMainXmlString=function(){var A=new XMLSerializer();return A.serializeToString(this.MainNode);};FCKXHtml._AppendAttributes=function(A,B,C){var D=B.attributes;for (var n=0;n<D.length;n++){var E=D[n];if (E.specified){var F=E.nodeName.toLowerCase();var G;if (F.StartsWith('_fck')) continue;else if (F.indexOf('_moz')==0) continue;else if (F=='class') G=E.nodeValue;else if (E.nodeValue===true) G=F;else G=B.getAttribute(F,2);this._AppendAttribute(C,F,G);}}}
+var FCKCodeFormatter={};FCKCodeFormatter.Init=function(){var A=this.Regex={};A.BlocksOpener=/\<(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.BlocksCloser=/\<\/(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.NewLineTags=/\<(BR|HR)[^\>]*\>/gi;A.MainTags=/\<\/?(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR)[^\>]*\>/gi;A.LineSplitter=/\s*\n+\s*/g;A.IncreaseIndent=/^\<(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \/\>]/i;A.DecreaseIndent=/^\<\/(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \>]/i;A.FormatIndentatorRemove=new RegExp('^'+FCKConfig.FormatIndentator);A.ProtectedTags=/(<PRE[^>]*>)([\s\S]*?)(<\/PRE>)/gi;};FCKCodeFormatter._ProtectData=function(A,B,C,D){return B+'___FCKpd___'+FCKCodeFormatter.ProtectedData.AddItem(C)+D;};FCKCodeFormatter.Format=function(A){if (!this.Regex) this.Init();FCKCodeFormatter.ProtectedData=[];var B=A.replace(this.Regex.ProtectedTags,FCKCodeFormatter._ProtectData);B=B.replace(this.Regex.BlocksOpener,'\n$&');B=B.replace(this.Regex.BlocksCloser,'$&\n');B=B.replace(this.Regex.NewLineTags,'$&\n');B=B.replace(this.Regex.MainTags,'\n$&\n');var C='';var D=B.split(this.Regex.LineSplitter);B='';for (var i=0;i<D.length;i++){var E=D[i];if (E.length==0) continue;if (this.Regex.DecreaseIndent.test(E)) C=C.replace(this.Regex.FormatIndentatorRemove,'');B+=C+E+'\n';if (this.Regex.IncreaseIndent.test(E)) C+=FCKConfig.FormatIndentator;};for (var j=0;j<FCKCodeFormatter.ProtectedData.length;j++){var F=new RegExp('___FCKpd___'+j);B=B.replace(F,FCKCodeFormatter.ProtectedData[j].replace(/\$/g,'$$$$'));};return B.Trim();}
+var FCKUndo={};FCKUndo.SaveUndoStep=function(){}
+var FCKEditingArea=function(A){this.TargetElement=A;this.Mode=0;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKEditingArea_Cleanup);};FCKEditingArea.prototype.Start=function(A,B){var C=this.TargetElement;var D=FCKTools.GetElementDocument(C);while(C.childNodes.length>0) C.removeChild(C.childNodes[0]);if (this.Mode==0){var E=this.IFrame=D.createElement('iframe');E.src='javascript:void(0)';E.frameBorder=0;E.width=E.height='100%';C.appendChild(E);if (FCKBrowserInfo.IsIE) A=A.replace(/(<base[^>]*?)\s*\/?>(?!\s*<\/base>)/gi,'$1></base>');else if (!B){if (FCKBrowserInfo.IsGecko) A=A.replace(/(<body[^>]*>)\s*(<\/body>)/i,'$1'+GECKO_BOGUS+'$2');var F=A.match(FCKRegexLib.BodyContents);if (F){A=F[1]+'&nbsp;'+F[3];this._BodyHTML=F[2];}else this._BodyHTML=A;};this.Window=E.contentWindow;var G=this.Document=this.Window.document;G.open();G.write(A);G.close();if (FCKBrowserInfo.IsGecko10&&!B){this.Start(A,true);return;};this.Window._FCKEditingArea=this;if (FCKBrowserInfo.IsGecko10) this.Window.setTimeout(FCKEditingArea_CompleteStart,500);else FCKEditingArea_CompleteStart.call(this.Window);}else{var H=this.Textarea=D.createElement('textarea');H.className='SourceField';H.dir='ltr';H.style.width=H.style.height='100%';H.style.border='none';C.appendChild(H);H.value=A;FCKTools.RunFunction(this.OnLoad);}};function FCKEditingArea_CompleteStart(){if (!this.document.body){this.setTimeout(FCKEditingArea_CompleteStart,50);return;};var A=this._FCKEditingArea;A.MakeEditable();FCKTools.RunFunction(A.OnLoad);};FCKEditingArea.prototype.MakeEditable=function(){var A=this.Document;if (FCKBrowserInfo.IsIE){A.body.contentEditable=true;}else{try{A.body.spellcheck=(this.FFSpellChecker!==false);if (this._BodyHTML){A.body.innerHTML=this._BodyHTML;this._BodyHTML=null;};A.designMode='on';try{A.execCommand('styleWithCSS',false,FCKConfig.GeckoUseSPAN);}catch (e){A.execCommand('useCSS',false,!FCKConfig.GeckoUseSPAN);};A.execCommand('enableObjectResizing',false,!FCKConfig.DisableObjectResizing);A.execCommand('enableInlineTableEditing',false,!FCKConfig.DisableFFTableHandles);}catch (e) {}}};FCKEditingArea.prototype.Focus=function(){try{if (this.Mode==0){if (FCKBrowserInfo.IsIE&&this.Document.hasFocus()) return;if (FCKBrowserInfo.IsSafari) this.IFrame.focus();else{this.Window.focus();}}else{var A=FCKTools.GetElementDocument(this.Textarea);if ((!A.hasFocus||A.hasFocus())&&A.activeElement==this.Textarea) return;this.Textarea.focus();}}catch(e) {}};function FCKEditingArea_Cleanup(){this.TargetElement=null;this.IFrame=null;this.Document=null;this.Textarea=null;if (this.Window){this.Window._FCKEditingArea=null;this.Window=null;}};
+var FCKKeystrokeHandler=function(A){this.Keystrokes={};this.CancelCtrlDefaults=(A!==false);};FCKKeystrokeHandler.prototype.AttachToElement=function(A){FCKTools.AddEventListenerEx(A,'keydown',_FCKKeystrokeHandler_OnKeyDown,this);if (FCKBrowserInfo.IsGecko10||FCKBrowserInfo.IsOpera||(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac)) FCKTools.AddEventListenerEx(A,'keypress',_FCKKeystrokeHandler_OnKeyPress,this);};FCKKeystrokeHandler.prototype.SetKeystrokes=function(){for (var i=0;i<arguments.length;i++){var A=arguments[i];if (typeof(A[0])=='object') this.SetKeystrokes.apply(this,A);else{if (A.length==1) delete this.Keystrokes[A[0]];else this.Keystrokes[A[0]]=A[1]===true?true:A;}}};function _FCKKeystrokeHandler_OnKeyDown(A,B){var C=A.keyCode||A.which;var D=0;if (A.ctrlKey||A.metaKey) D+=CTRL;if (A.shiftKey) D+=SHIFT;if (A.altKey) D+=ALT;var E=C+D;var F=B._CancelIt=false;var G=B.Keystrokes[E];if (G){if (G===true||!(B.OnKeystroke&&B.OnKeystroke.apply(B,G))) return true;F=true;};if (F||(B.CancelCtrlDefaults&&D==CTRL&&(C<33||C>40))){B._CancelIt=true;if (A.preventDefault) return A.preventDefault();A.returnValue=false;A.cancelBubble=true;return false;};return true;};function _FCKKeystrokeHandler_OnKeyPress(A,B){if (B._CancelIt){if (A.preventDefault) return A.preventDefault();return false;};return true;}
+var FCKListHandler={OutdentListItem:function(A){var B=A.parentNode;if (B.tagName.toUpperCase().Equals('UL','OL')){var C=FCKTools.GetElementDocument(A);var D=new FCKDocumentFragment(C);var E=D.RootNode;var F=false;var G=FCKDomTools.GetFirstChild(A,['UL','OL']);if (G){F=true;var H;while ((H=G.firstChild)) E.appendChild(G.removeChild(H));FCKDomTools.RemoveNode(G);};var I;var J=false;while ((I=A.nextSibling)){if (!F&&I.nodeType==1&&I.nodeName.toUpperCase()=='LI') J=F=true;E.appendChild(I.parentNode.removeChild(I));if (!J&&I.nodeType==1&&I.nodeName.toUpperCase().Equals('UL','OL')) FCKDomTools.RemoveNode(I,true);};var K=B.parentNode.tagName.toUpperCase();var L=(K=='LI');if (L||K.Equals('UL','OL')){if (F){var G=B.cloneNode(false);D.AppendTo(G);A.appendChild(G);}else if (L) D.InsertAfterNode(B.parentNode);else D.InsertAfterNode(B);if (L) FCKDomTools.InsertAfterNode(B.parentNode,B.removeChild(A));else FCKDomTools.InsertAfterNode(B,B.removeChild(A));}else{if (F){var N=B.cloneNode(false);D.AppendTo(N);FCKDomTools.InsertAfterNode(B,N);};var O=C.createElement(FCKConfig.EnterMode=='p'?'p':'div');FCKDomTools.MoveChildren(B.removeChild(A),O);FCKDomTools.InsertAfterNode(B,O);if (FCKConfig.EnterMode=='br'){if (FCKBrowserInfo.IsGecko) O.parentNode.insertBefore(FCKTools.CreateBogusBR(C),O);else FCKDomTools.InsertAfterNode(O,FCKTools.CreateBogusBR(C));FCKDomTools.RemoveNode(O,true);}};if (this.CheckEmptyList(B)) FCKDomTools.RemoveNode(B,true);}},CheckEmptyList:function(A){return (FCKDomTools.GetFirstChild(A,'LI')==null);},CheckListHasContents:function(A){var B=A.firstChild;while (B){switch (B.nodeType){case 1:if (!B.nodeName.IEquals('UL','LI')) return true;break;case 3:if (B.nodeValue.Trim().length>0) return true;};B=B.nextSibling;};return false;}};
+var FCKElementPath=function(A){var B=null;var C=null;var D=[];var e=A;while (e){if (e.nodeType==1){if (!this.LastElement) this.LastElement=e;var E=e.nodeName.toLowerCase();if (!C){if (!B&&FCKListsLib.PathBlockElements[E]!=null) B=e;if (FCKListsLib.PathBlockLimitElements[E]!=null) C=e;};D.push(e);if (E=='body') break;};e=e.parentNode;};this.Block=B;this.BlockLimit=C;this.Elements=D;};
+var FCKDomRange=function(A){this.Window=A;};FCKDomRange.prototype={_UpdateElementInfo:function(){if (!this._Range) this.Release(true);else{var A=this._Range.startContainer;var B=this._Range.endContainer;var C=new FCKElementPath(A);this.StartContainer=C.LastElement;this.StartBlock=C.Block;this.StartBlockLimit=C.BlockLimit;if (A!=B) C=new FCKElementPath(B);this.EndContainer=C.LastElement;this.EndBlock=C.Block;this.EndBlockLimit=C.BlockLimit;}},CreateRange:function(){return new FCKW3CRange(this.Window.document);},DeleteContents:function(){if (this._Range){this._Range.deleteContents();this._UpdateElementInfo();}},ExtractContents:function(){if (this._Range){var A=this._Range.extractContents();this._UpdateElementInfo();return A;}},CheckIsCollapsed:function(){if (this._Range) return this._Range.collapsed;},Collapse:function(A){if (this._Range) this._Range.collapse(A);this._UpdateElementInfo();},Clone:function(){var A=FCKTools.CloneObject(this);if (this._Range) A._Range=this._Range.cloneRange();return A;},MoveToNodeContents:function(A){if (!this._Range) this._Range=this.CreateRange();this._Range.selectNodeContents(A);this._UpdateElementInfo();},MoveToElementStart:function(A){this.SetStart(A,1);this.SetEnd(A,1);},MoveToElementEditStart:function(A){var B;while ((B=A.firstChild)&&B.nodeType==1&&FCKListsLib.EmptyElements[B.nodeName.toLowerCase()]==null) A=B;this.MoveToElementStart(A);},InsertNode:function(A){if (this._Range) this._Range.insertNode(A);},CheckIsEmpty:function(A){if (this.CheckIsCollapsed()) return true;var B=this.Window.document.createElement('div');this._Range.cloneContents().AppendTo(B);FCKDomTools.TrimNode(B,A);return (B.innerHTML.length==0);},CheckStartOfBlock:function(){var A=this.Clone();A.Collapse(true);A.SetStart(A.StartBlock||A.StartBlockLimit,1);var B=A.CheckIsEmpty();A.Release();return B;},CheckEndOfBlock:function(A){var B=this.Clone();B.Collapse(false);B.SetEnd(B.EndBlock||B.EndBlockLimit,2);var C=B.CheckIsCollapsed();if (!C){var D=this.Window.document.createElement('div');B._Range.cloneContents().AppendTo(D);FCKDomTools.TrimNode(D,true);C=true;var E=D;while ((E=E.lastChild)){if (E.previousSibling||E.nodeType!=1||FCKListsLib.InlineChildReqElements[E.nodeName.toLowerCase()]==null){C=false;break;}}};B.Release();if (A) this.Select();return C;},CreateBookmark:function(){var A={StartId:'fck_dom_range_start_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000),EndId:'fck_dom_range_end_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000)};var B=this.Window.document;var C;var D;if (!this.CheckIsCollapsed()){C=B.createElement('span');C.id=A.EndId;C.innerHTML='&nbsp;';D=this.Clone();D.Collapse(false);D.InsertNode(C);};C=B.createElement('span');C.id=A.StartId;C.innerHTML='&nbsp;';D=this.Clone();D.Collapse(true);D.InsertNode(C);return A;},MoveToBookmark:function(A,B){var C=this.Window.document;var D=C.getElementById(A.StartId);var E=C.getElementById(A.EndId);this.SetStart(D,3);if (!B) FCKDomTools.RemoveNode(D);if (E){this.SetEnd(E,3);if (!B) FCKDomTools.RemoveNode(E);}else this.Collapse(true);},SetStart:function(A,B){var C=this._Range;if (!C) C=this._Range=this.CreateRange();switch(B){case 1:C.setStart(A,0);break;case 2:C.setStart(A,A.childNodes.length);break;case 3:C.setStartBefore(A);break;case 4:C.setStartAfter(A);};this._UpdateElementInfo();},SetEnd:function(A,B){var C=this._Range;if (!C) C=this._Range=this.CreateRange();switch(B){case 1:C.setEnd(A,0);break;case 2:C.setEnd(A,A.childNodes.length);break;case 3:C.setEndBefore(A);break;case 4:C.setEndAfter(A);};this._UpdateElementInfo();},Expand:function(A){var B,oSibling;switch (A){case 'block_contents':if (this.StartBlock) this.SetStart(this.StartBlock,1);else{B=this._Range.startContainer;if (B.nodeType==1){if (!(B=B.childNodes[this._Range.startOffset])) B=B.firstChild;};if (!B) return;while (true){oSibling=B.previousSibling;if (!oSibling){if (B.parentNode!=this.StartBlockLimit) B=B.parentNode;else break;}else if (oSibling.nodeType!=1||!(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test(oSibling.nodeName.toUpperCase())){B=oSibling;}else break;};this._Range.setStartBefore(B);};if (this.EndBlock) this.SetEnd(this.EndBlock,2);else{B=this._Range.endContainer;if (B.nodeType==1) B=B.childNodes[this._Range.endOffset]||B.lastChild;if (!B) return;while (true){oSibling=B.nextSibling;if (!oSibling){if (B.parentNode!=this.EndBlockLimit) B=B.parentNode;else break;}else if (oSibling.nodeType!=1||!(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test(oSibling.nodeName.toUpperCase())){B=oSibling;}else break;};this._Range.setEndAfter(B);};this._UpdateElementInfo();}},Release:function(A){if (!A) this.Window=null;this.StartContainer=null;this.StartBlock=null;this.StartBlockLimit=null;this.EndContainer=null;this.EndBlock=null;this.EndBlockLimit=null;this._Range=null;}};
+FCKDomRange.prototype.MoveToSelection=function(){this.Release(true);var A=this.Window.getSelection();if (A.rangeCount==1){this._Range=FCKW3CRange.CreateFromRange(this.Window.document,A.getRangeAt(0));this._UpdateElementInfo();}};FCKDomRange.prototype.Select=function(){var A=this._Range;if (A){var B=this.Window.document.createRange();B.setStart(A.startContainer,A.startOffset);try{B.setEnd(A.endContainer,A.endOffset);}catch (e){if (e.toString().Contains('NS_ERROR_ILLEGAL_VALUE')){A.collapse(true);B.setEnd(A.endContainer,A.endOffset);}else throw(e);};var C=this.Window.getSelection();C.removeAllRanges();C.addRange(B);}};
+var FCKDocumentFragment=function(A,B){this.RootNode=B||A.createDocumentFragment();};FCKDocumentFragment.prototype={AppendTo:function(A){A.appendChild(this.RootNode);},InsertAfterNode:function(A){FCKDomTools.InsertAfterNode(A,this.RootNode);}}
+var FCKW3CRange=function(A){this._Document=A;this.startContainer=null;this.startOffset=null;this.endContainer=null;this.endOffset=null;this.collapsed=true;};FCKW3CRange.CreateRange=function(A){return new FCKW3CRange(A);};FCKW3CRange.CreateFromRange=function(A,B){var C=FCKW3CRange.CreateRange(A);C.setStart(B.startContainer,B.startOffset);C.setEnd(B.endContainer,B.endOffset);return C;};FCKW3CRange.prototype={_UpdateCollapsed:function(){this.collapsed=(this.startContainer==this.endContainer&&this.startOffset==this.endOffset);},setStart:function(A,B){this.startContainer=A;this.startOffset=B;if (!this.endContainer){this.endContainer=A;this.endOffset=B;};this._UpdateCollapsed();},setEnd:function(A,B){this.endContainer=A;this.endOffset=B;if (!this.startContainer){this.startContainer=A;this.startOffset=B;};this._UpdateCollapsed();},setStartAfter:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setStartBefore:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A));},setEndAfter:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setEndBefore:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A));},collapse:function(A){if (A){this.endContainer=this.startContainer;this.endOffset=this.startOffset;}else{this.startContainer=this.endContainer;this.startOffset=this.endOffset;};this.collapsed=true;},selectNodeContents:function(A){this.setStart(A,0);this.setEnd(A,A.nodeType==3?A.data.length:A.childNodes.length);},insertNode:function(A){var B=this.startContainer;var C=this.startOffset;if (B.nodeType==3){B.splitText(C);if (B==this.endContainer) this.setEnd(B.nextSibling,this.endOffset-this.startOffset);FCKDomTools.InsertAfterNode(B,A);return;}else{B.insertBefore(A,B.childNodes[C]||null);if (B==this.endContainer){this.endOffset++;this.collapsed=false;}}},deleteContents:function(){if (this.collapsed) return;this._ExecContentsAction(0);},extractContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(1,A);return A;},cloneContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(2,A);return A;},_ExecContentsAction:function(A,B){var C=this.startContainer;var D=this.endContainer;var E=this.startOffset;var F=this.endOffset;var G=false;var H=false;if (D.nodeType==3) D=D.splitText(F);else{if (D.childNodes.length>0){if (F>D.childNodes.length-1){D=FCKDomTools.InsertAfterNode(D.lastChild,this._Document.createTextNode(''));H=true;}else D=D.childNodes[F];}};if (C.nodeType==3){C.splitText(E);if (C==D) D=C.nextSibling;}else{if (C.childNodes.length>0&&E<=C.childNodes.length-1){if (E==0){C=C.insertBefore(this._Document.createTextNode(''),C.firstChild);G=true;}else C=C.childNodes[E].previousSibling;}};var I=FCKDomTools.GetParents(C);var J=FCKDomTools.GetParents(D);var i,topStart,topEnd;for (i=0;i<I.length;i++){topStart=I[i];topEnd=J[i];if (topStart!=topEnd) break;};var K,levelStartNode,levelClone,currentNode,currentSibling;if (B) K=B.RootNode;for (var j=i;j<I.length;j++){levelStartNode=I[j];if (K&&levelStartNode!=C) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==C));currentNode=levelStartNode.nextSibling;while(currentNode){if (currentNode==J[j]||currentNode==D) break;currentSibling=currentNode.nextSibling;if (A==2) K.appendChild(currentNode.cloneNode(true));else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.appendChild(currentNode);};currentNode=currentSibling;};if (K) K=levelClone;};if (B) K=B.RootNode;for (var k=i;k<J.length;k++){levelStartNode=J[k];if (A>0&&levelStartNode!=D) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==D));if (!I[k]||levelStartNode.parentNode!=I[k].parentNode){currentNode=levelStartNode.previousSibling;while(currentNode){if (currentNode==I[k]||currentNode==C) break;currentSibling=currentNode.previousSibling;if (A==2) K.insertBefore(currentNode.cloneNode(true),K.firstChild);else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.insertBefore(currentNode,K.firstChild);};currentNode=currentSibling;}};if (K) K=levelClone;};if (A==2){var L=this.startContainer;if (L.nodeType==3){L.data+=L.nextSibling.data;L.parentNode.removeChild(L.nextSibling);};var M=this.endContainer;if (M.nodeType==3&&M.nextSibling){M.data+=M.nextSibling.data;M.parentNode.removeChild(M.nextSibling);}}else{if (topStart&&topEnd&&(C.parentNode!=topStart.parentNode||D.parentNode!=topEnd.parentNode)) this.setStart(topEnd.parentNode,FCKDomTools.GetIndexOf(topEnd));this.collapse(true);};if(G) C.parentNode.removeChild(C);if(H&&D.parentNode) D.parentNode.removeChild(D);},cloneRange:function(){return FCKW3CRange.CreateFromRange(this._Document,this);},toString:function(){var A=this.cloneContents();var B=this._Document.createElement('div');A.AppendTo(B);return B.textContent||B.innerText;}};
+var FCKEnterKey=function(A,B,C){this.Window=A;this.EnterMode=B||'p';this.ShiftEnterMode=C||'br';var D=new FCKKeystrokeHandler(false);D._EnterKey=this;D.OnKeystroke=FCKEnterKey_OnKeystroke;D.SetKeystrokes([[13,'Enter'],[SHIFT+13,'ShiftEnter'],[8,'Backspace'],[46,'Delete']]);D.AttachToElement(A.document);};function FCKEnterKey_OnKeystroke(A,B){var C=this._EnterKey;try{switch (B){case 'Enter':return C.DoEnter();break;case 'ShiftEnter':return C.DoShiftEnter();break;case 'Backspace':return C.DoBackspace();break;case 'Delete':return C.DoDelete();}}catch (e){};return false;};FCKEnterKey.prototype.DoEnter=function(A,B){this._HasShift=(B===true);var C=A||this.EnterMode;if (C=='br') return this._ExecuteEnterBr();else return this._ExecuteEnterBlock(C);};FCKEnterKey.prototype.DoShiftEnter=function(){return this.DoEnter(this.ShiftEnterMode,true);};FCKEnterKey.prototype.DoBackspace=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (!B.CheckIsCollapsed()) return false;var C=B.StartBlock;var D=B.EndBlock;if (B.StartBlockLimit==B.EndBlockLimit&&C&&D){if (!B.CheckIsCollapsed()){var E=B.CheckEndOfBlock();B.DeleteContents();if (C!=D){B.SetStart(D,1);B.SetEnd(D,1);};B.Select();A=(C==D);};if (B.CheckStartOfBlock()){var F=B.StartBlock;var G=FCKDomTools.GetPreviousSourceElement(F,true,['BODY',B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,G,F);}else if (FCKBrowserInfo.IsGecko){B.Select();}};B.Release();return A;};FCKEnterKey.prototype._ExecuteBackspace=function(A,B,C){var D=false;if (!B&&C&&C.nodeName.IEquals('LI')&&C.parentNode.parentNode.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};if (B&&B.nodeName.IEquals('LI')){var E=FCKDomTools.GetLastChild(B,['UL','OL']);while (E){B=FCKDomTools.GetLastChild(E,'LI');E=FCKDomTools.GetLastChild(B,['UL','OL']);}};if (B&&C){if (C.nodeName.IEquals('LI')&&!B.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};var F=C.parentNode;var G=B.nodeName.toLowerCase();if (FCKListsLib.EmptyElements[G]!=null||G=='table'){FCKDomTools.RemoveNode(B);D=true;}else{FCKDomTools.RemoveNode(C);while (F.innerHTML.Trim().length==0){var H=F.parentNode;H.removeChild(F);F=H;};FCKDomTools.TrimNode(C);FCKDomTools.TrimNode(B);A.SetStart(B,2);A.Collapse(true);var I=A.CreateBookmark();FCKDomTools.MoveChildren(C,B);A.MoveToBookmark(I);A.Select();D=true;}};return D;};FCKEnterKey.prototype.DoDelete=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (B.CheckIsCollapsed()&&B.CheckEndOfBlock(FCKBrowserInfo.IsGeckoLike)){var C=B.StartBlock;var D=FCKDomTools.GetNextSourceElement(C,true,[B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,C,D);};B.Release();return A;};FCKEnterKey.prototype._ExecuteEnterBlock=function(A,B){var C=B||new FCKDomRange(this.Window);if (!B) C.MoveToSelection();if (C.StartBlockLimit==C.EndBlockLimit){if (!C.StartBlock) this._FixBlock(C,true,A);if (!C.EndBlock) this._FixBlock(C,false,A);var D=C.StartBlock;var E=C.EndBlock;if (!C.CheckIsEmpty()) C.DeleteContents();if (D==E){var F;var G=C.CheckStartOfBlock();var H=C.CheckEndOfBlock();if (G&&!H){F=D.cloneNode(false);if (FCKBrowserInfo.IsGeckoLike) F.innerHTML=GECKO_BOGUS;D.parentNode.insertBefore(F,D);if (FCKBrowserInfo.IsIE){C.MoveToNodeContents(F);C.Select();};C.MoveToElementEditStart(D);}else{if (H){var I=D.tagName.toUpperCase();if (G&&I=='LI'){this._OutdentWithSelection(D,C);C.Release();return true;}else{if ((/^H[1-6]$/).test(I)||this._HasShift) F=this.Window.document.createElement(A);else{F=D.cloneNode(false);this._RecreateEndingTree(D,F);};if (FCKBrowserInfo.IsGeckoLike){F.innerHTML=GECKO_BOGUS;if (G) D.innerHTML=GECKO_BOGUS;}}}else{C.SetEnd(D,2);var J=C.ExtractContents();F=D.cloneNode(false);FCKDomTools.TrimNode(J.RootNode);if (J.RootNode.firstChild.nodeType==1&&J.RootNode.firstChild.tagName.toUpperCase().Equals('UL','OL')) F.innerHTML=GECKO_BOGUS;J.AppendTo(F);if (FCKBrowserInfo.IsGecko){this._AppendBogusBr(D);this._AppendBogusBr(F);}};if (F){FCKDomTools.InsertAfterNode(D,F);C.MoveToElementEditStart(F);if (FCKBrowserInfo.IsGeckoLike) F.scrollIntoView(false);}}}else{C.MoveToElementEditStart(E);};C.Select();};C.Release();return true;};FCKEnterKey.prototype._ExecuteEnterBr=function(A){var B=new FCKDomRange(this.Window);B.MoveToSelection();if (B.StartBlockLimit==B.EndBlockLimit){B.DeleteContents();B.MoveToSelection();var C=B.CheckStartOfBlock();var D=B.CheckEndOfBlock();var E=B.StartBlock?B.StartBlock.tagName.toUpperCase():'';var F=this._HasShift;if (!F&&E=='LI') return this._ExecuteEnterBlock(null,B);if (!F&&D&&(/^H[1-6]$/).test(E)){FCKDebug.Output('BR - Header');FCKDomTools.InsertAfterNode(B.StartBlock,this.Window.document.createElement('br'));if (FCKBrowserInfo.IsGecko) FCKDomTools.InsertAfterNode(B.StartBlock,this.Window.document.createTextNode(''));B.SetStart(B.StartBlock.nextSibling,FCKBrowserInfo.IsIE?3:1);}else{FCKDebug.Output('BR - No Header');var G=this.Window.document.createElement('br');B.InsertNode(G);if (FCKBrowserInfo.IsGecko) FCKDomTools.InsertAfterNode(G,this.Window.document.createTextNode(''));if (D&&FCKBrowserInfo.IsGeckoLike) this._AppendBogusBr(G.parentNode);if (FCKBrowserInfo.IsIE) B.SetStart(G,4);else B.SetStart(G.nextSibling,1);};B.Collapse(true);B.Select();};B.Release();return true;};FCKEnterKey.prototype._FixBlock=function(A,B,C){var D=A.CreateBookmark();A.Collapse(B);A.Expand('block_contents');var E=this.Window.document.createElement(C);A.ExtractContents().AppendTo(E);FCKDomTools.TrimNode(E);A.InsertNode(E);A.MoveToBookmark(D);};FCKEnterKey.prototype._AppendBogusBr=function(A){if (!A) return;var B=FCKTools.GetLastItem(A.getElementsByTagName('br'));if (!B||B.getAttribute('type',2)!='_moz') A.appendChild(FCKTools.CreateBogusBR(this.Window.document));};FCKEnterKey.prototype._RecreateEndingTree=function(A,B){while ((A=A.lastChild)&&A.nodeType==1&&FCKListsLib.InlineChildReqElements[A.nodeName.toLowerCase()]!=null) B=B.insertBefore(A.cloneNode(false),B.firstChild);};FCKEnterKey.prototype._OutdentWithSelection=function(A,B){var C=B.CreateBookmark();FCKListHandler.OutdentListItem(A);B.MoveToBookmark(C);B.Select();}
+var FCKDocumentProcessor={};FCKDocumentProcessor._Items=[];FCKDocumentProcessor.AppendNew=function(){var A={};this._Items.AddItem(A);return A;};FCKDocumentProcessor.Process=function(A){var B,i=0;while((B=this._Items[i++])) B.ProcessDocument(A);};var FCKDocumentProcessor_CreateFakeImage=function(A,B){var C=FCK.EditorDocument.createElement('IMG');C.className=A;C.src=FCKConfig.FullBasePath+'images/spacer.gif';C.setAttribute('_fckfakelement','true',0);C.setAttribute('_fckrealelement',FCKTempBin.AddElement(B),0);return C;};if (FCKBrowserInfo.IsIE||FCKBrowserInfo.IsOpera){var FCKAnchorsProcessor=FCKDocumentProcessor.AppendNew();FCKAnchorsProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('A');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.name.length>0){if (C.innerHTML!==''){if (FCKBrowserInfo.IsIE) C.className+=' FCK__AnchorC';}else{var D=FCKDocumentProcessor_CreateFakeImage('FCK__Anchor',C.cloneNode(true));D.setAttribute('_fckanchor','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}}};var FCKPageBreaksProcessor=FCKDocumentProcessor.AppendNew();FCKPageBreaksProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('DIV');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.style.pageBreakAfter=='always'&&C.childNodes.length==1&&C.childNodes[0].style&&C.childNodes[0].style.display=='none'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',C.cloneNode(true));C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};var FCKFlashProcessor=FCKDocumentProcessor.AppendNew();FCKFlashProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('EMBED');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=C.attributes['type'];if ((C.src&&C.src.EndsWith('.swf',true))||(D&&D.nodeValue=='application/x-shockwave-flash')){var E=C.cloneNode(true);if (FCKBrowserInfo.IsIE){var F=['scale','play','loop','menu','wmode','quality'];for (var G=0;G<F.length;G++){var H=C.getAttribute(F[G]);if (H) E.setAttribute(F[G],H);};E.setAttribute('type',D.nodeValue);};var I=FCKDocumentProcessor_CreateFakeImage('FCK__Flash',E);I.setAttribute('_fckflash','true',0);FCKFlashProcessor.RefreshView(I,C);C.parentNode.insertBefore(I,C);C.parentNode.removeChild(C);}}};FCKFlashProcessor.RefreshView=function(A,B){if (B.getAttribute('width')>0) A.style.width=FCKTools.ConvertHtmlSizeToStyle(B.getAttribute('width'));if (B.getAttribute('height')>0) A.style.height=FCKTools.ConvertHtmlSizeToStyle(B.getAttribute('height'));};FCK.GetRealElement=function(A){var e=FCKTempBin.Elements[A.getAttribute('_fckrealelement')];if (A.getAttribute('_fckflash')){if (A.style.width.length>0) e.width=FCKTools.ConvertStyleSizeToHtml(A.style.width);if (A.style.height.length>0) e.height=FCKTools.ConvertStyleSizeToHtml(A.style.height);};return e;};if (FCKBrowserInfo.IsIE){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('HR');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=A.createElement('hr');D.mergeAttributes(C,true);FCKDomTools.InsertAfterNode(C,D);C.parentNode.removeChild(C);}}};FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('INPUT');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.type=='hidden'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__InputHidden',C.cloneNode(true));D.setAttribute('_fckinputhidden','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}
+var FCKSelection=FCK.Selection={};
+FCKSelection.GetType=function(){this._Type='Text';var A;try { A=FCK.EditorWindow.getSelection();}catch (e) {};if (A&&A.rangeCount==1){var B=A.getRangeAt(0);if (B.startContainer==B.endContainer&&(B.endOffset-B.startOffset)==1&&B.startContainer.nodeType!=Node.TEXT_NODE) this._Type='Control';};return this._Type;};FCKSelection.GetSelectedElement=function(){if (this.GetType()=='Control'){var A=FCK.EditorWindow.getSelection();return A.anchorNode.childNodes[A.anchorOffset];};return null;};FCKSelection.GetParentElement=function(){if (this.GetType()=='Control') return FCKSelection.GetSelectedElement().parentNode;else{var A=FCK.EditorWindow.getSelection();if (A){var B=A.anchorNode;while (B&&B.nodeType!=1) B=B.parentNode;return B;}};return null;};FCKSelection.SelectNode=function(A){var B=FCK.EditorDocument.createRange();B.selectNode(A);var C=FCK.EditorWindow.getSelection();C.removeAllRanges();C.addRange(B);};FCKSelection.Collapse=function(A){var B=FCK.EditorWindow.getSelection();if (A==null||A===true) B.collapseToStart();else B.collapseToEnd();};FCKSelection.HasAncestorNode=function(A){var B=this.GetSelectedElement();if (!B&&FCK.EditorWindow){try { B=FCK.EditorWindow.getSelection().getRangeAt(0).startContainer;}catch(e){}};while (B){if (B.nodeType==1&&B.tagName==A) return true;B=B.parentNode;};return false;};FCKSelection.MoveToAncestorNode=function(A){var B;var C=this.GetSelectedElement();if (!C) C=FCK.EditorWindow.getSelection().getRangeAt(0).startContainer;while (C){if (C.nodeName==A) return C;C=C.parentNode;};return null;};FCKSelection.Delete=function(){var A=FCK.EditorWindow.getSelection();for (var i=0;i<A.rangeCount;i++){A.getRangeAt(i).deleteContents();};return A;};
+var FCKTableHandler={};FCKTableHandler.InsertRow=function(){var A=FCKSelection.MoveToAncestorNode('TR');if (!A) return;var B=A.cloneNode(true);A.parentNode.insertBefore(B,A);FCKTableHandler.ClearRow(A);};FCKTableHandler.DeleteRows=function(A){if (!A) A=FCKSelection.MoveToAncestorNode('TR');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');if (B.rows.length==1){FCKTableHandler.DeleteTable(B);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteTable=function(A){if (!A){A=FCKSelection.GetSelectedElement();if (!A||A.tagName!='TABLE') A=FCKSelection.MoveToAncestorNode('TABLE');};if (!A) return;FCKSelection.SelectNode(A);FCKSelection.Collapse();A.parentNode.removeChild(A);};FCKTableHandler.InsertColumn=function(){var A=FCKSelection.MoveToAncestorNode('TD')||FCKSelection.MoveToAncestorNode('TH');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');var C=A.cellIndex+1;for (var i=0;i<B.rows.length;i++){var D=B.rows[i];if (D.cells.length<C) continue;A=D.cells[C-1].cloneNode(false);if (FCKBrowserInfo.IsGecko) A.innerHTML=GECKO_BOGUS;var E=D.cells[C];if (E) D.insertBefore(A,E);else D.appendChild(A);}};FCKTableHandler.DeleteColumns=function(){var A=FCKSelection.MoveToAncestorNode('TD')||FCKSelection.MoveToAncestorNode('TH');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');var C=A.cellIndex;for (var i=B.rows.length-1;i>=0;i--){var D=B.rows[i];if (C==0&&D.cells.length==1){FCKTableHandler.DeleteRows(D);continue;};if (D.cells[C]) D.removeChild(D.cells[C]);}};FCKTableHandler.InsertCell=function(A){var B=A?A:FCKSelection.MoveToAncestorNode('TD');if (!B) return null;var C=FCK.EditorDocument.createElement('TD');if (FCKBrowserInfo.IsGecko) C.innerHTML=GECKO_BOGUS;if (B.cellIndex==B.parentNode.cells.length-1){B.parentNode.appendChild(C);}else{B.parentNode.insertBefore(C,B.nextSibling);};return C;};FCKTableHandler.DeleteCell=function(A){if (A.parentNode.cells.length==1){FCKTableHandler.DeleteRows(FCKTools.GetElementAscensor(A,'TR'));return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteCells=function(){var A=FCKTableHandler.GetSelectedCells();for (var i=A.length-1;i>=0;i--){FCKTableHandler.DeleteCell(A[i]);}};FCKTableHandler.MergeCells=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length<2) return;if (A[0].parentNode!=A[A.length-1].parentNode) return;var B=isNaN(A[0].colSpan)?1:A[0].colSpan;var C='';var D=FCK.EditorDocument.createDocumentFragment();for (var i=A.length-1;i>=0;i--){var E=A[i];for (var c=E.childNodes.length-1;c>=0;c--){var F=E.removeChild(E.childNodes[c]);if ((F.hasAttribute&&F.hasAttribute('_moz_editor_bogus_node'))||(F.getAttribute&&F.getAttribute('type',2)=='_moz')) continue;D.insertBefore(F,D.firstChild);};if (i>0){B+=isNaN(E.colSpan)?1:E.colSpan;FCKTableHandler.DeleteCell(E);}};A[0].colSpan=B;if (FCKBrowserInfo.IsGecko&&D.childNodes.length==0) A[0].innerHTML=GECKO_BOGUS;else A[0].appendChild(D);};FCKTableHandler.SplitCell=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length!=1) return;var B=this._CreateTableMap(A[0].parentNode.parentNode);var C=FCKTableHandler._GetCellIndexSpan(B,A[0].parentNode.rowIndex,A[0]);var D=this._GetCollumnCells(B,C);for (var i=0;i<D.length;i++){if (D[i]==A[0]){var E=this.InsertCell(A[0]);if (!isNaN(A[0].rowSpan)&&A[0].rowSpan>1) E.rowSpan=A[0].rowSpan;}else{if (isNaN(D[i].colSpan)) D[i].colSpan=2;else D[i].colSpan+=1;}}};FCKTableHandler._GetCellIndexSpan=function(A,B,C){if (A.length<B+1) return null;var D=A[B];for (var c=0;c<D.length;c++){if (D[c]==C) return c;};return null;};FCKTableHandler._GetCollumnCells=function(A,B){var C=[];for (var r=0;r<A.length;r++){var D=A[r][B];if (D&&(C.length==0||C[C.length-1]!=D)) C[C.length]=D;};return C;};FCKTableHandler._CreateTableMap=function(A){var B=A.rows;var r=-1;var C=[];for (var i=0;i<B.length;i++){r++;if (!C[r]) C[r]=[];var c=-1;for (var j=0;j<B[i].cells.length;j++){var D=B[i].cells[j];c++;while (C[r][c]) c++;var E=isNaN(D.colSpan)?1:D.colSpan;var F=isNaN(D.rowSpan)?1:D.rowSpan;for (var G=0;G<F;G++){if (!C[r+G]) C[r+G]=[];for (var H=0;H<E;H++){C[r+G][c+H]=B[i].cells[j];}};c+=E-1;}};return C;};FCKTableHandler.ClearRow=function(A){var B=A.cells;for (var i=0;i<B.length;i++){if (FCKBrowserInfo.IsGecko) B[i].innerHTML=GECKO_BOGUS;else B[i].innerHTML='';}};
+FCKTableHandler.GetSelectedCells=function(){var A=[];var B=FCK.EditorWindow.getSelection();if (B.rangeCount==1&&B.anchorNode.nodeType==3){var C=FCKTools.GetElementAscensor(B.anchorNode,'TD,TH');if (C){A[0]=C;return A;}};for (var i=0;i<B.rangeCount;i++){var D=B.getRangeAt(i);var E;if (D.startContainer.tagName.Equals('TD','TH')) E=D.startContainer;else E=D.startContainer.childNodes[D.startOffset];if (E.tagName.Equals('TD','TH')) A[A.length]=E;};return A;};
+var FCKXml=function(){};FCKXml.prototype.LoadUrl=function(A){this.Error=false;var B=this;var C=FCKTools.CreateXmlObject('XmlHttp');C.open("GET",A,false);C.send(null);if (C.status==200||C.status==304) this.DOMDocument=C.responseXML;else if (C.status==0&&C.readyState==4) this.DOMDocument=C.responseXML;else this.DOMDocument=null;if (this.DOMDocument==null||this.DOMDocument.firstChild==null){this.Error=true;if (window.confirm('Error loading "'+A+'"\r\nDo you want to see more info?')) alert('URL requested: "'+A+'"\r\nServer response:\r\nStatus: '+C.status+'\r\nResponse text:\r\n'+C.responseText);}};FCKXml.prototype.SelectNodes=function(A,B){if (this.Error) return [];var C=[];var D=this.DOMDocument.evaluate(A,B?B:this.DOMDocument,this.DOMDocument.createNSResolver(this.DOMDocument.documentElement),XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);if (D){var E=D.iterateNext();while(E){C[C.length]=E;E=D.iterateNext();}};return C;};FCKXml.prototype.SelectSingleNode=function(A,B){if (this.Error) return null;var C=this.DOMDocument.evaluate(A,B?B:this.DOMDocument,this.DOMDocument.createNSResolver(this.DOMDocument.documentElement),9,null);if (C&&C.singleNodeValue) return C.singleNodeValue;else return null;}
+var FCKStyleDef=function(A,B){this.Name=A;this.Element=B.toUpperCase();this.IsObjectElement=FCKRegexLib.ObjectElements.test(this.Element);this.Attributes={};};FCKStyleDef.prototype.AddAttribute=function(A,B){this.Attributes[A]=B;};FCKStyleDef.prototype.GetOpenerTag=function(){var s='<'+this.Element;for (var a in this.Attributes) s+=' '+a+'="'+this.Attributes[a]+'"';return s+'>';};FCKStyleDef.prototype.GetCloserTag=function(){return '</'+this.Element+'>';};FCKStyleDef.prototype.RemoveFromSelection=function(){if (FCKSelection.GetType()=='Control') this._RemoveMe(FCK.ToolbarSet.CurrentInstance.Selection.GetSelectedElement());else this._RemoveMe(FCK.ToolbarSet.CurrentInstance.Selection.GetParentElement());}
+FCKStyleDef.prototype.ApplyToSelection=function(){if (FCKSelection.GetType()=='Text'&&!this.IsObjectElement){var A=FCK.ToolbarSet.CurrentInstance.EditorWindow.getSelection();var e=FCK.ToolbarSet.CurrentInstance.EditorDocument.createElement(this.Element);for (var i=0;i<A.rangeCount;i++){e.appendChild(A.getRangeAt(i).extractContents());};this._AddAttributes(e);this._RemoveDuplicates(e);var B=A.getRangeAt(0);B.insertNode(e);}else{var C=FCK.ToolbarSet.CurrentInstance.Selection.GetSelectedElement();if (C.tagName==this.Element) this._AddAttributes(C);}};FCKStyleDef.prototype._AddAttributes=function(A){for (var a in this.Attributes){switch (a.toLowerCase()){case 'src':A.setAttribute('_fcksavedurl',this.Attributes[a],0);default:A.setAttribute(a,this.Attributes[a],0);}}};FCKStyleDef.prototype._RemoveDuplicates=function(A){for (var i=0;i<A.childNodes.length;i++){var B=A.childNodes[i];if (B.nodeType!=1) continue;this._RemoveDuplicates(B);if (this.IsEqual(B)) FCKTools.RemoveOuterTags(B);}};FCKStyleDef.prototype.IsEqual=function(e){if (e.tagName!=this.Element) return false;for (var a in this.Attributes){if (e.getAttribute(a)!=this.Attributes[a]) return false;};return true;};FCKStyleDef.prototype._RemoveMe=function(A){if (!A) return;var B=A.parentNode;if (A.nodeType==1&&this.IsEqual(A)){if (this.IsObjectElement){for (var a in this.Attributes) A.removeAttribute(a,0);return;}else FCKTools.RemoveOuterTags(A);};this._RemoveMe(B);}
+var FCKStylesLoader=function(){this.Styles={};this.StyleGroups={};this.Loaded=false;this.HasObjectElements=false;};FCKStylesLoader.prototype.Load=function(A){var B=new FCKXml();B.LoadUrl(A);var C=B.SelectNodes('Styles/Style');for (var i=0;i<C.length;i++){var D=C[i].attributes.getNamedItem('element').value.toUpperCase();var E=new FCKStyleDef(C[i].attributes.getNamedItem('name').value,D);if (E.IsObjectElement) this.HasObjectElements=true;var F=B.SelectNodes('Attribute',C[i]);for (var j=0;j<F.length;j++){var G=F[j].attributes.getNamedItem('name').value;var H=F[j].attributes.getNamedItem('value').value;if (G.toLowerCase()=='style'){var I=document.createElement('SPAN');I.style.cssText=H;H=I.style.cssText;};E.AddAttribute(G,H);};this.Styles[E.Name]=E;var J=this.StyleGroups[D];if (J==null){this.StyleGroups[D]=[];J=this.StyleGroups[D];};J[J.length]=E;};this.Loaded=true;}
+var FCKNamedCommand=function(A){this.Name=A;};FCKNamedCommand.prototype.Execute=function(){FCK.ExecuteNamedCommand(this.Name);};FCKNamedCommand.prototype.GetState=function(){return FCK.GetNamedCommandState(this.Name);};
+var FCKDialogCommand=function(A,B,C,D,E,F,G){this.Name=A;this.Title=B;this.Url=C;this.Width=D;this.Height=E;this.GetStateFunction=F;this.GetStateParam=G;this.Resizable=false;};FCKDialogCommand.prototype.Execute=function(){FCKDialog.OpenDialog('FCKDialog_'+this.Name,this.Title,this.Url,this.Width,this.Height,null,null,this.Resizable);};FCKDialogCommand.prototype.GetState=function(){if (this.GetStateFunction) return this.GetStateFunction(this.GetStateParam);else return 0;};var FCKUndefinedCommand=function(){this.Name='Undefined';};FCKUndefinedCommand.prototype.Execute=function(){alert(FCKLang.NotImplemented);};FCKUndefinedCommand.prototype.GetState=function(){return 0;};var FCKFontNameCommand=function(){this.Name='FontName';};FCKFontNameCommand.prototype.Execute=function(A){if (A==null||A==""){}else FCK.ExecuteNamedCommand('FontName',A);};FCKFontNameCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FontName');};var FCKFontSizeCommand=function(){this.Name='FontSize';};FCKFontSizeCommand.prototype.Execute=function(A){if (typeof(A)=='string') A=parseInt(A,10);if (A==null||A==''){FCK.ExecuteNamedCommand('FontSize',3);}else FCK.ExecuteNamedCommand('FontSize',A);};FCKFontSizeCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FontSize');};var FCKFormatBlockCommand=function(){this.Name='FormatBlock';};FCKFormatBlockCommand.prototype.Execute=function(A){if (A==null||A=='') FCK.ExecuteNamedCommand('FormatBlock','<P>');else if (A=='div'&&FCKBrowserInfo.IsGecko) FCK.ExecuteNamedCommand('FormatBlock','div');else FCK.ExecuteNamedCommand('FormatBlock','<'+A+'>');};FCKFormatBlockCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FormatBlock');};var FCKPreviewCommand=function(){this.Name='Preview';};FCKPreviewCommand.prototype.Execute=function(){FCK.Preview();};FCKPreviewCommand.prototype.GetState=function(){return 0;};var FCKSaveCommand=function(){this.Name='Save';};FCKSaveCommand.prototype.Execute=function(){var A=FCK.GetParentForm();if (typeof(A.onsubmit)=='function'){var B=A.onsubmit();if (B!=null&&B===false) return;};if (typeof(A.submit)=='function') A.submit();else A.submit.click();};FCKSaveCommand.prototype.GetState=function(){return 0;};var FCKNewPageCommand=function(){this.Name='NewPage';};FCKNewPageCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();FCK.SetHTML('');FCKUndo.Typing=true;};FCKNewPageCommand.prototype.GetState=function(){return 0;};var FCKSourceCommand=function(){this.Name='Source';};FCKSourceCommand.prototype.Execute=function(){if (FCKConfig.SourcePopup){var A=FCKConfig.ScreenWidth*0.65;var B=FCKConfig.ScreenHeight*0.65;FCKDialog.OpenDialog('FCKDialog_Source',FCKLang.Source,'dialog/fck_source.html',A,B,null,null,true);}else FCK.SwitchEditMode();};FCKSourceCommand.prototype.GetState=function(){return (FCK.EditMode==0?0:1);};var FCKUndoCommand=function(){this.Name='Undo';};FCKUndoCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsIE) FCKUndo.Undo();else FCK.ExecuteNamedCommand('Undo');};FCKUndoCommand.prototype.GetState=function(){if (FCKBrowserInfo.IsIE) return (FCKUndo.CheckUndoState()?0:-1);else return FCK.GetNamedCommandState('Undo');};var FCKRedoCommand=function(){this.Name='Redo';};FCKRedoCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsIE) FCKUndo.Redo();else FCK.ExecuteNamedCommand('Redo');};FCKRedoCommand.prototype.GetState=function(){if (FCKBrowserInfo.IsIE) return (FCKUndo.CheckRedoState()?0:-1);else return FCK.GetNamedCommandState('Redo');};var FCKPageBreakCommand=function(){this.Name='PageBreak';};FCKPageBreakCommand.prototype.Execute=function(){var e=FCK.EditorDocument.createElement('DIV');e.style.pageBreakAfter='always';e.innerHTML='<span style="DISPLAY:none">&nbsp;</span>';var A=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',e);A=FCK.InsertElement(A);};FCKPageBreakCommand.prototype.GetState=function(){return 0;};var FCKUnlinkCommand=function(){this.Name='Unlink';};FCKUnlinkCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsGecko){var A=FCK.Selection.MoveToAncestorNode('A');if (A) FCKTools.RemoveOuterTags(A);return;};FCK.ExecuteNamedCommand(this.Name);};FCKUnlinkCommand.prototype.GetState=function(){var A=FCK.GetNamedCommandState(this.Name);if (A==0&&FCK.EditMode==0){var B=FCKSelection.MoveToAncestorNode('A');var C=(B&&B.name.length>0&&B.href.length==0);if (C) A=-1;};return A;};var FCKSelectAllCommand=function(){this.Name='SelectAll';};FCKSelectAllCommand.prototype.Execute=function(){if (FCK.EditMode==0){FCK.ExecuteNamedCommand('SelectAll');}else{var A=FCK.EditingArea.Textarea;if (FCKBrowserInfo.IsIE){A.createTextRange().execCommand('SelectAll');}else{A.selectionStart=0;A.selectionEnd=A.value.length;};A.focus();}};FCKSelectAllCommand.prototype.GetState=function(){return 0;};var FCKPasteCommand=function(){this.Name='Paste';};FCKPasteCommand.prototype={Execute:function(){if (FCKBrowserInfo.IsIE) FCK.Paste();else FCK.ExecuteNamedCommand('Paste');},GetState:function(){return FCK.GetNamedCommandState('Paste');}};
+var FCKSpellCheckCommand=function(){this.Name='SpellCheck';this.IsEnabled=(FCKConfig.SpellChecker=='SpellerPages');};FCKSpellCheckCommand.prototype.Execute=function(){FCKDialog.OpenDialog('FCKDialog_SpellCheck','Spell Check','dialog/fck_spellerpages.html',440,480);};FCKSpellCheckCommand.prototype.GetState=function(){return this.IsEnabled?0:-1;}
+var FCKTextColorCommand=function(A){this.Name=A=='ForeColor'?'TextColor':'BGColor';this.Type=A;var B;if (FCKBrowserInfo.IsIE) B=window;else if (FCK.ToolbarSet._IFrame) B=FCKTools.GetElementWindow(FCK.ToolbarSet._IFrame);else B=window.parent;this._Panel=new FCKPanel(B);this._Panel.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');this._Panel.MainNode.className='FCK_Panel';this._CreatePanelBody(this._Panel.Document,this._Panel.MainNode);FCKTools.DisableSelection(this._Panel.Document.body);};FCKTextColorCommand.prototype.Execute=function(A,B,C){FCK._ActiveColorPanelType=this.Type;this._Panel.Show(A,B,C);};FCKTextColorCommand.prototype.SetColor=function(A){if (FCK._ActiveColorPanelType=='ForeColor') FCK.ExecuteNamedCommand('ForeColor',A);else if (FCKBrowserInfo.IsGeckoLike){if (FCKBrowserInfo.IsGecko&&!FCKConfig.GeckoUseSPAN) FCK.EditorDocument.execCommand('useCSS',false,false);FCK.ExecuteNamedCommand('hilitecolor',A);if (FCKBrowserInfo.IsGecko&&!FCKConfig.GeckoUseSPAN) FCK.EditorDocument.execCommand('useCSS',false,true);}else FCK.ExecuteNamedCommand('BackColor',A);delete FCK._ActiveColorPanelType;};FCKTextColorCommand.prototype.GetState=function(){return 0;};function FCKTextColorCommand_OnMouseOver() { this.className='ColorSelected';};function FCKTextColorCommand_OnMouseOut() { this.className='ColorDeselected';};function FCKTextColorCommand_OnClick(){this.className='ColorDeselected';this.Command.SetColor('#'+this.Color);this.Command._Panel.Hide();};function FCKTextColorCommand_AutoOnClick(){this.className='ColorDeselected';this.Command.SetColor('');this.Command._Panel.Hide();};function FCKTextColorCommand_MoreOnClick(){this.className='ColorDeselected';this.Command._Panel.Hide();FCKDialog.OpenDialog('FCKDialog_Color',FCKLang.DlgColorTitle,'dialog/fck_colorselector.html',400,330,this.Command.SetColor);};FCKTextColorCommand.prototype._CreatePanelBody=function(A,B){function CreateSelectionDiv(){var C=A.createElement("DIV");C.className='ColorDeselected';C.onmouseover=FCKTextColorCommand_OnMouseOver;C.onmouseout=FCKTextColorCommand_OnMouseOut;return C;};var D=B.appendChild(A.createElement("TABLE"));D.className='ForceBaseFont';D.style.tableLayout='fixed';D.cellPadding=0;D.cellSpacing=0;D.border=0;D.width=150;var E=D.insertRow(-1).insertCell(-1);E.colSpan=8;var C=E.appendChild(CreateSelectionDiv());C.innerHTML='<table cellspacing="0" cellpadding="0" width="100%" border="0">\n <tr>\n <td><div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #000000"></div></div></td>\n <td nowrap width="100%" align="center">'+FCKLang.ColorAutomatic+'</td>\n </tr>\n </table>';C.Command=this;C.onclick=FCKTextColorCommand_AutoOnClick;var G=FCKConfig.FontColors.toString().split(',');var H=0;while (H<G.length){var I=D.insertRow(-1);for (var i=0;i<8&&H<G.length;i++,H++){C=I.insertCell(-1).appendChild(CreateSelectionDiv());C.Color=G[H];C.innerHTML='<div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #'+G[H]+'"></div></div>';C.Command=this;C.onclick=FCKTextColorCommand_OnClick;}};E=D.insertRow(-1).insertCell(-1);E.colSpan=8;C=E.appendChild(CreateSelectionDiv());C.innerHTML='<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td nowrap align="center">'+FCKLang.ColorMoreColors+'</td></tr></table>';C.Command=this;C.onclick=FCKTextColorCommand_MoreOnClick;}
+var FCKPastePlainTextCommand=function(){this.Name='PasteText';};FCKPastePlainTextCommand.prototype.Execute=function(){FCK.PasteAsPlainText();};FCKPastePlainTextCommand.prototype.GetState=function(){return FCK.GetNamedCommandState('Paste');};
+var FCKPasteWordCommand=function(){this.Name='PasteWord';};FCKPasteWordCommand.prototype.Execute=function(){FCK.PasteFromWord();};FCKPasteWordCommand.prototype.GetState=function(){if (FCKConfig.ForcePasteAsPlainText) return -1;else return FCK.GetNamedCommandState('Paste');};
+var FCKTableCommand=function(A){this.Name=A;};FCKTableCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();switch (this.Name){case 'TableInsertRow':FCKTableHandler.InsertRow();break;case 'TableDeleteRows':FCKTableHandler.DeleteRows();break;case 'TableInsertColumn':FCKTableHandler.InsertColumn();break;case 'TableDeleteColumns':FCKTableHandler.DeleteColumns();break;case 'TableInsertCell':FCKTableHandler.InsertCell();break;case 'TableDeleteCells':FCKTableHandler.DeleteCells();break;case 'TableMergeCells':FCKTableHandler.MergeCells();break;case 'TableSplitCell':FCKTableHandler.SplitCell();break;case 'TableDelete':FCKTableHandler.DeleteTable();break;default:alert(FCKLang.UnknownCommand.replace(/%1/g,this.Name));}};FCKTableCommand.prototype.GetState=function(){return 0;}
+var FCKStyleCommand=function(){this.Name='Style';this.StylesLoader=new FCKStylesLoader();this.StylesLoader.Load(FCKConfig.StylesXmlPath);this.Styles=this.StylesLoader.Styles;};FCKStyleCommand.prototype.Execute=function(A,B){FCKUndo.SaveUndoStep();if (B.Selected) B.Style.RemoveFromSelection();else B.Style.ApplyToSelection();FCKUndo.SaveUndoStep();FCK.Focus();FCK.Events.FireEvent("OnSelectionChange");};FCKStyleCommand.prototype.GetState=function(){if (!FCK.EditorDocument) return -1;var A=FCK.EditorDocument.selection;if (FCKSelection.GetType()=='Control'){var e=FCKSelection.GetSelectedElement();if (e) return this.StylesLoader.StyleGroups[e.tagName]?0:-1;};return 0;};FCKStyleCommand.prototype.GetActiveStyles=function(){var A=[];if (FCKSelection.GetType()=='Control') this._CheckStyle(FCKSelection.GetSelectedElement(),A,false);else this._CheckStyle(FCKSelection.GetParentElement(),A,true);return A;};FCKStyleCommand.prototype._CheckStyle=function(A,B,C){if (!A) return;if (A.nodeType==1){var D=this.StylesLoader.StyleGroups[A.tagName];if (D){for (var i=0;i<D.length;i++){if (D[i].IsEqual(A)) B[B.length]=D[i];}}};if (C) this._CheckStyle(A.parentNode,B,C);}
+var FCKFitWindow=function(){this.Name='FitWindow';};FCKFitWindow.prototype.Execute=function(){var A=window.frameElement;var B=A.style;var C=parent;var D=C.document.documentElement;var E=C.document.body;var F=E.style;var G;if (!this.IsMaximized){if(FCKBrowserInfo.IsIE) C.attachEvent('onresize',FCKFitWindow_Resize);else C.addEventListener('resize',FCKFitWindow_Resize,true);this._ScrollPos=FCKTools.GetScrollPosition(C);G=A;while((G=G.parentNode)){if (G.nodeType==1) G._fckSavedStyles=FCKTools.SaveStyles(G);};if (FCKBrowserInfo.IsIE){this.documentElementOverflow=D.style.overflow;D.style.overflow='hidden';F.overflow='hidden';}else{F.overflow='hidden';F.width='0px';F.height='0px';};this._EditorFrameStyles=FCKTools.SaveStyles(A);var H=FCKTools.GetViewPaneSize(C);B.position="absolute";B.zIndex=FCKConfig.FloatingPanelsZIndex-1;B.left="0px";B.top="0px";B.width=H.Width+"px";B.height=H.Height+"px";if (!FCKBrowserInfo.IsIE){B.borderRight=B.borderBottom="9999px solid white";B.backgroundColor="white";};C.scrollTo(0,0);this.IsMaximized=true;}else{if(FCKBrowserInfo.IsIE) C.detachEvent("onresize",FCKFitWindow_Resize);else C.removeEventListener("resize",FCKFitWindow_Resize,true);G=A;while((G=G.parentNode)){if (G._fckSavedStyles){FCKTools.RestoreStyles(G,G._fckSavedStyles);G._fckSavedStyles=null;}};if (FCKBrowserInfo.IsIE) D.style.overflow=this.documentElementOverflow;FCKTools.RestoreStyles(A,this._EditorFrameStyles);C.scrollTo(this._ScrollPos.X,this._ScrollPos.Y);this.IsMaximized=false;};FCKToolbarItems.GetItem('FitWindow').RefreshState();FCK.EditingArea.MakeEditable();FCK.Focus();};FCKFitWindow.prototype.GetState=function(){if (FCKConfig.ToolbarLocation!='In') return -1;else return (this.IsMaximized?1:0);};function FCKFitWindow_Resize(){var A=FCKTools.GetViewPaneSize(parent);var B=window.frameElement.style;B.width=A.Width+'px';B.height=A.Height+'px';};
+var FCKCommands=FCK.Commands={};FCKCommands.LoadedCommands={};FCKCommands.RegisterCommand=function(A,B){this.LoadedCommands[A]=B;};FCKCommands.GetCommand=function(A){var B=FCKCommands.LoadedCommands[A];if (B) return B;switch (A){case 'DocProps':B=new FCKDialogCommand('DocProps',FCKLang.DocProps,'dialog/fck_docprops.html',400,390,FCKCommands.GetFullPageState);break;case 'Templates':B=new FCKDialogCommand('Templates',FCKLang.DlgTemplatesTitle,'dialog/fck_template.html',380,450);break;case 'Link':B=new FCKDialogCommand('Link',FCKLang.DlgLnkWindowTitle,'dialog/fck_link.html',400,330);break;case 'Unlink':B=new FCKUnlinkCommand();break;case 'Anchor':B=new FCKDialogCommand('Anchor',FCKLang.DlgAnchorTitle,'dialog/fck_anchor.html',370,170);break;case 'BulletedList':B=new FCKDialogCommand('BulletedList',FCKLang.BulletedListProp,'dialog/fck_listprop.html?UL',370,170);break;case 'NumberedList':B=new FCKDialogCommand('NumberedList',FCKLang.NumberedListProp,'dialog/fck_listprop.html?OL',370,170);break;case 'About':B=new FCKDialogCommand('About',FCKLang.About,'dialog/fck_about.html',400,330);break;case 'Find':B=new FCKDialogCommand('Find',FCKLang.DlgFindTitle,'dialog/fck_find.html',340,170);break;case 'Replace':B=new FCKDialogCommand('Replace',FCKLang.DlgReplaceTitle,'dialog/fck_replace.html',340,200);break;case 'Image':B=new FCKDialogCommand('Image',FCKLang.DlgImgTitle,'dialog/fck_image.html',450,400);break;case 'Flash':B=new FCKDialogCommand('Flash',FCKLang.DlgFlashTitle,'dialog/fck_flash.html',450,400);break;case 'SpecialChar':B=new FCKDialogCommand('SpecialChar',FCKLang.DlgSpecialCharTitle,'dialog/fck_specialchar.html',400,320);break;case 'Smiley':B=new FCKDialogCommand('Smiley',FCKLang.DlgSmileyTitle,'dialog/fck_smiley.html',FCKConfig.SmileyWindowWidth,FCKConfig.SmileyWindowHeight);break;case 'Table':B=new FCKDialogCommand('Table',FCKLang.DlgTableTitle,'dialog/fck_table.html',450,250);break;case 'TableProp':B=new FCKDialogCommand('Table',FCKLang.DlgTableTitle,'dialog/fck_table.html?Parent',400,250);break;case 'TableCellProp':B=new FCKDialogCommand('TableCell',FCKLang.DlgCellTitle,'dialog/fck_tablecell.html',550,250);break;case 'Style':B=new FCKStyleCommand();break;case 'FontName':B=new FCKFontNameCommand();break;case 'FontSize':B=new FCKFontSizeCommand();break;case 'FontFormat':B=new FCKFormatBlockCommand();break;case 'Source':B=new FCKSourceCommand();break;case 'Preview':B=new FCKPreviewCommand();break;case 'Save':B=new FCKSaveCommand();break;case 'NewPage':B=new FCKNewPageCommand();break;case 'PageBreak':B=new FCKPageBreakCommand();break;case 'TextColor':B=new FCKTextColorCommand('ForeColor');break;case 'BGColor':B=new FCKTextColorCommand('BackColor');break;case 'Paste':B=new FCKPasteCommand();break;case 'PasteText':B=new FCKPastePlainTextCommand();break;case 'PasteWord':B=new FCKPasteWordCommand();break;case 'TableInsertRow':B=new FCKTableCommand('TableInsertRow');break;case 'TableDeleteRows':B=new FCKTableCommand('TableDeleteRows');break;case 'TableInsertColumn':B=new FCKTableCommand('TableInsertColumn');break;case 'TableDeleteColumns':B=new FCKTableCommand('TableDeleteColumns');break;case 'TableInsertCell':B=new FCKTableCommand('TableInsertCell');break;case 'TableDeleteCells':B=new FCKTableCommand('TableDeleteCells');break;case 'TableMergeCells':B=new FCKTableCommand('TableMergeCells');break;case 'TableSplitCell':B=new FCKTableCommand('TableSplitCell');break;case 'TableDelete':B=new FCKTableCommand('TableDelete');break;case 'Form':B=new FCKDialogCommand('Form',FCKLang.Form,'dialog/fck_form.html',380,230);break;case 'Checkbox':B=new FCKDialogCommand('Checkbox',FCKLang.Checkbox,'dialog/fck_checkbox.html',380,230);break;case 'Radio':B=new FCKDialogCommand('Radio',FCKLang.RadioButton,'dialog/fck_radiobutton.html',380,230);break;case 'TextField':B=new FCKDialogCommand('TextField',FCKLang.TextField,'dialog/fck_textfield.html',380,230);break;case 'Textarea':B=new FCKDialogCommand('Textarea',FCKLang.Textarea,'dialog/fck_textarea.html',380,230);break;case 'HiddenField':B=new FCKDialogCommand('HiddenField',FCKLang.HiddenField,'dialog/fck_hiddenfield.html',380,230);break;case 'Button':B=new FCKDialogCommand('Button',FCKLang.Button,'dialog/fck_button.html',380,230);break;case 'Select':B=new FCKDialogCommand('Select',FCKLang.SelectionField,'dialog/fck_select.html',400,380);break;case 'ImageButton':B=new FCKDialogCommand('ImageButton',FCKLang.ImageButton,'dialog/fck_image.html?ImageButton',450,400);break;case 'SpellCheck':B=new FCKSpellCheckCommand();break;case 'FitWindow':B=new FCKFitWindow();break;case 'Undo':B=new FCKUndoCommand();break;case 'Redo':B=new FCKRedoCommand();break;case 'SelectAll':B=new FCKSelectAllCommand();break;case 'Undefined':B=new FCKUndefinedCommand();break;default:if (FCKRegexLib.NamedCommands.test(A)) B=new FCKNamedCommand(A);else{alert(FCKLang.UnknownCommand.replace(/%1/g,A));return null;}};FCKCommands.LoadedCommands[A]=B;return B;};FCKCommands.GetFullPageState=function(){return FCKConfig.FullPage?0:-1;};
+var FCKPanel=function(A){this.IsRTL=(FCKLang.Dir=='rtl');this.IsContextMenu=false;this._LockCounter=0;this._Window=A||window;var B;if (FCKBrowserInfo.IsIE){this._Popup=this._Window.createPopup();B=this.Document=this._Popup.document;FCK.IECleanup.AddItem(this,FCKPanel_Cleanup);}else{var C=this._IFrame=this._Window.document.createElement('iframe');C.src='javascript:void(0)';C.allowTransparency=true;C.frameBorder='0';C.scrolling='no';C.style.position='absolute';C.style.zIndex=FCKConfig.FloatingPanelsZIndex;C.width=C.height=0;if (this._Window==window.parent&&window.frameElement) window.frameElement.parentNode.insertBefore(C,window.frameElement);else this._Window.document.body.appendChild(C);var D=C.contentWindow;B=this.Document=D.document;var E='';if (FCKBrowserInfo.IsSafari) E='<base href="'+window.document.location+'">';B.open();B.write('<html><head>'+E+'<\/head><body style="margin:0px;padding:0px;"><\/body><\/html>');B.close();FCKTools.AddEventListenerEx(D,'focus',FCKPanel_Window_OnFocus,this);FCKTools.AddEventListenerEx(D,'blur',FCKPanel_Window_OnBlur,this);};B.dir=FCKLang.Dir;B.oncontextmenu=FCKTools.CancelEvent;this.MainNode=B.body.appendChild(B.createElement('DIV'));this.MainNode.style.cssFloat=this.IsRTL?'right':'left';};FCKPanel.prototype.AppendStyleSheet=function(A){FCKTools.AppendStyleSheet(this.Document,A);};FCKPanel.prototype.Preload=function(x,y,A){if (this._Popup) this._Popup.show(x,y,0,0,A);};FCKPanel.prototype.Show=function(x,y,A,B,C){var D;if (this._Popup){this._Popup.show(x,y,0,0,A);this.MainNode.style.width=B?B+'px':'';this.MainNode.style.height=C?C+'px':'';D=this.MainNode.offsetWidth;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=(x*-1)+A.offsetWidth-D;};this._Popup.show(x,y,D,this.MainNode.offsetHeight,A);if (this.OnHide){if (this._Timer) CheckPopupOnHide.call(this,true);this._Timer=FCKTools.SetInterval(CheckPopupOnHide,100,this);}}else{if (typeof(FCKFocusManager)!='undefined') FCKFocusManager.Lock();if (this.ParentPanel) this.ParentPanel.Lock();this.MainNode.style.width=B?B+'px':'';this.MainNode.style.height=C?C+'px':'';D=this.MainNode.offsetWidth;if (!B) this._IFrame.width=1;if (!C) this._IFrame.height=1;D=this.MainNode.offsetWidth;var E=FCKTools.GetElementPosition(A.nodeType==9?(FCKTools.IsStrictMode(A)?A.documentElement:A.body):A,this._Window);if (this.IsRTL&&!this.IsContextMenu) x=(x*-1);x+=E.X;y+=E.Y;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=x+A.offsetWidth-D;}else{var F=FCKTools.GetViewPaneSize(this._Window);var G=FCKTools.GetScrollPosition(this._Window);var H=F.Height+G.Y;var I=F.Width+G.X;if ((x+D)>I) x-=x+D-I;if ((y+this.MainNode.offsetHeight)>H) y-=y+this.MainNode.offsetHeight-H;};if (x<0) x=0;this._IFrame.style.left=x+'px';this._IFrame.style.top=y+'px';var J=D;var K=this.MainNode.offsetHeight;this._IFrame.width=J;this._IFrame.height=K;this._IFrame.contentWindow.focus();};this._IsOpened=true;FCKTools.RunFunction(this.OnShow,this);};FCKPanel.prototype.Hide=function(A){if (this._Popup) this._Popup.hide();else{if (!this._IsOpened) return;if (typeof(FCKFocusManager)!='undefined') FCKFocusManager.Unlock();this._IFrame.width=this._IFrame.height=0;this._IsOpened=false;if (this.ParentPanel) this.ParentPanel.Unlock();if (!A) FCKTools.RunFunction(this.OnHide,this);}};FCKPanel.prototype.CheckIsOpened=function(){if (this._Popup) return this._Popup.isOpen;else return this._IsOpened;};FCKPanel.prototype.CreateChildPanel=function(){var A=this._Popup?FCKTools.GetDocumentWindow(this.Document):this._Window;var B=new FCKPanel(A);B.ParentPanel=this;return B;};FCKPanel.prototype.Lock=function(){this._LockCounter++;};FCKPanel.prototype.Unlock=function(){if (--this._LockCounter==0&&!this.HasFocus) this.Hide();};function FCKPanel_Window_OnFocus(e,A){A.HasFocus=true;};function FCKPanel_Window_OnBlur(e,A){A.HasFocus=false;if (A._LockCounter==0) FCKTools.RunFunction(A.Hide,A);};function CheckPopupOnHide(A){if (A||!this._Popup.isOpen){window.clearInterval(this._Timer);this._Timer=null;FCKTools.RunFunction(this.OnHide,this);}};function FCKPanel_Cleanup(){this._Popup=null;this._Window=null;this.Document=null;this.MainNode=null;}
+var FCKIcon=function(A){var B=A?typeof(A):'undefined';switch (B){case 'number':this.Path=FCKConfig.SkinPath+'fck_strip.gif';this.Size=16;this.Position=A;break;case 'undefined':this.Path=FCK_SPACER_PATH;break;case 'string':this.Path=A;break;default:this.Path=A[0];this.Size=A[1];this.Position=A[2];}};FCKIcon.prototype.CreateIconElement=function(A){var B,eIconImage;if (this.Position){var C='-'+((this.Position-1)*this.Size)+'px';if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path;eIconImage.style.top=C;}else{B=A.createElement('IMG');B.src=FCK_SPACER_PATH;B.style.backgroundPosition='0px '+C;B.style.backgroundImage='url('+this.Path+')';}}else{if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path?this.Path:FCK_SPACER_PATH;}else{B=A.createElement('IMG');B.src=this.Path?this.Path:FCK_SPACER_PATH;}};B.className='TB_Button_Image';return B;}
+var FCKToolbarButtonUI=function(A,B,C,D,E,F){this.Name=A;this.Label=B||A;this.Tooltip=C||this.Label;this.Style=E||0;this.State=F||0;this.Icon=new FCKIcon(D);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarButtonUI_Cleanup);};FCKToolbarButtonUI.prototype._CreatePaddingElement=function(A){var B=A.createElement('IMG');B.className='TB_Button_Padding';B.src=FCK_SPACER_PATH;return B;};FCKToolbarButtonUI.prototype.Create=function(A){var B=this.MainElement;if (B){FCKToolbarButtonUI_Cleanup.call(this);if (B.parentNode) B.parentNode.removeChild(B);B=this.MainElement=null;};var C=FCKTools.GetElementDocument(A);B=this.MainElement=C.createElement('DIV');B._FCKButton=this;B.title=this.Tooltip;if (FCKBrowserInfo.IsGecko) B.onmousedown=FCKTools.CancelEvent;this.ChangeState(this.State,true);if (this.Style==0&&!this.ShowArrow){B.appendChild(this.Icon.CreateIconElement(C));}else{var D=B.appendChild(C.createElement('TABLE'));D.cellPadding=0;D.cellSpacing=0;var E=D.insertRow(-1);var F=E.insertCell(-1);if (this.Style==0||this.Style==2) F.appendChild(this.Icon.CreateIconElement(C));else F.appendChild(this._CreatePaddingElement(C));if (this.Style==1||this.Style==2){F=E.insertCell(-1);F.className='TB_Button_Text';F.noWrap=true;F.appendChild(C.createTextNode(this.Label));};if (this.ShowArrow){if (this.Style!=0){E.insertCell(-1).appendChild(this._CreatePaddingElement(C));};F=E.insertCell(-1);var G=F.appendChild(C.createElement('IMG'));G.src=FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif';G.width=5;G.height=3;};F=E.insertCell(-1);F.appendChild(this._CreatePaddingElement(C));};A.appendChild(B);};FCKToolbarButtonUI.prototype.ChangeState=function(A,B){if (!B&&this.State==A) return;var e=this.MainElement;switch (parseInt(A,10)){case 0:e.className='TB_Button_Off';e.onmouseover=FCKToolbarButton_OnMouseOverOff;e.onmouseout=FCKToolbarButton_OnMouseOutOff;e.onclick=FCKToolbarButton_OnClick;break;case 1:e.className='TB_Button_On';e.onmouseover=FCKToolbarButton_OnMouseOverOn;e.onmouseout=FCKToolbarButton_OnMouseOutOn;e.onclick=FCKToolbarButton_OnClick;break;case -1:e.className='TB_Button_Disabled';e.onmouseover=null;e.onmouseout=null;e.onclick=null;break;};this.State=A;};function FCKToolbarButtonUI_Cleanup(){if (this.MainElement){this.MainElement._FCKButton=null;this.MainElement=null;}};function FCKToolbarButton_OnMouseOverOn(){this.className='TB_Button_On_Over';};function FCKToolbarButton_OnMouseOutOn(){this.className='TB_Button_On';};function FCKToolbarButton_OnMouseOverOff(){this.className='TB_Button_Off_Over';};function FCKToolbarButton_OnMouseOutOff(){this.className='TB_Button_Off';};function FCKToolbarButton_OnClick(e){if (this._FCKButton.OnClick) this._FCKButton.OnClick(this._FCKButton);};
+var FCKToolbarButton=function(A,B,C,D,E,F,G){this.CommandName=A;this.Label=B;this.Tooltip=C;this.Style=D;this.SourceView=E?true:false;this.ContextSensitive=F?true:false;if (G==null) this.IconPath=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(G)=='number') this.IconPath=[FCKConfig.SkinPath+'fck_strip.gif',16,G];};FCKToolbarButton.prototype.Create=function(A){this._UIButton=new FCKToolbarButtonUI(this.CommandName,this.Label,this.Tooltip,this.IconPath,this.Style);this._UIButton.OnClick=this.Click;this._UIButton._ToolbarButton=this;this._UIButton.Create(A);};FCKToolbarButton.prototype.RefreshState=function(){var A=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (A==this._UIButton.State) return;this._UIButton.ChangeState(A);};FCKToolbarButton.prototype.Click=function(){var A=this._ToolbarButton||this;FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(A.CommandName).Execute();};FCKToolbarButton.prototype.Enable=function(){this.RefreshState();};FCKToolbarButton.prototype.Disable=function(){this._UIButton.ChangeState(-1);}
+var FCKSpecialCombo=function(A,B,C,D,E){this.FieldWidth=B||100;this.PanelWidth=C||150;this.PanelMaxHeight=D||150;this.Label='&nbsp;';this.Caption=A;this.Tooltip=A;this.Style=2;this.Enabled=true;this.Items={};this._Panel=new FCKPanel(E||window);this._Panel.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');this._PanelBox=this._Panel.MainNode.appendChild(this._Panel.Document.createElement('DIV'));this._PanelBox.className='SC_Panel';this._PanelBox.style.width=this.PanelWidth+'px';this._PanelBox.innerHTML='<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>';this._ItemsHolderEl=this._PanelBox.getElementsByTagName('TD')[0];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKSpecialCombo_Cleanup);};function FCKSpecialCombo_ItemOnMouseOver(){this.className+=' SC_ItemOver';};function FCKSpecialCombo_ItemOnMouseOut(){this.className=this.originalClass;};function FCKSpecialCombo_ItemOnClick(){this.className=this.originalClass;this.FCKSpecialCombo._Panel.Hide();this.FCKSpecialCombo.SetLabel(this.FCKItemLabel);if (typeof(this.FCKSpecialCombo.OnSelect)=='function') this.FCKSpecialCombo.OnSelect(this.FCKItemID,this);};FCKSpecialCombo.prototype.AddItem=function(A,B,C,D){var E=this._ItemsHolderEl.appendChild(this._Panel.Document.createElement('DIV'));E.className=E.originalClass='SC_Item';E.innerHTML=B;E.FCKItemID=A;E.FCKItemLabel=C||A;E.FCKSpecialCombo=this;E.Selected=false;if (FCKBrowserInfo.IsIE) E.style.width='100%';if (D) E.style.backgroundColor=D;E.onmouseover=FCKSpecialCombo_ItemOnMouseOver;E.onmouseout=FCKSpecialCombo_ItemOnMouseOut;E.onclick=FCKSpecialCombo_ItemOnClick;this.Items[A.toString().toLowerCase()]=E;return E;};FCKSpecialCombo.prototype.SelectItem=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];if (B){B.className=B.originalClass='SC_ItemSelected';B.Selected=true;}};FCKSpecialCombo.prototype.SelectItemByLabel=function(A,B){for (var C in this.Items){var D=this.Items[C];if (D.FCKItemLabel==A){D.className=D.originalClass='SC_ItemSelected';D.Selected=true;if (B) this.SetLabel(A);}}};FCKSpecialCombo.prototype.DeselectAll=function(A){for (var i in this.Items){this.Items[i].className=this.Items[i].originalClass='SC_Item';this.Items[i].Selected=false;};if (A) this.SetLabel('');};FCKSpecialCombo.prototype.SetLabelById=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];this.SetLabel(B?B.FCKItemLabel:'');};FCKSpecialCombo.prototype.SetLabel=function(A){this.Label=A.length==0?'&nbsp;':A;if (this._LabelEl){this._LabelEl.innerHTML=this.Label;FCKTools.DisableSelection(this._LabelEl);}};FCKSpecialCombo.prototype.SetEnabled=function(A){this.Enabled=A;this._OuterTable.className=A?'':'SC_FieldDisabled';};FCKSpecialCombo.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this._OuterTable=A.appendChild(B.createElement('TABLE'));C.cellPadding=0;C.cellSpacing=0;C.insertRow(-1);var D;var E;switch (this.Style){case 0:D='TB_ButtonType_Icon';E=false;break;case 1:D='TB_ButtonType_Text';E=false;break;case 2:E=true;break;};if (this.Caption&&this.Caption.length>0&&E){var F=C.rows[0].insertCell(-1);F.innerHTML=this.Caption;F.className='SC_FieldCaption';};var G=FCKTools.AppendElement(C.rows[0].insertCell(-1),'div');if (E){G.className='SC_Field';G.style.width=this.FieldWidth+'px';G.innerHTML='<table width="100%" cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldLabel"><label>&nbsp;</label></td><td class="SC_FieldButton">&nbsp;</td></tr></tbody></table>';this._LabelEl=G.getElementsByTagName('label')[0];this._LabelEl.innerHTML=this.Label;}else{G.className='TB_Button_Off';G.innerHTML='<table title="'+this.Tooltip+'" class="'+D+'" cellspacing="0" cellpadding="0" border="0"><tr><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td><td class="TB_Text">'+this.Caption+'</td><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td><td class="TB_ButtonArrow"><img src="'+FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif" width="5" height="3"></td><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td></tr></table>';};G.SpecialCombo=this;G.onmouseover=FCKSpecialCombo_OnMouseOver;G.onmouseout=FCKSpecialCombo_OnMouseOut;G.onclick=FCKSpecialCombo_OnClick;FCKTools.DisableSelection(this._Panel.Document.body);};function FCKSpecialCombo_Cleanup(){this._LabelEl=null;this._OuterTable=null;this._ItemsHolderEl=null;this._PanelBox=null;if (this.Items){for (var A in this.Items) this.Items[A]=null;}};function FCKSpecialCombo_OnMouseOver(){if (this.SpecialCombo.Enabled){switch (this.SpecialCombo.Style){case 0:this.className='TB_Button_On_Over';break;case 1:this.className='TB_Button_On_Over';break;case 2:this.className='SC_Field SC_FieldOver';break;}}};function FCKSpecialCombo_OnMouseOut(){switch (this.SpecialCombo.Style){case 0:this.className='TB_Button_Off';break;case 1:this.className='TB_Button_Off';break;case 2:this.className='SC_Field';break;}};function FCKSpecialCombo_OnClick(e){var A=this.SpecialCombo;if (A.Enabled){var B=A._Panel;var C=A._PanelBox;var D=A._ItemsHolderEl;var E=A.PanelMaxHeight;if (A.OnBeforeClick) A.OnBeforeClick(A);if (FCKBrowserInfo.IsIE) B.Preload(0,this.offsetHeight,this);if (D.offsetHeight>E) C.style.height=E+'px';else C.style.height='';B.Show(0,this.offsetHeight,this);}};
+var FCKToolbarSpecialCombo=function(){this.SourceView=false;this.ContextSensitive=true;this._LastValue=null;};function FCKToolbarSpecialCombo_OnSelect(A,B){FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Execute(A,B);};FCKToolbarSpecialCombo.prototype.Create=function(A){this._Combo=new FCKSpecialCombo(this.GetLabel(),this.FieldWidth,this.PanelWidth,this.PanelMaxHeight,FCKBrowserInfo.IsIE?window:FCKTools.GetElementWindow(A).parent);this._Combo.Tooltip=this.Tooltip;this._Combo.Style=this.Style;this.CreateItems(this._Combo);this._Combo.Create(A);this._Combo.CommandName=this.CommandName;this._Combo.OnSelect=FCKToolbarSpecialCombo_OnSelect;};function FCKToolbarSpecialCombo_RefreshActiveItems(A,B){A.DeselectAll();A.SelectItem(B);A.SetLabelById(B);};FCKToolbarSpecialCombo.prototype.RefreshState=function(){var A;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B!=-1){A=1;if (this.RefreshActiveItems) this.RefreshActiveItems(this._Combo,B);else{if (this._LastValue!=B){this._LastValue=B;FCKToolbarSpecialCombo_RefreshActiveItems(this._Combo,B);}}}else A=-1;if (A==this.State) return;if (A==-1){this._Combo.DeselectAll();this._Combo.SetLabel('');};this.State=A;this._Combo.SetEnabled(A!=-1);};FCKToolbarSpecialCombo.prototype.Enable=function(){this.RefreshState();};FCKToolbarSpecialCombo.prototype.Disable=function(){this.State=-1;this._Combo.DeselectAll();this._Combo.SetLabel('');this._Combo.SetEnabled(false);};
+var FCKToolbarFontsCombo=function(A,B){this.CommandName='FontName';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarFontsCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontsCombo.prototype.GetLabel=function(){return FCKLang.Font;};FCKToolbarFontsCombo.prototype.CreateItems=function(A){var B=FCKConfig.FontNames.split(';');for (var i=0;i<B.length;i++) this._Combo.AddItem(B[i],'<font face="'+B[i]+'" style="font-size: 12px">'+B[i]+'</font>');}
+var FCKToolbarFontSizeCombo=function(A,B){this.CommandName='FontSize';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarFontSizeCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontSizeCombo.prototype.GetLabel=function(){return FCKLang.FontSize;};FCKToolbarFontSizeCombo.prototype.CreateItems=function(A){A.FieldWidth=70;var B=FCKConfig.FontSizes.split(';');for (var i=0;i<B.length;i++){var C=B[i].split('/');this._Combo.AddItem(C[0],'<font size="'+C[0]+'">'+C[1]+'</font>',C[1]);}}
+var FCKToolbarFontFormatCombo=function(A,B){this.CommandName='FontFormat';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.NormalLabel='Normal';this.PanelWidth=190;};FCKToolbarFontFormatCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontFormatCombo.prototype.GetLabel=function(){return FCKLang.FontFormat;};FCKToolbarFontFormatCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) B.body.id=FCKConfig.BodyId;if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) B.body.className+=' '+FCKConfig.BodyClass;var C=FCKLang['FontFormats'].split(';');var D={p:C[0],pre:C[1],address:C[2],h1:C[3],h2:C[4],h3:C[5],h4:C[6],h5:C[7],h6:C[8],div:C[9]};var E=FCKConfig.FontFormats.split(';');for (var i=0;i<E.length;i++){var F=E[i];var G=D[F];if (F=='p') this.NormalLabel=G;this._Combo.AddItem(F,'<div class="BaseFont"><'+F+'>'+G+'</'+F+'></div>',G);}};if (FCKBrowserInfo.IsIE){FCKToolbarFontFormatCombo.prototype.RefreshActiveItems=function(A,B){if (B==this.NormalLabel){if (A.Label!='&nbsp;') A.DeselectAll(true);}else{if (this._LastValue==B) return;A.SelectItemByLabel(B,true);};this._LastValue=B;}}
+var FCKToolbarStyleCombo=function(A,B){this.CommandName='Style';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarStyleCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarStyleCombo.prototype.GetLabel=function(){return FCKLang.Style;};FCKToolbarStyleCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);B.body.className+=' ForceBaseFont';if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) B.body.id=FCKConfig.BodyId;if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) B.body.className+=' '+FCKConfig.BodyClass;if (!(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsGecko10)) A.OnBeforeClick=this.RefreshVisibleItems;var C=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Styles;for (var s in C){var D=C[s];var E;if (D.IsObjectElement) E=A.AddItem(s,s);else E=A.AddItem(s,D.GetOpenerTag()+s+D.GetCloserTag());E.Style=D;}};FCKToolbarStyleCombo.prototype.RefreshActiveItems=function(A){A.DeselectAll();var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetActiveStyles();if (B.length>0){for (var i=0;i<B.length;i++) A.SelectItem(B[i].Name);A.SetLabelById(B[0].Name);}else A.SetLabel('');};FCKToolbarStyleCombo.prototype.RefreshVisibleItems=function(A){if (FCKSelection.GetType()=='Control') var B=FCKSelection.GetSelectedElement().tagName;for (var i in A.Items){var C=A.Items[i];if ((B&&C.Style.Element==B)||(!B&&!C.Style.IsObjectElement)) C.style.display='';else C.style.display='none';}}
+var FCKToolbarPanelButton=function(A,B,C,D,E){this.CommandName=A;var F;if (E==null) F=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(E)=='number') F=[FCKConfig.SkinPath+'fck_strip.gif',16,E];var G=this._UIButton=new FCKToolbarButtonUI(A,B,C,F,D);G._FCKToolbarPanelButton=this;G.ShowArrow=true;G.OnClick=FCKToolbarPanelButton_OnButtonClick;};FCKToolbarPanelButton.prototype.TypeName='FCKToolbarPanelButton';FCKToolbarPanelButton.prototype.Create=function(A){A.className+='Menu';this._UIButton.Create(A);var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName)._Panel;B._FCKToolbarPanelButton=this;var C=B.Document.body.appendChild(B.Document.createElement('div'));C.style.position='absolute';C.style.top='0px';var D=this.LineImg=C.appendChild(B.Document.createElement('IMG'));D.className='TB_ConnectionLine';D.src=FCK_SPACER_PATH;B.OnHide=FCKToolbarPanelButton_OnPanelHide;};function FCKToolbarPanelButton_OnButtonClick(A){var B=this._FCKToolbarPanelButton;var e=B._UIButton.MainElement;B._UIButton.ChangeState(1);B.LineImg.style.width=(e.offsetWidth-2)+'px';FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(B.CommandName).Execute(0,e.offsetHeight-1,e);};function FCKToolbarPanelButton_OnPanelHide(){var A=this._FCKToolbarPanelButton;A._UIButton.ChangeState(0);};FCKToolbarPanelButton.prototype.RefreshState=FCKToolbarButton.prototype.RefreshState;FCKToolbarPanelButton.prototype.Enable=FCKToolbarButton.prototype.Enable;FCKToolbarPanelButton.prototype.Disable=FCKToolbarButton.prototype.Disable;
+var FCKToolbarItems={};FCKToolbarItems.LoadedItems={};FCKToolbarItems.RegisterItem=function(A,B){this.LoadedItems[A]=B;};FCKToolbarItems.GetItem=function(A){var B=FCKToolbarItems.LoadedItems[A];if (B) return B;switch (A){case 'Source':B=new FCKToolbarButton('Source',FCKLang.Source,null,2,true,true,1);break;case 'DocProps':B=new FCKToolbarButton('DocProps',FCKLang.DocProps,null,null,null,null,2);break;case 'Save':B=new FCKToolbarButton('Save',FCKLang.Save,null,null,true,null,3);break;case 'NewPage':B=new FCKToolbarButton('NewPage',FCKLang.NewPage,null,null,true,null,4);break;case 'Preview':B=new FCKToolbarButton('Preview',FCKLang.Preview,null,null,true,null,5);break;case 'Templates':B=new FCKToolbarButton('Templates',FCKLang.Templates,null,null,null,null,6);break;case 'About':B=new FCKToolbarButton('About',FCKLang.About,null,null,true,null,47);break;case 'Cut':B=new FCKToolbarButton('Cut',FCKLang.Cut,null,null,false,true,7);break;case 'Copy':B=new FCKToolbarButton('Copy',FCKLang.Copy,null,null,false,true,8);break;case 'Paste':B=new FCKToolbarButton('Paste',FCKLang.Paste,null,null,false,true,9);break;case 'PasteText':B=new FCKToolbarButton('PasteText',FCKLang.PasteText,null,null,false,true,10);break;case 'PasteWord':B=new FCKToolbarButton('PasteWord',FCKLang.PasteWord,null,null,false,true,11);break;case 'Print':B=new FCKToolbarButton('Print',FCKLang.Print,null,null,false,true,12);break;case 'SpellCheck':B=new FCKToolbarButton('SpellCheck',FCKLang.SpellCheck,null,null,null,null,13);break;case 'Undo':B=new FCKToolbarButton('Undo',FCKLang.Undo,null,null,false,true,14);break;case 'Redo':B=new FCKToolbarButton('Redo',FCKLang.Redo,null,null,false,true,15);break;case 'SelectAll':B=new FCKToolbarButton('SelectAll',FCKLang.SelectAll,null,null,true,null,18);break;case 'RemoveFormat':B=new FCKToolbarButton('RemoveFormat',FCKLang.RemoveFormat,null,null,false,true,19);break;case 'FitWindow':B=new FCKToolbarButton('FitWindow',FCKLang.FitWindow,null,null,true,true,66);break;case 'Bold':B=new FCKToolbarButton('Bold',FCKLang.Bold,null,null,false,true,20);break;case 'Italic':B=new FCKToolbarButton('Italic',FCKLang.Italic,null,null,false,true,21);break;case 'Underline':B=new FCKToolbarButton('Underline',FCKLang.Underline,null,null,false,true,22);break;case 'StrikeThrough':B=new FCKToolbarButton('StrikeThrough',FCKLang.StrikeThrough,null,null,false,true,23);break;case 'Subscript':B=new FCKToolbarButton('Subscript',FCKLang.Subscript,null,null,false,true,24);break;case 'Superscript':B=new FCKToolbarButton('Superscript',FCKLang.Superscript,null,null,false,true,25);break;case 'OrderedList':B=new FCKToolbarButton('InsertOrderedList',FCKLang.NumberedListLbl,FCKLang.NumberedList,null,false,true,26);break;case 'UnorderedList':B=new FCKToolbarButton('InsertUnorderedList',FCKLang.BulletedListLbl,FCKLang.BulletedList,null,false,true,27);break;case 'Outdent':B=new FCKToolbarButton('Outdent',FCKLang.DecreaseIndent,null,null,false,true,28);break;case 'Indent':B=new FCKToolbarButton('Indent',FCKLang.IncreaseIndent,null,null,false,true,29);break;case 'Link':B=new FCKToolbarButton('Link',FCKLang.InsertLinkLbl,FCKLang.InsertLink,null,false,true,34);break;case 'Unlink':B=new FCKToolbarButton('Unlink',FCKLang.RemoveLink,null,null,false,true,35);break;case 'Anchor':B=new FCKToolbarButton('Anchor',FCKLang.Anchor,null,null,null,null,36);break;case 'Image':B=new FCKToolbarButton('Image',FCKLang.InsertImageLbl,FCKLang.InsertImage,null,false,true,37);break;case 'Flash':B=new FCKToolbarButton('Flash',FCKLang.InsertFlashLbl,FCKLang.InsertFlash,null,false,true,38);break;case 'Table':B=new FCKToolbarButton('Table',FCKLang.InsertTableLbl,FCKLang.InsertTable,null,false,true,39);break;case 'SpecialChar':B=new FCKToolbarButton('SpecialChar',FCKLang.InsertSpecialCharLbl,FCKLang.InsertSpecialChar,null,false,true,42);break;case 'Smiley':B=new FCKToolbarButton('Smiley',FCKLang.InsertSmileyLbl,FCKLang.InsertSmiley,null,false,true,41);break;case 'PageBreak':B=new FCKToolbarButton('PageBreak',FCKLang.PageBreakLbl,FCKLang.PageBreak,null,false,true,43);break;case 'Rule':B=new FCKToolbarButton('InsertHorizontalRule',FCKLang.InsertLineLbl,FCKLang.InsertLine,null,false,true,40);break;case 'JustifyLeft':B=new FCKToolbarButton('JustifyLeft',FCKLang.LeftJustify,null,null,false,true,30);break;case 'JustifyCenter':B=new FCKToolbarButton('JustifyCenter',FCKLang.CenterJustify,null,null,false,true,31);break;case 'JustifyRight':B=new FCKToolbarButton('JustifyRight',FCKLang.RightJustify,null,null,false,true,32);break;case 'JustifyFull':B=new FCKToolbarButton('JustifyFull',FCKLang.BlockJustify,null,null,false,true,33);break;case 'Style':B=new FCKToolbarStyleCombo();break;case 'FontName':B=new FCKToolbarFontsCombo();break;case 'FontSize':B=new FCKToolbarFontSizeCombo();break;case 'FontFormat':B=new FCKToolbarFontFormatCombo();break;case 'TextColor':B=new FCKToolbarPanelButton('TextColor',FCKLang.TextColor,null,null,45);break;case 'BGColor':B=new FCKToolbarPanelButton('BGColor',FCKLang.BGColor,null,null,46);break;case 'Find':B=new FCKToolbarButton('Find',FCKLang.Find,null,null,null,null,16);break;case 'Replace':B=new FCKToolbarButton('Replace',FCKLang.Replace,null,null,null,null,17);break;case 'Form':B=new FCKToolbarButton('Form',FCKLang.Form,null,null,null,null,48);break;case 'Checkbox':B=new FCKToolbarButton('Checkbox',FCKLang.Checkbox,null,null,null,null,49);break;case 'Radio':B=new FCKToolbarButton('Radio',FCKLang.RadioButton,null,null,null,null,50);break;case 'TextField':B=new FCKToolbarButton('TextField',FCKLang.TextField,null,null,null,null,51);break;case 'Textarea':B=new FCKToolbarButton('Textarea',FCKLang.Textarea,null,null,null,null,52);break;case 'HiddenField':B=new FCKToolbarButton('HiddenField',FCKLang.HiddenField,null,null,null,null,56);break;case 'Button':B=new FCKToolbarButton('Button',FCKLang.Button,null,null,null,null,54);break;case 'Select':B=new FCKToolbarButton('Select',FCKLang.SelectionField,null,null,null,null,53);break;case 'ImageButton':B=new FCKToolbarButton('ImageButton',FCKLang.ImageButton,null,null,null,null,55);break;default:alert(FCKLang.UnknownToolbarItem.replace(/%1/g,A));return null;};FCKToolbarItems.LoadedItems[A]=B;return B;}
+var FCKToolbar=function(){this.Items=[];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbar_Cleanup);};FCKToolbar.prototype.AddItem=function(A){return this.Items[this.Items.length]=A;};FCKToolbar.prototype.AddButton=function(A,B,C,D,E,F){if (typeof(D)=='number') D=[this.DefaultIconsStrip,this.DefaultIconSize,D];var G=new FCKToolbarButtonUI(A,B,C,D,E,F);G._FCKToolbar=this;G.OnClick=FCKToolbar_OnItemClick;return this.AddItem(G);};function FCKToolbar_OnItemClick(A){var B=A._FCKToolbar;if (B.OnItemClick) B.OnItemClick(B,A);};FCKToolbar.prototype.AddSeparator=function(){this.AddItem(new FCKToolbarSeparator());};FCKToolbar.prototype.Create=function(A){if (this.MainElement){if (this.MainElement.parentNode) this.MainElement.parentNode.removeChild(this.MainElement);this.MainElement=null;};var B=FCKTools.GetElementDocument(A);var e=this.MainElement=B.createElement('table');e.className='TB_Toolbar';e.style.styleFloat=e.style.cssFloat=(FCKLang.Dir=='ltr'?'left':'right');e.dir=FCKLang.Dir;e.cellPadding=0;e.cellSpacing=0;this.RowElement=e.insertRow(-1);var C;if (!this.HideStart){C=this.RowElement.insertCell(-1);C.appendChild(B.createElement('div')).className='TB_Start';};for (var i=0;i<this.Items.length;i++){this.Items[i].Create(this.RowElement.insertCell(-1));};if (!this.HideEnd){C=this.RowElement.insertCell(-1);C.appendChild(B.createElement('div')).className='TB_End';};A.appendChild(e);};function FCKToolbar_Cleanup(){this.MainElement=null;this.RowElement=null;};var FCKToolbarSeparator=function(){};FCKToolbarSeparator.prototype.Create=function(A){FCKTools.AppendElement(A,'div').className='TB_Separator';}
+var FCKToolbarBreak=function(){};FCKToolbarBreak.prototype.Create=function(A){var B=A.ownerDocument.createElement('div');B.style.clear=B.style.cssFloat=FCKLang.Dir=='rtl'?'right':'left';A.appendChild(B);}
+function FCKToolbarSet_Create(A){var B;var C=A||FCKConfig.ToolbarLocation;switch (C){case 'In':document.getElementById('xToolbarRow').style.display='';B=new FCKToolbarSet(document);break;default:FCK.Events.AttachEvent('OnBlur',FCK_OnBlur);FCK.Events.AttachEvent('OnFocus',FCK_OnFocus);var D;var E=C.match(/^Out:(.+)\((\w+)\)$/);if (E){D=eval('parent.'+E[1]).document.getElementById(E[2]);}else{E=C.match(/^Out:(\w+)$/);if (E) D=parent.document.getElementById(E[1]);};if (!D){alert('Invalid value for "ToolbarLocation"');return this._Init('In');};B=D.__FCKToolbarSet;if (B) break;var F=FCKTools.GetElementDocument(D).createElement('iframe');F.src='javascript:void(0)';F.frameBorder=0;F.width='100%';F.height='10';D.appendChild(F);F.unselectable='on';var G=F.contentWindow.document;G.open();G.write('<html><head><script type="text/javascript"> window.onload = window.onresize = function() { window.frameElement.height = document.body.scrollHeight ; } </script></head><body style="overflow: hidden">'+document.getElementById('xToolbarSpace').innerHTML+'</body></html>');G.close();G.oncontextmenu=FCKTools.CancelEvent;FCKTools.AppendStyleSheet(G,FCKConfig.SkinPath+'fck_editor.css');B=D.__FCKToolbarSet=new FCKToolbarSet(G);B._IFrame=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(D,FCKToolbarSet_Target_Cleanup);};B.CurrentInstance=FCK;FCK.AttachToOnSelectionChange(B.RefreshItemsState);return B;};function FCK_OnBlur(A){var B=A.ToolbarSet;if (B.CurrentInstance==A) B.Disable();};function FCK_OnFocus(A){var B=A.ToolbarSet;var C=A||FCK;B.CurrentInstance.FocusManager.RemoveWindow(B._IFrame.contentWindow);B.CurrentInstance=C;C.FocusManager.AddWindow(B._IFrame.contentWindow,true);B.Enable();};function FCKToolbarSet_Cleanup(){this._TargetElement=null;this._IFrame=null;};function FCKToolbarSet_Target_Cleanup(){this.__FCKToolbarSet=null;};var FCKToolbarSet=function(A){this._Document=A;this._TargetElement=A.getElementById('xToolbar');var B=A.getElementById('xExpandHandle');var C=A.getElementById('xCollapseHandle');B.title=FCKLang.ToolbarExpand;B.onclick=FCKToolbarSet_Expand_OnClick;C.title=FCKLang.ToolbarCollapse;C.onclick=FCKToolbarSet_Collapse_OnClick;if (!FCKConfig.ToolbarCanCollapse||FCKConfig.ToolbarStartExpanded) this.Expand();else this.Collapse();C.style.display=FCKConfig.ToolbarCanCollapse?'':'none';if (FCKConfig.ToolbarCanCollapse) C.style.display='';else A.getElementById('xTBLeftBorder').style.display='';this.Toolbars=[];this.IsLoaded=false;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarSet_Cleanup);};function FCKToolbarSet_Expand_OnClick(){FCK.ToolbarSet.Expand();};function FCKToolbarSet_Collapse_OnClick(){FCK.ToolbarSet.Collapse();};FCKToolbarSet.prototype.Expand=function(){this._ChangeVisibility(false);};FCKToolbarSet.prototype.Collapse=function(){this._ChangeVisibility(true);};FCKToolbarSet.prototype._ChangeVisibility=function(A){this._Document.getElementById('xCollapsed').style.display=A?'':'none';this._Document.getElementById('xExpanded').style.display=A?'none':'';if (FCKBrowserInfo.IsGecko){FCKTools.RunFunction(window.onresize);}};FCKToolbarSet.prototype.Load=function(A){this.Name=A;this.Items=[];this.ItemsWysiwygOnly=[];this.ItemsContextSensitive=[];this._TargetElement.innerHTML='';var B=FCKConfig.ToolbarSets[A];if (!B){alert(FCKLang.UnknownToolbarSet.replace(/%1/g,A));return;};this.Toolbars=[];for (var x=0;x<B.length;x++){var C=B[x];if (!C) continue;var D;if (typeof(C)=='string'){if (C=='/') D=new FCKToolbarBreak();}else{D=new FCKToolbar();for (var j=0;j<C.length;j++){var E=C[j];if (E=='-') D.AddSeparator();else{var F=FCKToolbarItems.GetItem(E);if (F){D.AddItem(F);this.Items.push(F);if (!F.SourceView) this.ItemsWysiwygOnly.push(F);if (F.ContextSensitive) this.ItemsContextSensitive.push(F);}}}};D.Create(this._TargetElement);this.Toolbars[this.Toolbars.length]=D;};FCKTools.DisableSelection(this._Document.getElementById('xCollapseHandle').parentNode);if (FCK.Status!=2) FCK.Events.AttachEvent('OnStatusChange',this.RefreshModeState);else this.RefreshModeState();this.IsLoaded=true;this.IsEnabled=true;FCKTools.RunFunction(this.OnLoad);};FCKToolbarSet.prototype.Enable=function(){if (this.IsEnabled) return;this.IsEnabled=true;var A=this.Items;for (var i=0;i<A.length;i++) A[i].RefreshState();};FCKToolbarSet.prototype.Disable=function(){if (!this.IsEnabled) return;this.IsEnabled=false;var A=this.Items;for (var i=0;i<A.length;i++) A[i].Disable();};FCKToolbarSet.prototype.RefreshModeState=function(A){if (FCK.Status!=2) return;var B=A?A.ToolbarSet:this;var C=B.ItemsWysiwygOnly;if (FCK.EditMode==0){for (var i=0;i<C.length;i++) C[i].Enable();B.RefreshItemsState(A);}else{B.RefreshItemsState(A);for (var j=0;j<C.length;j++) C[j].Disable();}};FCKToolbarSet.prototype.RefreshItemsState=function(A){var B=(A?A.ToolbarSet:this).ItemsContextSensitive;for (var i=0;i<B.length;i++) B[i].RefreshState();};
+var FCKDialog={};FCKDialog.OpenDialog=function(A,B,C,D,E,F,G,H){var I={};I.Title=B;I.Page=C;I.Editor=window;I.CustomValue=F;var J=FCKConfig.BasePath+'fckdialog.html';this.Show(I,A,J,D,E,G,H);};
+FCKDialog.Show=function(A,B,C,D,E,F,G){var H=(FCKConfig.ScreenHeight-E)/2;var I=(FCKConfig.ScreenWidth-D)/2;var J="location=no,menubar=no,toolbar=no,dependent=yes,dialog=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable="+(G?'yes':'no')+",width="+D+",height="+E+",top="+H+",left="+I;if (!F) F=window;FCKFocusManager.Lock();var K=F.open('','FCKeditorDialog_'+B,J,true);if (!K){alert(FCKLang.DialogBlocked);FCKFocusManager.Unlock();return;};K.moveTo(I,H);K.resizeTo(D,E);K.focus();K.location.href=C;K.dialogArguments=A;F.FCKLastDialogInfo=A;this.Window=K;try{window.top.parent.addEventListener('mousedown',this.CheckFocus,true);window.top.parent.addEventListener('mouseup',this.CheckFocus,true);window.top.parent.addEventListener('click',this.CheckFocus,true);window.top.parent.addEventListener('focus',this.CheckFocus,true);}catch (e){}};FCKDialog.CheckFocus=function(){if (typeof(FCKDialog)!="object") return false;if (FCKDialog.Window&&!FCKDialog.Window.closed) FCKDialog.Window.focus();else{try{window.top.parent.removeEventListener('onmousedown',FCKDialog.CheckFocus,true);window.top.parent.removeEventListener('mouseup',FCKDialog.CheckFocus,true);window.top.parent.removeEventListener('click',FCKDialog.CheckFocus,true);window.top.parent.removeEventListener('onfocus',FCKDialog.CheckFocus,true);}catch (e){}};return false;};
+var FCKMenuItem=function(A,B,C,D,E){this.Name=B;this.Label=C||B;this.IsDisabled=E;this.Icon=new FCKIcon(D);this.SubMenu=new FCKMenuBlockPanel();this.SubMenu.Parent=A;this.SubMenu.OnClick=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnClick,this);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuItem_Cleanup);};FCKMenuItem.prototype.AddItem=function(A,B,C,D){this.HasSubMenu=true;return this.SubMenu.AddItem(A,B,C,D);};FCKMenuItem.prototype.AddSeparator=function(){this.SubMenu.AddSeparator();};FCKMenuItem.prototype.Create=function(A){var B=this.HasSubMenu;var C=FCKTools.GetElementDocument(A);var r=this.MainElement=A.insertRow(-1);r.className=this.IsDisabled?'MN_Item_Disabled':'MN_Item';if (!this.IsDisabled){FCKTools.AddEventListenerEx(r,'mouseover',FCKMenuItem_OnMouseOver,[this]);FCKTools.AddEventListenerEx(r,'click',FCKMenuItem_OnClick,[this]);if (!B) FCKTools.AddEventListenerEx(r,'mouseout',FCKMenuItem_OnMouseOut,[this]);};var D=r.insertCell(-1);D.className='MN_Icon';D.appendChild(this.Icon.CreateIconElement(C));D=r.insertCell(-1);D.className='MN_Label';D.noWrap=true;D.appendChild(C.createTextNode(this.Label));D=r.insertCell(-1);if (B){D.className='MN_Arrow';var E=D.appendChild(C.createElement('IMG'));E.src=FCK_IMAGES_PATH+'arrow_'+FCKLang.Dir+'.gif';E.width=4;E.height=7;this.SubMenu.Create();this.SubMenu.Panel.OnHide=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnHide,this);}};FCKMenuItem.prototype.Activate=function(){this.MainElement.className='MN_Item_Over';if (this.HasSubMenu){this.SubMenu.Show(this.MainElement.offsetWidth+2,-2,this.MainElement);};FCKTools.RunFunction(this.OnActivate,this);};FCKMenuItem.prototype.Deactivate=function(){this.MainElement.className='MN_Item';if (this.HasSubMenu) this.SubMenu.Hide();};function FCKMenuItem_SubMenu_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuItem_SubMenu_OnHide(A){A.Deactivate();};function FCKMenuItem_OnClick(A,B){if (B.HasSubMenu) B.Activate();else{B.Deactivate();FCKTools.RunFunction(B.OnClick,B,[B]);}};function FCKMenuItem_OnMouseOver(A,B){B.Activate();};function FCKMenuItem_OnMouseOut(A,B){B.Deactivate();};function FCKMenuItem_Cleanup(){this.MainElement=null;}
+var FCKMenuBlock=function(){this._Items=[];};FCKMenuBlock.prototype.Count=function(){return this._Items.length;};FCKMenuBlock.prototype.AddItem=function(A,B,C,D){var E=new FCKMenuItem(this,A,B,C,D);E.OnClick=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnClick,this);E.OnActivate=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnActivate,this);this._Items.push(E);return E;};FCKMenuBlock.prototype.AddSeparator=function(){this._Items.push(new FCKMenuSeparator());};FCKMenuBlock.prototype.RemoveAllItems=function(){this._Items=[];var A=this._ItemsTable;if (A){while (A.rows.length>0) A.deleteRow(0);}};FCKMenuBlock.prototype.Create=function(A){if (!this._ItemsTable){if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuBlock_Cleanup);this._Window=FCKTools.GetElementWindow(A);var B=FCKTools.GetElementDocument(A);var C=A.appendChild(B.createElement('table'));C.cellPadding=0;C.cellSpacing=0;FCKTools.DisableSelection(C);var D=C.insertRow(-1).insertCell(-1);D.className='MN_Menu';var E=this._ItemsTable=D.appendChild(B.createElement('table'));E.cellPadding=0;E.cellSpacing=0;};for (var i=0;i<this._Items.length;i++) this._Items[i].Create(this._ItemsTable);};function FCKMenuBlock_Item_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuBlock_Item_OnActivate(A){var B=A._ActiveItem;if (B&&B!=this){if (!FCKBrowserInfo.IsIE&&B.HasSubMenu&&!this.HasSubMenu) A._Window.focus();B.Deactivate();};A._ActiveItem=this;};function FCKMenuBlock_Cleanup(){this._Window=null;this._ItemsTable=null;};var FCKMenuSeparator=function(){};FCKMenuSeparator.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var r=A.insertRow(-1);var C=r.insertCell(-1);C.className='MN_Separator MN_Icon';C=r.insertCell(-1);C.className='MN_Separator';C.appendChild(B.createElement('DIV')).className='MN_Separator_Line';C=r.insertCell(-1);C.className='MN_Separator';C.appendChild(B.createElement('DIV')).className='MN_Separator_Line';}
+var FCKMenuBlockPanel=function(){FCKMenuBlock.call(this);};FCKMenuBlockPanel.prototype=new FCKMenuBlock();FCKMenuBlockPanel.prototype.Create=function(){var A=this.Panel=(this.Parent&&this.Parent.Panel?this.Parent.Panel.CreateChildPanel():new FCKPanel());A.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');FCKMenuBlock.prototype.Create.call(this,A.MainNode);};FCKMenuBlockPanel.prototype.Show=function(x,y,A){if (!this.Panel.CheckIsOpened()) this.Panel.Show(x,y,A);};FCKMenuBlockPanel.prototype.Hide=function(){if (this.Panel.CheckIsOpened()) this.Panel.Hide();}
+var FCKContextMenu=function(A,B){this.CtrlDisable=false;var C=this._Panel=new FCKPanel(A);C.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');C.IsContextMenu=true;if (FCKBrowserInfo.IsGecko) C.Document.addEventListener('draggesture',function(e) {e.preventDefault();return false;},true);var D=this._MenuBlock=new FCKMenuBlock();D.Panel=C;D.OnClick=FCKTools.CreateEventListener(FCKContextMenu_MenuBlock_OnClick,this);this._Redraw=true;};FCKContextMenu.prototype.SetMouseClickWindow=function(A){if (!FCKBrowserInfo.IsIE){this._Document=A.document;this._Document.addEventListener('contextmenu',FCKContextMenu_Document_OnContextMenu,false);}};FCKContextMenu.prototype.AddItem=function(A,B,C,D){var E=this._MenuBlock.AddItem(A,B,C,D);this._Redraw=true;return E;};FCKContextMenu.prototype.AddSeparator=function(){this._MenuBlock.AddSeparator();this._Redraw=true;};FCKContextMenu.prototype.RemoveAllItems=function(){this._MenuBlock.RemoveAllItems();this._Redraw=true;};FCKContextMenu.prototype.AttachToElement=function(A){if (FCKBrowserInfo.IsIE) FCKTools.AddEventListenerEx(A,'contextmenu',FCKContextMenu_AttachedElement_OnContextMenu,this);else A._FCKContextMenu=this;};function FCKContextMenu_Document_OnContextMenu(e){var A=e.target;while (A){if (A._FCKContextMenu){if (A._FCKContextMenu.CtrlDisable&&(e.ctrlKey||e.metaKey)) return true;FCKTools.CancelEvent(e);FCKContextMenu_AttachedElement_OnContextMenu(e,A._FCKContextMenu,A);};A=A.parentNode;}};function FCKContextMenu_AttachedElement_OnContextMenu(A,B,C){if (B.CtrlDisable&&(A.ctrlKey||A.metaKey)) return true;var D=C||this;if (B.OnBeforeOpen) B.OnBeforeOpen.call(B,D);if (B._MenuBlock.Count()==0) return false;if (B._Redraw){B._MenuBlock.Create(B._Panel.MainNode);B._Redraw=false;};FCKTools.DisableSelection(B._Panel.Document.body);B._Panel.Show(A.pageX||A.screenX,A.pageY||A.screenY,A.currentTarget||null);return false;};function FCKContextMenu_MenuBlock_OnClick(A,B){B._Panel.Hide();FCKTools.RunFunction(B.OnItemClick,B,A);}
+FCK.ContextMenu={};FCK.ContextMenu.Listeners=[];FCK.ContextMenu.RegisterListener=function(A){if (A) this.Listeners.push(A);};function FCK_ContextMenu_Init(){var A=FCK.ContextMenu._InnerContextMenu=new FCKContextMenu(FCKBrowserInfo.IsIE?window:window.parent,FCKLang.Dir);A.CtrlDisable=FCKConfig.BrowserContextMenuOnCtrl;A.OnBeforeOpen=FCK_ContextMenu_OnBeforeOpen;A.OnItemClick=FCK_ContextMenu_OnItemClick;var B=FCK.ContextMenu;for (var i=0;i<FCKConfig.ContextMenu.length;i++) B.RegisterListener(FCK_ContextMenu_GetListener(FCKConfig.ContextMenu[i]));};function FCK_ContextMenu_GetListener(A){switch (A){case 'Generic':return {AddItems:function(menu,tag,tagName){menu.AddItem('Cut',FCKLang.Cut,7,FCKCommands.GetCommand('Cut').GetState()==-1);menu.AddItem('Copy',FCKLang.Copy,8,FCKCommands.GetCommand('Copy').GetState()==-1);menu.AddItem('Paste',FCKLang.Paste,9,FCKCommands.GetCommand('Paste').GetState()==-1);}};case 'Table':return {AddItems:function(menu,tag,tagName){var B=(tagName=='TABLE');var C=(!B&&FCKSelection.HasAncestorNode('TABLE'));if (C){menu.AddSeparator();var D=menu.AddItem('Cell',FCKLang.CellCM);D.AddItem('TableInsertCell',FCKLang.InsertCell,58);D.AddItem('TableDeleteCells',FCKLang.DeleteCells,59);D.AddItem('TableMergeCells',FCKLang.MergeCells,60);D.AddItem('TableSplitCell',FCKLang.SplitCell,61);D.AddSeparator();D.AddItem('TableCellProp',FCKLang.CellProperties,57);menu.AddSeparator();D=menu.AddItem('Row',FCKLang.RowCM);D.AddItem('TableInsertRow',FCKLang.InsertRow,62);D.AddItem('TableDeleteRows',FCKLang.DeleteRows,63);menu.AddSeparator();D=menu.AddItem('Column',FCKLang.ColumnCM);D.AddItem('TableInsertColumn',FCKLang.InsertColumn,64);D.AddItem('TableDeleteColumns',FCKLang.DeleteColumns,65);};if (B||C){menu.AddSeparator();menu.AddItem('TableDelete',FCKLang.TableDelete);menu.AddItem('TableProp',FCKLang.TableProperties,39);}}};case 'Link':return {AddItems:function(menu,tag,tagName){var E=(tagName=='A'||FCKSelection.HasAncestorNode('A'));if (E||FCK.GetNamedCommandState('Unlink')!=-1){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0&&F.href.length==0);if (G) return;menu.AddSeparator();if (E) menu.AddItem('Link',FCKLang.EditLink,34);menu.AddItem('Unlink',FCKLang.RemoveLink,35);}}};case 'Image':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&!tag.getAttribute('_fckfakelement')){menu.AddSeparator();menu.AddItem('Image',FCKLang.ImageProperties,37);}}};case 'Anchor':return {AddItems:function(menu,tag,tagName){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0);if (G||(tagName=='IMG'&&tag.getAttribute('_fckanchor'))){menu.AddSeparator();menu.AddItem('Anchor',FCKLang.AnchorProp,36);}}};case 'Flash':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckflash')){menu.AddSeparator();menu.AddItem('Flash',FCKLang.FlashProperties,38);}}};case 'Form':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('FORM')){menu.AddSeparator();menu.AddItem('Form',FCKLang.FormProp,48);}}};case 'Checkbox':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='checkbox'){menu.AddSeparator();menu.AddItem('Checkbox',FCKLang.CheckboxProp,49);}}};case 'Radio':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='radio'){menu.AddSeparator();menu.AddItem('Radio',FCKLang.RadioButtonProp,50);}}};case 'TextField':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='text'||tag.type=='password')){menu.AddSeparator();menu.AddItem('TextField',FCKLang.TextFieldProp,51);}}};case 'HiddenField':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckinputhidden')){menu.AddSeparator();menu.AddItem('HiddenField',FCKLang.HiddenFieldProp,56);}}};case 'ImageButton':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='image'){menu.AddSeparator();menu.AddItem('ImageButton',FCKLang.ImageButtonProp,55);}}};case 'Button':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='button'||tag.type=='submit'||tag.type=='reset')){menu.AddSeparator();menu.AddItem('Button',FCKLang.ButtonProp,54);}}};case 'Select':return {AddItems:function(menu,tag,tagName){if (tagName=='SELECT'){menu.AddSeparator();menu.AddItem('Select',FCKLang.SelectionFieldProp,53);}}};case 'Textarea':return {AddItems:function(menu,tag,tagName){if (tagName=='TEXTAREA'){menu.AddSeparator();menu.AddItem('Textarea',FCKLang.TextareaProp,52);}}};case 'BulletedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('UL')){menu.AddSeparator();menu.AddItem('BulletedList',FCKLang.BulletedListProp,27);}}};case 'NumberedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('OL')){menu.AddSeparator();menu.AddItem('NumberedList',FCKLang.NumberedListProp,26);}}};};return null;};function FCK_ContextMenu_OnBeforeOpen(){FCK.Events.FireEvent('OnSelectionChange');var A,sTagName;if ((A=FCKSelection.GetSelectedElement())) sTagName=A.tagName;var B=FCK.ContextMenu._InnerContextMenu;B.RemoveAllItems();var C=FCK.ContextMenu.Listeners;for (var i=0;i<C.length;i++) C[i].AddItems(B,A,sTagName);};function FCK_ContextMenu_OnItemClick(A){FCK.Focus();FCKCommands.GetCommand(A.Name).Execute();};
+var FCKPlugin=function(A,B,C){this.Name=A;this.BasePath=C?C:FCKConfig.PluginsPath;this.Path=this.BasePath+A+'/';if (!B||B.length==0) this.AvailableLangs=[];else this.AvailableLangs=B.split(',');};FCKPlugin.prototype.Load=function(){if (this.AvailableLangs.length>0){var A;if (this.AvailableLangs.IndexOf(FCKLanguageManager.ActiveLanguage.Code)>=0) A=FCKLanguageManager.ActiveLanguage.Code;else A=this.AvailableLangs[0];LoadScript(this.Path+'lang/'+A+'.js');};LoadScript(this.Path+'fckplugin.js');}
+var FCKPlugins=FCK.Plugins={};FCKPlugins.ItemsCount=0;FCKPlugins.Items={};FCKPlugins.Load=function(){var A=FCKPlugins.Items;for (var i=0;i<FCKConfig.Plugins.Items.length;i++){var B=FCKConfig.Plugins.Items[i];var C=A[B[0]]=new FCKPlugin(B[0],B[1],B[2]);FCKPlugins.ItemsCount++;};for (var s in A) A[s].Load();FCKPlugins.Load=null;}
diff --git a/httemplate/elements/fckeditor/editor/js/fckeditorcode_ie.js b/httemplate/elements/fckeditor/editor/js/fckeditorcode_ie.js
new file mode 100644
index 000000000..0d4395701
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/js/fckeditorcode_ie.js
@@ -0,0 +1,99 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This file has been compressed for better performance. The original source
+ * can be found at "editor/_source".
+ */
+
+var FCK_STATUS_NOTLOADED=window.parent.FCK_STATUS_NOTLOADED=0;var FCK_STATUS_ACTIVE=window.parent.FCK_STATUS_ACTIVE=1;var FCK_STATUS_COMPLETE=window.parent.FCK_STATUS_COMPLETE=2;var FCK_TRISTATE_OFF=window.parent.FCK_TRISTATE_OFF=0;var FCK_TRISTATE_ON=window.parent.FCK_TRISTATE_ON=1;var FCK_TRISTATE_DISABLED=window.parent.FCK_TRISTATE_DISABLED=-1;var FCK_UNKNOWN=window.parent.FCK_UNKNOWN=-9;var FCK_TOOLBARITEM_ONLYICON=window.parent.FCK_TOOLBARITEM_ONLYICON=0;var FCK_TOOLBARITEM_ONLYTEXT=window.parent.FCK_TOOLBARITEM_ONLYTEXT=1;var FCK_TOOLBARITEM_ICONTEXT=window.parent.FCK_TOOLBARITEM_ICONTEXT=2;var FCK_EDITMODE_WYSIWYG=window.parent.FCK_EDITMODE_WYSIWYG=0;var FCK_EDITMODE_SOURCE=window.parent.FCK_EDITMODE_SOURCE=1;var FCK_IMAGES_PATH='images/';var FCK_SPACER_PATH='images/spacer.gif';var CTRL=1000;var SHIFT=2000;var ALT=4000;
+String.prototype.Contains=function(A){return (this.indexOf(A)>-1);};String.prototype.Equals=function(){var A=arguments;if (A.length==1&&A[0].pop) A=A[0];for (var i=0;i<A.length;i++){if (this==A[i]) return true;};return false;};String.prototype.IEquals=function(){var A=this.toUpperCase();var B=arguments;if (B.length==1&&B[0].pop) B=B[0];for (var i=0;i<B.length;i++){if (A==B[i].toUpperCase()) return true;};return false;};String.prototype.ReplaceAll=function(A,B){var C=this;for (var i=0;i<A.length;i++){C=C.replace(A[i],B[i]);};return C;};Array.prototype.AddItem=function(A){var i=this.length;this[i]=A;return i;};Array.prototype.IndexOf=function(A){for (var i=0;i<this.length;i++){if (this[i]==A) return i;};return-1;};String.prototype.StartsWith=function(A){return (this.substr(0,A.length)==A);};String.prototype.EndsWith=function(A,B){var C=this.length;var D=A.length;if (D>C) return false;if (B){var E=new RegExp(A+'$','i');return E.test(this);}else return (D==0||this.substr(C-D,D)==A);};String.prototype.Remove=function(A,B){var s='';if (A>0) s=this.substring(0,A);if (A+B<this.length) s+=this.substring(A+B,this.length);return s;};String.prototype.Trim=function(){return this.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g,'');};String.prototype.LTrim=function(){return this.replace(/^[ \t\n\r]*/g,'');};String.prototype.RTrim=function(){return this.replace(/[ \t\n\r]*$/g,'');};String.prototype.ReplaceNewLineChars=function(A){return this.replace(/\n/g,A);}
+var FCKIECleanup=function(A){if (A._FCKCleanupObj) this.Items=A._FCKCleanupObj.Items;else{this.Items=[];A._FCKCleanupObj=this;FCKTools.AddEventListenerEx(A,'unload',FCKIECleanup_Cleanup);}};FCKIECleanup.prototype.AddItem=function(A,B){this.Items.push([A,B]);};function FCKIECleanup_Cleanup(){if (!this._FCKCleanupObj) return;var A=this._FCKCleanupObj.Items;while (A.length>0){var B=A.pop();if (B) B[1].call(B[0]);};this._FCKCleanupObj=null;if (CollectGarbage) CollectGarbage();}
+var s=navigator.userAgent.toLowerCase();var FCKBrowserInfo={IsIE:s.Contains('msie'),IsIE7:s.Contains('msie 7'),IsGecko:s.Contains('gecko/'),IsSafari:s.Contains('safari'),IsOpera:s.Contains('opera'),IsMac:s.Contains('macintosh')};(function(A){A.IsGeckoLike=(A.IsGecko||A.IsSafari||A.IsOpera);if (A.IsGecko){var B=s.match(/gecko\/(\d+)/)[1];A.IsGecko10=((B<20051111)||(/rv:1\.7/.test(s)));}else A.IsGecko10=false;})(FCKBrowserInfo);
+var FCKURLParams={};(function(){var A=document.location.search.substr(1).split('&');for (var i=0;i<A.length;i++){var B=A[i].split('=');var C=decodeURIComponent(B[0]);var D=decodeURIComponent(B[1]);FCKURLParams[C]=D;}})();
+var FCKEvents=function(A){this.Owner=A;this._RegisteredEvents={};};FCKEvents.prototype.AttachEvent=function(A,B){var C;if (!(C=this._RegisteredEvents[A])) this._RegisteredEvents[A]=[B];else C.push(B);};FCKEvents.prototype.FireEvent=function(A,B){var C=true;var D=this._RegisteredEvents[A];if (D){for (var i=0;i<D.length;i++) C=(D[i](this.Owner,B)&&C);};return C;};
+var FCK={Name:FCKURLParams['InstanceName'],Status:0,EditMode:0,Toolbar:null,HasFocus:false,AttachToOnSelectionChange:function(A){this.Events.AttachEvent('OnSelectionChange',A);},GetLinkedFieldValue:function(){return this.LinkedField.value;},GetParentForm:function(){return this.LinkedField.form;},StartupValue:'',IsDirty:function(){if (this.EditMode==1) return (this.StartupValue!=this.EditingArea.Textarea.value);else return (this.StartupValue!=this.EditorDocument.body.innerHTML);},ResetIsDirty:function(){if (this.EditMode==1) this.StartupValue=this.EditingArea.Textarea.value;else if (this.EditorDocument.body) this.StartupValue=this.EditorDocument.body.innerHTML;},StartEditor:function(){this.TempBaseTag=FCKConfig.BaseHref.length>0?'<base href="'+FCKConfig.BaseHref+'" _fcktemp="true"></base>':'';var A=FCK.KeystrokeHandler=new FCKKeystrokeHandler();A.OnKeystroke=_FCK_KeystrokeHandler_OnKeystroke;A.SetKeystrokes(FCKConfig.Keystrokes);if (FCKBrowserInfo.IsIE7){if ((CTRL+86/*V*/) in A.Keystrokes) A.SetKeystrokes([CTRL+86,true]);if ((SHIFT+45/*INS*/) in A.Keystrokes) A.SetKeystrokes([SHIFT+45,true]);};this.EditingArea=new FCKEditingArea(document.getElementById('xEditingArea'));this.EditingArea.FFSpellChecker=FCKConfig.FirefoxSpellChecker;FCKListsLib.Setup();this.SetHTML(this.GetLinkedFieldValue(),true);},Focus:function(){FCK.EditingArea.Focus();},SetStatus:function(A){this.Status=A;if (A==1){FCKFocusManager.AddWindow(window,true);if (FCKBrowserInfo.IsIE) FCKFocusManager.AddWindow(window.frameElement,true);if (FCKConfig.StartupFocus) FCK.Focus();};this.Events.FireEvent('OnStatusChange',A);},FixBody:function(){var A=FCKConfig.EnterMode;if (A!='p'&&A!='div') return;var B=this.EditorDocument;if (!B) return;var C=B.body;if (!C) return;FCKDomTools.TrimNode(C);var D=C.firstChild;var E;while (D){var F=false;switch (D.nodeType){case 1:if (!FCKListsLib.BlockElements[D.nodeName.toLowerCase()]) F=true;break;case 3:if (E||D.nodeValue.Trim().length>0) F=true;};if (F){var G=D.parentNode;if (!E) E=G.insertBefore(B.createElement(A),D);E.appendChild(G.removeChild(D));D=E.nextSibling;}else{if (E){FCKDomTools.TrimNode(E);E=null;};D=D.nextSibling;}};if (E) FCKDomTools.TrimNode(E);},GetXHTML:function(A){if (FCK.EditMode==1) return FCK.EditingArea.Textarea.value;this.FixBody();var B;var C=FCK.EditorDocument;if (!C) return null;if (FCKConfig.FullPage){B=FCKXHtml.GetXHTML(C.getElementsByTagName('html')[0],true,A);if (FCK.DocTypeDeclaration&&FCK.DocTypeDeclaration.length>0) B=FCK.DocTypeDeclaration+'\n'+B;if (FCK.XmlDeclaration&&FCK.XmlDeclaration.length>0) B=FCK.XmlDeclaration+'\n'+B;}else{B=FCKXHtml.GetXHTML(C.body,false,A);if (FCKConfig.IgnoreEmptyParagraphValue&&FCKRegexLib.EmptyOutParagraph.test(B)) B='';};B=FCK.ProtectEventsRestore(B);if (FCKBrowserInfo.IsIE) B=B.replace(FCKRegexLib.ToReplace,'$1');return FCKConfig.ProtectedSource.Revert(B);},UpdateLinkedField:function(){FCK.LinkedField.value=FCK.GetXHTML(FCKConfig.FormatOutput);FCK.Events.FireEvent('OnAfterLinkedFieldUpdate');},RegisteredDoubleClickHandlers:{},OnDoubleClick:function(A){var B=FCK.RegisteredDoubleClickHandlers[A.tagName];if (B) B(A);},RegisterDoubleClickHandler:function(A,B){FCK.RegisteredDoubleClickHandlers[B.toUpperCase()]=A;},OnAfterSetHTML:function(){FCKDocumentProcessor.Process(FCK.EditorDocument);FCKUndo.SaveUndoStep();FCK.Events.FireEvent('OnSelectionChange');FCK.Events.FireEvent('OnAfterSetHTML');},ProtectUrls:function(A){A=A.replace(FCKRegexLib.ProtectUrlsA,'$& _fcksavedurl=$1');A=A.replace(FCKRegexLib.ProtectUrlsImg,'$& _fcksavedurl=$1');return A;},ProtectEvents:function(A){return A.replace(FCKRegexLib.TagsWithEvent,_FCK_ProtectEvents_ReplaceTags);},ProtectEventsRestore:function(A){return A.replace(FCKRegexLib.ProtectedEvents,_FCK_ProtectEvents_RestoreEvents);},ProtectTags:function(A){var B=FCKConfig.ProtectedTags;if (FCKBrowserInfo.IsIE) B+=B.length>0?'|ABBR|XML':'ABBR|XML';var C;if (B.length>0){C=new RegExp('<('+B+')(?!\w|:)','gi');A=A.replace(C,'<FCK:$1');C=new RegExp('<\/('+B+')>','gi');A=A.replace(C,'<\/FCK:$1>');};B='META';if (FCKBrowserInfo.IsIE) B+='|HR';C=new RegExp('<(('+B+')(?=\\s|>|/)[\\s\\S]*?)/?>','gi');A=A.replace(C,'<FCK:$1 />');return A;},SetHTML:function(A,B){this.EditingArea.Mode=FCK.EditMode;if (FCK.EditMode==0){A=FCKConfig.ProtectedSource.Protect(A);A=A.replace(FCKRegexLib.InvalidSelfCloseTags,'$1></$2>');A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);if (FCKBrowserInfo.IsGecko){A=A.replace(FCKRegexLib.StrongOpener,'<b$1');A=A.replace(FCKRegexLib.StrongCloser,'<\/b>');A=A.replace(FCKRegexLib.EmOpener,'<i$1');A=A.replace(FCKRegexLib.EmCloser,'<\/i>');};this._ForceResetIsDirty=(B===true);var C='';if (FCKConfig.FullPage){if (!FCKRegexLib.HeadOpener.test(A)){if (!FCKRegexLib.HtmlOpener.test(A)) A='<html dir="'+FCKConfig.ContentLangDirection+'">'+A+'</html>';A=A.replace(FCKRegexLib.HtmlOpener,'$&<head></head>');};FCK.DocTypeDeclaration=A.match(FCKRegexLib.DocTypeTag);if (FCKBrowserInfo.IsIE) C=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C='<link href="'+FCKConfig.FullBasePath+'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C+='<link href="'+FCKConfig.FullBasePath+'css/fck_internal.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C=A.replace(FCKRegexLib.HeadCloser,C+'$&');if (FCK.TempBaseTag.length>0&&!FCKRegexLib.HasBaseTag.test(A)) C=C.replace(FCKRegexLib.HeadOpener,'$&'+FCK.TempBaseTag);}else{C=FCKConfig.DocType+'<html dir="'+FCKConfig.ContentLangDirection+'"';if (FCKBrowserInfo.IsIE&&!FCKRegexLib.Html4DocType.test(FCKConfig.DocType)) C+=' style="overflow-y: scroll"';C+='><head><title></title>'+_FCK_GetEditorAreaStyleTags()+'<link href="'+FCKConfig.FullBasePath+'css/fck_internal.css" rel="stylesheet" type="text/css" _fcktemp="true" />';if (FCKBrowserInfo.IsIE) C+=FCK._GetBehaviorsStyle();else if (FCKConfig.ShowBorders) C+='<link href="'+FCKConfig.FullBasePath+'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />';C+=FCK.TempBaseTag;var D='<body';if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) D+=' id="'+FCKConfig.BodyId+'"';if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) D+=' class="'+FCKConfig.BodyClass+'"';C+='</head>'+D+'>';if (FCKBrowserInfo.IsGecko&&(A.length==0||FCKRegexLib.EmptyParagraph.test(A))) C+=GECKO_BOGUS;else C+=A;C+='</body></html>';};this.EditingArea.OnLoad=_FCK_EditingArea_OnLoad;this.EditingArea.Start(C);}else{FCK.EditorWindow=null;FCK.EditorDocument=null;this.EditingArea.OnLoad=null;this.EditingArea.Start(A);this.EditingArea.Textarea._FCKShowContextMenu=true;FCK.EnterKeyHandler=null;if (B) this.ResetIsDirty();FCK.KeystrokeHandler.AttachToElement(this.EditingArea.Textarea);this.EditingArea.Textarea.focus();FCK.Events.FireEvent('OnAfterSetHTML');};if (FCKBrowserInfo.IsGecko) window.onresize();},HasFocus:false,RedirectNamedCommands:{},ExecuteNamedCommand:function(A,B,C){FCKUndo.SaveUndoStep();if (!C&&FCK.RedirectNamedCommands[A]!=null) FCK.ExecuteRedirectedNamedCommand(A,B);else{FCK.Focus();FCK.EditorDocument.execCommand(A,false,B);FCK.Events.FireEvent('OnSelectionChange');};FCKUndo.SaveUndoStep();},GetNamedCommandState:function(A){try{if (!FCK.EditorDocument.queryCommandEnabled(A)) return -1;else return FCK.EditorDocument.queryCommandState(A)?1:0;}catch (e){return 0;}},GetNamedCommandValue:function(A){var B='';var C=FCK.GetNamedCommandState(A);if (C==-1) return null;try{B=this.EditorDocument.queryCommandValue(A);}catch(e) {};return B?B:'';},PasteFromWord:function(){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteFromWord,'dialog/fck_paste.html',400,330,'Word');},Preview:function(){var A=FCKConfig.ScreenWidth*0.8;var B=FCKConfig.ScreenHeight*0.7;var C=(FCKConfig.ScreenWidth-A)/2;var D=window.open('',null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+A+',height='+B+',left='+C);var E;if (FCKConfig.FullPage){if (FCK.TempBaseTag.length>0) E=FCK.TempBaseTag+FCK.GetXHTML();else E=FCK.GetXHTML();}else{E=FCKConfig.DocType+'<html dir="'+FCKConfig.ContentLangDirection+'"><head>'+FCK.TempBaseTag+'<title>'+FCKLang.Preview+'</title>'+_FCK_GetEditorAreaStyleTags()+'</head><body>'+FCK.GetXHTML()+'</body></html>';};D.document.write(E);D.document.close();},SwitchEditMode:function(A){var B=(FCK.EditMode==0);var C=FCK.IsDirty();var D;if (B){if (!A&&FCKBrowserInfo.IsIE) FCKUndo.SaveUndoStep();D=FCK.GetXHTML(FCKConfig.FormatSource);if (D==null) return false;}else D=this.EditingArea.Textarea.value;FCK.EditMode=B?1:0;FCK.SetHTML(D,!C);FCK.Focus();FCKTools.RunFunction(FCK.ToolbarSet.RefreshModeState,FCK.ToolbarSet);return true;},CreateElement:function(A){var e=FCK.EditorDocument.createElement(A);return FCK.InsertElementAndGetIt(e);},InsertElementAndGetIt:function(e){e.setAttribute('FCKTempLabel','true');this.InsertElement(e);var A=FCK.EditorDocument.getElementsByTagName(e.tagName);for (var i=0;i<A.length;i++){if (A[i].getAttribute('FCKTempLabel')){A[i].removeAttribute('FCKTempLabel');return A[i];}};return null;}};FCK.Events=new FCKEvents(FCK);FCK.GetHTML=FCK.GetXHTML;function _FCK_ProtectEvents_ReplaceTags(A){return A.replace(FCKRegexLib.EventAttributes,_FCK_ProtectEvents_ReplaceEvents);};function _FCK_ProtectEvents_ReplaceEvents(A,B){return ' '+B+'_fckprotectedatt="'+A.ReplaceAll([/&/g,/'/g,/"/g,/=/g,/</g,/>/g,/\r/g,/\n/g],['&apos;','&#39;','&quot;','&#61;','&lt;','&gt;','&#10;','&#13;'])+'"';};function _FCK_ProtectEvents_RestoreEvents(A,B){return B.ReplaceAll([/&#39;/g,/&quot;/g,/&#61;/g,/&lt;/g,/&gt;/g,/&#10;/g,/&#13;/g,/&apos;/g],["'",'"','=','<','>','\r','\n','&']);};function _FCK_EditingArea_OnLoad(){FCK.EditorWindow=FCK.EditingArea.Window;FCK.EditorDocument=FCK.EditingArea.Document;FCK.InitializeBehaviors();if (!FCKConfig.DisableEnterKeyHandler) FCK.EnterKeyHandler=new FCKEnterKey(FCK.EditorWindow,FCKConfig.EnterMode,FCKConfig.ShiftEnterMode);FCK.KeystrokeHandler.AttachToElement(FCK.EditorDocument);if (FCK._ForceResetIsDirty) FCK.ResetIsDirty();if (FCKBrowserInfo.IsIE&&FCK.HasFocus) FCK.EditorDocument.body.setActive();FCK.OnAfterSetHTML();if (FCK.Status!=0) return;FCK.SetStatus(1);};function _FCK_GetEditorAreaStyleTags(){var A='';var B=FCKConfig.EditorAreaCSS;for (var i=0;i<B.length;i++) A+='<link href="'+B[i]+'" rel="stylesheet" type="text/css" />';return A;};function _FCK_KeystrokeHandler_OnKeystroke(A,B){if (FCK.Status!=2) return false;if (FCK.EditMode==0){if (B=='Paste') return!FCK.Events.FireEvent('OnPaste');}else{if (B.Equals('Paste','Undo','Redo','SelectAll')) return false;};var C=FCK.Commands.GetCommand(B);return (C.Execute.apply(C,FCKTools.ArgumentsToArray(arguments,2))!==false);};(function(){var A=window.parent.document;var B=A.getElementById(FCK.Name);var i=0;while (B||i==0){if (B&&B.tagName.toLowerCase().Equals('input','textarea')){FCK.LinkedField=B;break;};B=A.getElementsByName(FCK.Name)[i++];}})();var FCKTempBin={Elements:[],AddElement:function(A){var B=this.Elements.length;this.Elements[B]=A;return B;},RemoveElement:function(A){var e=this.Elements[A];this.Elements[A]=null;return e;},Reset:function(){var i=0;while (i<this.Elements.length) this.Elements[i++]=null;this.Elements.length=0;}};var FCKFocusManager=FCK.FocusManager={IsLocked:false,AddWindow:function(A,B){var C;if (FCKBrowserInfo.IsIE) C=A.nodeType==1?A:A.frameElement?A.frameElement:A.document;else C=A.document;FCKTools.AddEventListener(C,'blur',FCKFocusManager_Win_OnBlur);FCKTools.AddEventListener(C,'focus',B?FCKFocusManager_Win_OnFocus_Area:FCKFocusManager_Win_OnFocus);},RemoveWindow:function(A){if (FCKBrowserInfo.IsIE) oTarget=A.nodeType==1?A:A.frameElement?A.frameElement:A.document;else oTarget=A.document;FCKTools.RemoveEventListener(oTarget,'blur',FCKFocusManager_Win_OnBlur);FCKTools.RemoveEventListener(oTarget,'focus',FCKFocusManager_Win_OnFocus_Area);FCKTools.RemoveEventListener(oTarget,'focus',FCKFocusManager_Win_OnFocus);},Lock:function(){this.IsLocked=true;},Unlock:function(){if (this._HasPendingBlur) FCKFocusManager._Timer=window.setTimeout(FCKFocusManager_FireOnBlur,100);this.IsLocked=false;},_ResetTimer:function(){this._HasPendingBlur=false;if (this._Timer){window.clearTimeout(this._Timer);delete this._Timer;}}};function FCKFocusManager_Win_OnBlur(){if (typeof(FCK)!='undefined'&&FCK.HasFocus){FCKFocusManager._ResetTimer();FCKFocusManager._Timer=window.setTimeout(FCKFocusManager_FireOnBlur,100);}};function FCKFocusManager_FireOnBlur(){if (FCKFocusManager.IsLocked) FCKFocusManager._HasPendingBlur=true;else{FCK.HasFocus=false;FCK.Events.FireEvent("OnBlur");}};function FCKFocusManager_Win_OnFocus_Area(){FCK.Focus();FCKFocusManager_Win_OnFocus();};function FCKFocusManager_Win_OnFocus(){FCKFocusManager._ResetTimer();if (!FCK.HasFocus&&!FCKFocusManager.IsLocked){FCK.HasFocus=true;FCK.Events.FireEvent("OnFocus");}};
+FCK.Description="FCKeditor for Internet Explorer 5.5+";FCK._GetBehaviorsStyle=function(){if (!FCK._BehaviorsStyle){var A=FCKConfig.FullBasePath;var B='';var C;C='<style type="text/css" _fcktemp="true">';if (FCKConfig.ShowBorders) B='url('+A+'css/behaviors/showtableborders.htc)';C+='INPUT,TEXTAREA,SELECT,.FCK__Anchor,.FCK__PageBreak,.FCK__InputHidden';if (FCKConfig.DisableObjectResizing){C+=',IMG';B+=' url('+A+'css/behaviors/disablehandles.htc)';};C+=' { behavior: url('+A+'css/behaviors/disablehandles.htc) ; }';if (B.length>0) C+='TABLE { behavior: '+B+' ; }';C+='</style>';FCK._BehaviorsStyle=C;};return FCK._BehaviorsStyle;};function Doc_OnMouseUp(){if (FCK.EditorWindow.event.srcElement.tagName=='HTML'){FCK.Focus();FCK.EditorWindow.event.cancelBubble=true;FCK.EditorWindow.event.returnValue=false;}};function Doc_OnPaste(){return (FCK.Status==2&&FCK.Events.FireEvent("OnPaste"));};function Doc_OnKeyDown(){if (FCK.EditorWindow){var e=FCK.EditorWindow.event;if (!(e.keyCode>=16&&e.keyCode<=18)) Doc_OnKeyDownUndo();};return true;};function Doc_OnKeyDownUndo(){if (!FCKUndo.Typing){FCKUndo.SaveUndoStep();FCKUndo.Typing=true;FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.TypesCount++;if (FCKUndo.TypesCount>FCKUndo.MaxTypes){FCKUndo.TypesCount=0;FCKUndo.SaveUndoStep();}};function Doc_OnDblClick(){FCK.OnDoubleClick(FCK.EditorWindow.event.srcElement);FCK.EditorWindow.event.cancelBubble=true;};function Doc_OnSelectionChange(){FCK.Events.FireEvent("OnSelectionChange");};FCK.InitializeBehaviors=function(A){this.EditorDocument.attachEvent('onmouseup',Doc_OnMouseUp);this.EditorDocument.body.attachEvent('onpaste',Doc_OnPaste);FCK.ContextMenu._InnerContextMenu.AttachToElement(FCK.EditorDocument.body);if (FCKConfig.TabSpaces>0){window.FCKTabHTML='';for (i=0;i<FCKConfig.TabSpaces;i++) window.FCKTabHTML+="&nbsp;";};this.EditorDocument.attachEvent("onkeydown",Doc_OnKeyDown);this.EditorDocument.attachEvent("ondblclick",Doc_OnDblClick);this.EditorDocument.attachEvent("onselectionchange",Doc_OnSelectionChange);};FCK.InsertHtml=function(A){A=FCKConfig.ProtectedSource.Protect(A);A=FCK.ProtectEvents(A);A=FCK.ProtectUrls(A);A=FCK.ProtectTags(A);FCK.EditorWindow.focus();FCKUndo.SaveUndoStep();var B=FCK.EditorDocument.selection;if (B.type.toLowerCase()=='control') B.clear();A='<span id="__fakeFCKRemove__">&nbsp;</span>'+A;B.createRange().pasteHTML(A);FCK.EditorDocument.getElementById('__fakeFCKRemove__').removeNode(true);FCKDocumentProcessor.Process(FCK.EditorDocument);};FCK.SetInnerHtml=function(A){var B=FCK.EditorDocument;B.body.innerHTML='<div id="__fakeFCKRemove__">&nbsp;</div>'+A;B.getElementById('__fakeFCKRemove__').removeNode(true);};function FCK_PreloadImages(){var A=new FCKImagePreloader();A.AddImages(FCKConfig.PreloadImages);A.AddImages(FCKConfig.SkinPath+'fck_strip.gif');A.OnComplete=LoadToolbarSetup;A.Start();};function Document_OnContextMenu(){return (event.srcElement._FCKShowContextMenu==true);};document.oncontextmenu=Document_OnContextMenu;function FCK_Cleanup(){this.EditorWindow=null;this.EditorDocument=null;};FCK.Paste=function(){if (FCK._PasteIsRunning) return true;if (FCKConfig.ForcePasteAsPlainText){FCK.PasteAsPlainText();return false;};var A=FCK._CheckIsPastingEnabled(true);if (A===false) FCKTools.RunFunction(FCKDialog.OpenDialog,FCKDialog,['FCKDialog_Paste',FCKLang.Paste,'dialog/fck_paste.html',400,330,'Security']);else{if (FCKConfig.AutoDetectPasteFromWord&&A.length>0){var B=/<\w[^>]*(( class="?MsoNormal"?)|(="mso-))/gi;if (B.test(A)){if (confirm(FCKLang.PasteWordConfirm)){FCK.PasteFromWord();return false;}}};FCK._PasteIsRunning=true;FCK.ExecuteNamedCommand('Paste');delete FCK._PasteIsRunning;};return false;};FCK.PasteAsPlainText=function(){if (!FCK._CheckIsPastingEnabled()){FCKDialog.OpenDialog('FCKDialog_Paste',FCKLang.PasteAsText,'dialog/fck_paste.html',400,330,'PlainText');return;};var A=clipboardData.getData("Text");if (A&&A.length>0){A=FCKTools.HTMLEncode(A).replace(/\n/g,'<BR>');this.InsertHtml(A);}};FCK._CheckIsPastingEnabled=function(A){FCK._PasteIsEnabled=false;document.body.attachEvent('onpaste',FCK_CheckPasting_Listener);var B=FCK.GetClipboardHTML();document.body.detachEvent('onpaste',FCK_CheckPasting_Listener);if (FCK._PasteIsEnabled){if (!A) B=true;}else B=false;delete FCK._PasteIsEnabled;return B;};function FCK_CheckPasting_Listener(){FCK._PasteIsEnabled=true;};FCK.InsertElement=function(A){FCK.InsertHtml(A.outerHTML);};FCK.GetClipboardHTML=function(){var A=document.getElementById('___FCKHiddenDiv');if (!A){A=document.createElement('DIV');A.id='___FCKHiddenDiv';var B=A.style;B.position='absolute';B.visibility=B.overflow='hidden';B.width=B.height=1;document.body.appendChild(A);};A.innerHTML='';var C=document.body.createTextRange();C.moveToElementText(A);C.execCommand('Paste');var D=A.innerHTML;A.innerHTML='';return D;};FCK.CreateLink=function(A){var B=[];FCK.ExecuteNamedCommand('Unlink');if (A.length>0){if (FCKSelection.GetType()=='Control'){var C=this.EditorDocument.createElement('A');C.href=A;var D=FCKSelection.GetSelectedElement();D.parentNode.insertBefore(C,D);D.parentNode.removeChild(D);C.appendChild(D);return [C];};var E='javascript:void(0);/*'+(new Date().getTime())+'*/';FCK.ExecuteNamedCommand('CreateLink',E);var F=this.EditorDocument.links;for (i=0;i<F.length;i++){var C=F[i];if (C.getAttribute('href',2)==E){var H=C.innerHTML;C.href=A;C.innerHTML=H;var I=C.lastChild;if (I&&I.nodeName=='BR'){FCKDomTools.InsertAfterNode(C,C.removeChild(I));};B.push(C);}}};return B;};
+var FCKConfig=FCK.Config={};if (document.location.protocol=='file:'){FCKConfig.BasePath=decodeURIComponent(document.location.pathname.substr(1));FCKConfig.BasePath=FCKConfig.BasePath.replace(/\\/gi, '/');FCKConfig.BasePath='file://'+FCKConfig.BasePath.substring(0,FCKConfig.BasePath.lastIndexOf('/')+1);FCKConfig.FullBasePath=FCKConfig.BasePath;}else{FCKConfig.BasePath=document.location.pathname.substring(0,document.location.pathname.lastIndexOf('/')+1);FCKConfig.FullBasePath=document.location.protocol+'//'+document.location.host+FCKConfig.BasePath;};FCKConfig.EditorPath=FCKConfig.BasePath.replace(/editor\/$/,'');try{FCKConfig.ScreenWidth=screen.width;FCKConfig.ScreenHeight=screen.height;}catch (e){FCKConfig.ScreenWidth=800;FCKConfig.ScreenHeight=600;};FCKConfig.ProcessHiddenField=function(){this.PageConfig={};var A=window.parent.document.getElementById(FCK.Name+'___Config');if (!A) return;var B=A.value.split('&');for (var i=0;i<B.length;i++){if (B[i].length==0) continue;var C=B[i].split('=');var D=decodeURIComponent(C[0]);var E=decodeURIComponent(C[1]);if (D=='CustomConfigurationsPath') FCKConfig[D]=E;else if (E.toLowerCase()=="true") this.PageConfig[D]=true;else if (E.toLowerCase()=="false") this.PageConfig[D]=false;else if (E.length>0&&!isNaN(E)) this.PageConfig[D]=parseInt(E,10);else this.PageConfig[D]=E;}};function FCKConfig_LoadPageConfig(){var A=FCKConfig.PageConfig;for (var B in A) FCKConfig[B]=A[B];};function FCKConfig_PreProcess(){var A=FCKConfig;if (A.AllowQueryStringDebug){try{if ((/fckdebug=true/i).test(window.top.location.search)) A.Debug=true;}catch (e) {/*Ignore it. Much probably we are inside a FRAME where the "top" is in another domain (security error).*/}};if (!A.PluginsPath.EndsWith('/')) A.PluginsPath+='/';if (typeof(A.EditorAreaCSS)=='string') A.EditorAreaCSS=[A.EditorAreaCSS];var B=A.ToolbarComboPreviewCSS;if (!B||B.length==0) A.ToolbarComboPreviewCSS=A.EditorAreaCSS;else if (typeof(B)=='string') A.ToolbarComboPreviewCSS=[B];};FCKConfig.ToolbarSets={};FCKConfig.Plugins={};FCKConfig.Plugins.Items=[];FCKConfig.Plugins.Add=function(A,B,C){FCKConfig.Plugins.Items.AddItem([A,B,C]);};FCKConfig.ProtectedSource={};FCKConfig.ProtectedSource.RegexEntries=[/<!--[\s\S]*?-->/g,/<script[\s\S]*?<\/script>/gi,/<noscript[\s\S]*?<\/noscript>/gi,/<object[\s\S]+?<\/object>/gi];FCKConfig.ProtectedSource.Add=function(A){this.RegexEntries.AddItem(A);};FCKConfig.ProtectedSource.Protect=function(A){function _Replace(protectedSource){var B=FCKTempBin.AddElement(protectedSource);return '<!--{PS..'+B+'}-->';};for (var i=0;i<this.RegexEntries.length;i++){A=A.replace(this.RegexEntries[i],_Replace);};return A;};FCKConfig.ProtectedSource.Revert=function(A,B){function _Replace(m,opener,index){var C=B?FCKTempBin.RemoveElement(index):FCKTempBin.Elements[index];return FCKConfig.ProtectedSource.Revert(C,B);};return A.replace(/(<|&lt;)!--\{PS..(\d+)\}--(>|&gt;)/g,_Replace);}
+var FCKDebug={};FCKDebug._GetWindow=function(){if (!this.DebugWindow||this.DebugWindow.closed) this.DebugWindow=window.open(FCKConfig.BasePath+'fckdebug.html','FCKeditorDebug','menubar=no,scrollbars=yes,resizable=yes,location=no,toolbar=no,width=600,height=500',true);return this.DebugWindow;};FCKDebug.Output=function(A,B,C){if (!FCKConfig.Debug) return;try{this._GetWindow().Output(A,B);}catch (e) {}};FCKDebug.OutputObject=function(A,B){if (!FCKConfig.Debug) return;try{this._GetWindow().OutputObject(A,B);}catch (e) {}}
+var FCKDomTools={MoveChildren:function(A,B){if (A==B) return;var C;while ((C=A.firstChild)) B.appendChild(A.removeChild(C));},TrimNode:function(A,B){this.LTrimNode(A);this.RTrimNode(A,B);},LTrimNode:function(A){var B;while ((B=A.firstChild)){if (B.nodeType==3){var C=B.nodeValue.LTrim();var D=B.nodeValue.length;if (C.length==0){A.removeChild(B);continue;}else if (C.length<D){B.splitText(D-C.length);A.removeChild(A.firstChild);}};break;}},RTrimNode:function(A,B){var C;while ((C=A.lastChild)){switch (C.nodeType){case 1:if (C.nodeName.toUpperCase()=='BR'&&(B||C.getAttribute('type',2)=='_moz')){C.parentNode.removeChild(C);continue;};break;case 3:var D=C.nodeValue.RTrim();var E=C.nodeValue.length;if (D.length==0){C.parentNode.removeChild(C);continue;}else if (D.length<E){C.splitText(D.length);A.lastChild.parentNode.removeChild(A.lastChild);}};break;}},RemoveNode:function(A,B){if (B){var C;while ((C=A.firstChild)) A.parentNode.insertBefore(A.removeChild(C),A);};return A.parentNode.removeChild(A);},GetFirstChild:function(A,B){if (typeof (B)=='string') B=[B];var C=A.firstChild;while(C){if (C.nodeType==1&&C.tagName.Equals.apply(C.tagName,B)) return C;C=C.nextSibling;};return null;},GetLastChild:function(A,B){if (typeof (B)=='string') B=[B];var C=A.lastChild;while(C){if (C.nodeType==1&&(!B||C.tagName.Equals(B))) return C;C=C.previousSibling;};return null;},GetPreviousSourceElement:function(A,B,C,D){if (!A) return null;if (C&&A.nodeType==1&&A.nodeName.IEquals(C)) return null;if (A.previousSibling) A=A.previousSibling;else return this.GetPreviousSourceElement(A.parentNode,B,C,D);while (A){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (!D||!A.nodeName.IEquals(D)) return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;if (A.lastChild) A=A.lastChild;else return this.GetPreviousSourceElement(A,B,C,D);};return null;},GetNextSourceElement:function(A,B,C,D){if (!A) return null;if (A.nextSibling) A=A.nextSibling;else return this.GetNextSourceElement(A.parentNode,B,C,D);while (A){if (A.nodeType==1){if (C&&A.nodeName.IEquals(C)) break;if (!D||!A.nodeName.IEquals(D)) return A;}else if (B&&A.nodeType==3&&A.nodeValue.RTrim().length>0) break;if (A.firstChild) A=A.firstChild;else return this.GetNextSourceElement(A,B,C,D);};return null;},InsertAfterNode:function(A,B){return A.parentNode.insertBefore(B,A.nextSibling);},GetParents:function(A){var B=[];while (A){B.splice(0,0,A);A=A.parentNode;};return B;},GetIndexOf:function(A){var B=A.parentNode?A.parentNode.firstChild:null;var C=-1;while (B){C++;if (B==A) return C;B=B.nextSibling;};return-1;}};
+var GECKO_BOGUS='<br type="_moz">';var FCKTools={};FCKTools.CreateBogusBR=function(A){var B=A.createElement('br');B.setAttribute('type','_moz');return B;};FCKTools.AppendStyleSheet=function(A,B){if (typeof(B)=='string') return this._AppendStyleSheet(A,B);else{var C=[];for (var i=0;i<B.length;i++) C.push(this._AppendStyleSheet(A,B[i]));return C;}};FCKTools.GetElementDocument=function (A){return A.ownerDocument||A.document;};FCKTools.GetElementWindow=function(A){return this.GetDocumentWindow(this.GetElementDocument(A));};FCKTools.GetDocumentWindow=function(A){if (FCKBrowserInfo.IsSafari&&!A.parentWindow) this.FixDocumentParentWindow(window.top);return A.parentWindow||A.defaultView;};FCKTools.FixDocumentParentWindow=function(A){A.document.parentWindow=A;for (var i=0;i<A.frames.length;i++) FCKTools.FixDocumentParentWindow(A.frames[i]);};FCKTools.HTMLEncode=function(A){if (!A) return '';A=A.replace(/&/g,'&amp;');A=A.replace(/</g,'&lt;');A=A.replace(/>/g,'&gt;');return A;};FCKTools.HTMLDecode=function(A){if (!A) return '';A=A.replace(/&gt;/g,'>');A=A.replace(/&lt;/g,'<');A=A.replace(/&amp;/g,'&');return A;};FCKTools.AddSelectOption=function(A,B,C){var D=FCKTools.GetElementDocument(A).createElement("OPTION");D.text=B;D.value=C;A.options.add(D);return D;};FCKTools.RunFunction=function(A,B,C,D){if (A) this.SetTimeout(A,0,B,C,D);};FCKTools.SetTimeout=function(A,B,C,D,E){return (E||window).setTimeout(function(){if (D) A.apply(C,[].concat(D));else A.apply(C);},B);};FCKTools.SetInterval=function(A,B,C,D,E){return (E||window).setInterval(function(){A.apply(C,D||[]);},B);};FCKTools.ConvertStyleSizeToHtml=function(A){return A.EndsWith('%')?A:parseInt(A,10);};FCKTools.ConvertHtmlSizeToStyle=function(A){return A.EndsWith('%')?A:(A+'px');};FCKTools.GetElementAscensor=function(A,B){var e=A;var C=","+B.toUpperCase()+",";while (e){if (C.indexOf(","+e.nodeName.toUpperCase()+",")!=-1) return e;e=e.parentNode;};return null;};FCKTools.CreateEventListener=function(A,B){var f=function(){var C=[];for (var i=0;i<arguments.length;i++) C.push(arguments[i]);A.apply(this,C.concat(B));};return f;};FCKTools.IsStrictMode=function(A){return ('CSS1Compat'==(A.compatMode||'CSS1Compat'));};FCKTools.ArgumentsToArray=function(A,B,C){B=B||0;C=C||A.length;var D=[];for (var i=B;i<B+C&&i<A.length;i++) D.push(A[i]);return D;};FCKTools.CloneObject=function(A){var B=function() {};B.prototype=A;return new B;};FCKTools.GetLastItem=function(A){if (A.length>0) return A[A.length-1];return null;};
+FCKTools.CancelEvent=function(e){return false;};FCKTools._AppendStyleSheet=function(A,B){return A.createStyleSheet(B).owningElement;};FCKTools.ClearElementAttributes=function(A){A.clearAttributes();};FCKTools.GetAllChildrenIds=function(A){var B=[];for (var i=0;i<A.all.length;i++){var C=A.all[i].id;if (C&&C.length>0) B[B.length]=C;};return B;};FCKTools.RemoveOuterTags=function(e){e.insertAdjacentHTML('beforeBegin',e.innerHTML);e.parentNode.removeChild(e);};FCKTools.CreateXmlObject=function(A){var B;switch (A){case 'XmlHttp':B=['MSXML2.XmlHttp','Microsoft.XmlHttp'];break;case 'DOMDocument':B=['MSXML2.DOMDocument','Microsoft.XmlDom'];break;};for (var i=0;i<2;i++){try { return new ActiveXObject(B[i]);}catch (e){}};if (FCKLang.NoActiveX){alert(FCKLang.NoActiveX);FCKLang.NoActiveX=null;};return null;};FCKTools.DisableSelection=function(A){A.unselectable='on';var e,i=0;while ((e=A.all[i++])){switch (e.tagName){case 'IFRAME':case 'TEXTAREA':case 'INPUT':case 'SELECT':break;default:e.unselectable='on';}}};FCKTools.GetScrollPosition=function(A){var B=A.document;var C={ X:B.documentElement.scrollLeft,Y:B.documentElement.scrollTop };if (C.X>0||C.Y>0) return C;return { X:B.body.scrollLeft,Y:B.body.scrollTop };};FCKTools.AddEventListener=function(A,B,C){A.attachEvent('on'+B,C);};FCKTools.RemoveEventListener=function(A,B,C){A.detachEvent('on'+B,C);};FCKTools.AddEventListenerEx=function(A,B,C,D){var o={};o.Source=A;o.Params=D||[];o.Listener=function(ev){return C.apply(o.Source,[ev].concat(o.Params));};if (FCK.IECleanup) FCK.IECleanup.AddItem(null,function() { o.Source=null;o.Params=null;});A.attachEvent('on'+B,o.Listener);A=null;D=null;};FCKTools.GetViewPaneSize=function(A){var B;var C=A.document.documentElement;if (C&&C.clientWidth) B=C;else B=top.document.body;if (B) return { Width:B.clientWidth,Height:B.clientHeight };else return { Width:0,Height:0 };};FCKTools.SaveStyles=function(A){var B={};if (A.className.length>0){B.Class=A.className;A.className='';};var C=A.style.cssText;if (C.length>0){B.Inline=C;A.style.cssText='';};return B;};FCKTools.RestoreStyles=function(A,B){A.className=B.Class||'';A.style.cssText=B.Inline||'';};FCKTools.RegisterDollarFunction=function(A){A.$=A.document.getElementById;};FCKTools.AppendElement=function(A,B){return A.appendChild(this.GetElementDocument(A).createElement(B));};FCKTools.ToLowerCase=function(A){return A.toLowerCase();}
+var FCKeditorAPI;function InitializeAPI(){var A=window.parent;if (!(FCKeditorAPI=A.FCKeditorAPI)){var B='var FCKeditorAPI = {Version : "2.4.3",VersionBuild : "15657",__Instances : new Object(),GetInstance : function( name ){return this.__Instances[ name ];},_FormSubmit : function(){for ( var name in FCKeditorAPI.__Instances ){var oEditor = FCKeditorAPI.__Instances[ name ] ;if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )oEditor.UpdateLinkedField() ;}this._FCKOriginalSubmit() ;},_FunctionQueue : {Functions : new Array(),IsRunning : false,Add : function( f ){this.Functions.push( f );if ( !this.IsRunning )this.StartNext();},StartNext : function(){var aQueue = this.Functions ;if ( aQueue.length > 0 ){this.IsRunning = true;aQueue[0].call();}else this.IsRunning = false;},Remove : function( f ){var aQueue = this.Functions;var i = 0, fFunc;while( (fFunc = aQueue[ i ]) ){if ( fFunc == f )aQueue.splice( i,1 );i++ ;}this.StartNext();}}}';if (A.execScript) A.execScript(B,'JavaScript');else{if (FCKBrowserInfo.IsGecko10){eval.call(A,B);}else if (FCKBrowserInfo.IsSafari){var C=A.document;var D=C.createElement('script');D.appendChild(C.createTextNode(B));C.documentElement.appendChild(D);}else A.eval(B);};FCKeditorAPI=A.FCKeditorAPI;};FCKeditorAPI.__Instances[FCK.Name]=FCK;};function _AttachFormSubmitToAPI(){var A=FCK.GetParentForm();if (A){FCKTools.AddEventListener(A,'submit',FCK.UpdateLinkedField);if (!A._FCKOriginalSubmit&&(typeof(A.submit)=='function'||(!A.submit.tagName&&!A.submit.length))){A._FCKOriginalSubmit=A.submit;A.submit=FCKeditorAPI._FormSubmit;}}};function FCKeditorAPI_Cleanup(){delete FCKeditorAPI.__Instances[FCK.Name];};FCKTools.AddEventListener(window,'unload',FCKeditorAPI_Cleanup);
+var FCKImagePreloader=function(){this._Images=[];};FCKImagePreloader.prototype={AddImages:function(A){if (typeof(A)=='string') A=A.split(';');this._Images=this._Images.concat(A);},Start:function(){var A=this._Images;this._PreloadCount=A.length;for (var i=0;i<A.length;i++){var B=document.createElement('img');B.onload=B.onerror=_FCKImagePreloader_OnImage;B._FCKImagePreloader=this;B.src=A[i];_FCKImagePreloader_ImageCache.push(B);}}};var _FCKImagePreloader_ImageCache=[];function _FCKImagePreloader_OnImage(){var A=this._FCKImagePreloader;if ((--A._PreloadCount)==0&&A.OnComplete) A.OnComplete();this._FCKImagePreloader=null;}
+var FCKRegexLib={AposEntity:/&apos;/gi,ObjectElements:/^(?:IMG|TABLE|TR|TD|TH|INPUT|SELECT|TEXTAREA|HR|OBJECT|A|UL|OL|LI)$/i,NamedCommands:/^(?:Cut|Copy|Paste|Print|SelectAll|RemoveFormat|Unlink|Undo|Redo|Bold|Italic|Underline|StrikeThrough|Subscript|Superscript|JustifyLeft|JustifyCenter|JustifyRight|JustifyFull|Outdent|Indent|InsertOrderedList|InsertUnorderedList|InsertHorizontalRule)$/i,BodyContents:/([\s\S]*\<body[^\>]*\>)([\s\S]*)(\<\/body\>[\s\S]*)/i,ToReplace:/___fcktoreplace:([\w]+)/ig,MetaHttpEquiv:/http-equiv\s*=\s*["']?([^"' ]+)/i,HasBaseTag:/<base /i,HtmlOpener:/<html\s?[^>]*>/i,HeadOpener:/<head\s?[^>]*>/i,HeadCloser:/<\/head\s*>/i,FCK_Class:/(\s*FCK__[A-Za-z]*\s*)/,ElementName:/(^[a-z_:][\w.\-:]*\w$)|(^[a-z_]$)/,ForceSimpleAmpersand:/___FCKAmp___/g,SpaceNoClose:/\/>/g,EmptyParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>\s*(<\/\1>)?$/,EmptyOutParagraph:/^<(p|div|address|h\d|center)(?=[ >])[^>]*>(?:\s*|&nbsp;)(<\/\1>)?$/,TagBody:/></,StrongOpener:/<STRONG([ \>])/gi,StrongCloser:/<\/STRONG>/gi,EmOpener:/<EM([ \>])/gi,EmCloser:/<\/EM>/gi,GeckoEntitiesMarker:/#\?-\:/g,ProtectUrlsImg:/<img(?=\s).*?\ssrc=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi,ProtectUrlsA:/<a(?=\s).*?\shref=((?:(?:\s*)("|').*?\2)|(?:[^"'][^ >]+))/gi,Html4DocType:/HTML 4\.0 Transitional/i,DocTypeTag:/<!DOCTYPE[^>]*>/i,TagsWithEvent:/<[^\>]+ on\w+[\s\r\n]*=[\s\r\n]*?('|")[\s\S]+?\>/g,EventAttributes:/\s(on\w+)[\s\r\n]*=[\s\r\n]*?('|")([\s\S]*?)\2/g,ProtectedEvents:/\s\w+_fckprotectedatt="([^"]+)"/g,StyleProperties:/\S+\s*:/g,InvalidSelfCloseTags:/(<(?!base|meta|link|hr|br|param|img|area|input)([a-zA-Z0-9:]+)[^>]*)\/>/gi};
+var FCKListsLib={BlockElements:{ address:1,blockquote:1,center:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,marquee:1,noscript:1,ol:1,p:1,pre:1,script:1,table:1,ul:1 },NonEmptyBlockElements:{ p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,address:1,pre:1,ol:1,ul:1,li:1,td:1,th:1 },InlineChildReqElements:{ abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 },EmptyElements:{ base:1,meta:1,link:1,hr:1,br:1,param:1,img:1,area:1,input:1 },PathBlockElements:{ address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,ol:1,ul:1,li:1,dt:1,de:1 },PathBlockLimitElements:{ body:1,td:1,th:1,caption:1,form:1 },Setup:function(){if (FCKConfig.EnterMode=='div') this.PathBlockElements.div=1;else this.PathBlockLimitElements.div=1;}};
+var FCKLanguageManager=FCK.Language={AvailableLanguages:{af:'Afrikaans',ar:'Arabic',bg:'Bulgarian',bn:'Bengali/Bangla',bs:'Bosnian',ca:'Catalan',cs:'Czech',da:'Danish',de:'German',el:'Greek',en:'English','en-au':'English (Australia)','en-ca':'English (Canadian)','en-uk':'English (United Kingdom)',eo:'Esperanto',es:'Spanish',et:'Estonian',eu:'Basque',fa:'Persian',fi:'Finnish',fo:'Faroese',fr:'French',gl:'Galician',he:'Hebrew',hi:'Hindi',hr:'Croatian',hu:'Hungarian',it:'Italian',ja:'Japanese',km:'Khmer',ko:'Korean',lt:'Lithuanian',lv:'Latvian',mn:'Mongolian',ms:'Malay',nb:'Norwegian Bokmal',nl:'Dutch',no:'Norwegian',pl:'Polish',pt:'Portuguese (Portugal)','pt-br':'Portuguese (Brazil)',ro:'Romanian',ru:'Russian',sk:'Slovak',sl:'Slovenian',sr:'Serbian (Cyrillic)','sr-latn':'Serbian (Latin)',sv:'Swedish',th:'Thai',tr:'Turkish',uk:'Ukrainian',vi:'Vietnamese',zh:'Chinese Traditional','zh-cn':'Chinese Simplified'},GetActiveLanguage:function(){if (FCKConfig.AutoDetectLanguage){var A;if (navigator.userLanguage) A=navigator.userLanguage.toLowerCase();else if (navigator.language) A=navigator.language.toLowerCase();else{return FCKConfig.DefaultLanguage;};if (A.length>=5){A=A.substr(0,5);if (this.AvailableLanguages[A]) return A;};if (A.length>=2){A=A.substr(0,2);if (this.AvailableLanguages[A]) return A;}};return this.DefaultLanguage;},TranslateElements:function(A,B,C,D){var e=A.getElementsByTagName(B);var E,s;for (var i=0;i<e.length;i++){if ((E=e[i].getAttribute('fckLang'))){if ((s=FCKLang[E])){if (D) s=FCKTools.HTMLEncode(s);eval('e[i].'+C+' = s');}}}},TranslatePage:function(A){this.TranslateElements(A,'INPUT','value');this.TranslateElements(A,'SPAN','innerHTML');this.TranslateElements(A,'LABEL','innerHTML');this.TranslateElements(A,'OPTION','innerHTML',true);},Initialize:function(){if (this.AvailableLanguages[FCKConfig.DefaultLanguage]) this.DefaultLanguage=FCKConfig.DefaultLanguage;else this.DefaultLanguage='en';this.ActiveLanguage={};this.ActiveLanguage.Code=this.GetActiveLanguage();this.ActiveLanguage.Name=this.AvailableLanguages[this.ActiveLanguage.Code];}};
+var FCKXHtmlEntities={};FCKXHtmlEntities.Initialize=function(){if (FCKXHtmlEntities.Entities) return;var A='';var B,e;if (FCKConfig.ProcessHTMLEntities){FCKXHtmlEntities.Entities={' ':'nbsp','¡':'iexcl','¢':'cent','£':'pound','¤':'curren','¥':'yen','¦':'brvbar','§':'sect','¨':'uml','©':'copy','ª':'ordf','«':'laquo','¬':'not','­':'shy','®':'reg','¯':'macr','°':'deg','±':'plusmn','²':'sup2','³':'sup3','´':'acute','µ':'micro','¶':'para','·':'middot','¸':'cedil','¹':'sup1','º':'ordm','»':'raquo','¼':'frac14','½':'frac12','¾':'frac34','¿':'iquest','×':'times','÷':'divide','ƒ':'fnof','•':'bull','…':'hellip','′':'prime','″':'Prime','‾':'oline','⁄':'frasl','℘':'weierp','ℑ':'image','ℜ':'real','™':'trade','ℵ':'alefsym','←':'larr','↑':'uarr','→':'rarr','↓':'darr','↔':'harr','↵':'crarr','⇐':'lArr','⇑':'uArr','⇒':'rArr','⇓':'dArr','⇔':'hArr','∀':'forall','∂':'part','∃':'exist','∅':'empty','∇':'nabla','∈':'isin','∉':'notin','∋':'ni','∏':'prod','∑':'sum','−':'minus','∗':'lowast','√':'radic','∝':'prop','∞':'infin','∠':'ang','∧':'and','∨':'or','∩':'cap','∪':'cup','∫':'int','∴':'there4','∼':'sim','≅':'cong','≈':'asymp','≠':'ne','≡':'equiv','≤':'le','≥':'ge','⊂':'sub','⊃':'sup','⊄':'nsub','⊆':'sube','⊇':'supe','⊕':'oplus','⊗':'otimes','⊥':'perp','⋅':'sdot','◊':'loz','♠':'spades','♣':'clubs','♥':'hearts','♦':'diams','"':'quot','ˆ':'circ','˜':'tilde',' ':'ensp',' ':'emsp',' ':'thinsp','‌':'zwnj','‍':'zwj','‎':'lrm','‏':'rlm','–':'ndash','—':'mdash','‘':'lsquo','’':'rsquo','‚':'sbquo','“':'ldquo','”':'rdquo','„':'bdquo','†':'dagger','‡':'Dagger','‰':'permil','‹':'lsaquo','›':'rsaquo','€':'euro'};for (e in FCKXHtmlEntities.Entities) A+=e;if (FCKConfig.IncludeLatinEntities){B={'À':'Agrave','Á':'Aacute','Â':'Acirc','Ã':'Atilde','Ä':'Auml','Å':'Aring','Æ':'AElig','Ç':'Ccedil','È':'Egrave','É':'Eacute','Ê':'Ecirc','Ë':'Euml','Ì':'Igrave','Í':'Iacute','Î':'Icirc','Ï':'Iuml','Ð':'ETH','Ñ':'Ntilde','Ò':'Ograve','Ó':'Oacute','Ô':'Ocirc','Õ':'Otilde','Ö':'Ouml','Ø':'Oslash','Ù':'Ugrave','Ú':'Uacute','Û':'Ucirc','Ü':'Uuml','Ý':'Yacute','Þ':'THORN','ß':'szlig','à':'agrave','á':'aacute','â':'acirc','ã':'atilde','ä':'auml','å':'aring','æ':'aelig','ç':'ccedil','è':'egrave','é':'eacute','ê':'ecirc','ë':'euml','ì':'igrave','í':'iacute','î':'icirc','ï':'iuml','ð':'eth','ñ':'ntilde','ò':'ograve','ó':'oacute','ô':'ocirc','õ':'otilde','ö':'ouml','ø':'oslash','ù':'ugrave','ú':'uacute','û':'ucirc','ü':'uuml','ý':'yacute','þ':'thorn','ÿ':'yuml','Œ':'OElig','œ':'oelig','Š':'Scaron','š':'scaron','Ÿ':'Yuml'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;};if (FCKConfig.IncludeGreekEntities){B={'Α':'Alpha','Β':'Beta','Γ':'Gamma','Δ':'Delta','Ε':'Epsilon','Ζ':'Zeta','Η':'Eta','Θ':'Theta','Ι':'Iota','Κ':'Kappa','Λ':'Lambda','Μ':'Mu','Ν':'Nu','Ξ':'Xi','Ο':'Omicron','Π':'Pi','Ρ':'Rho','Σ':'Sigma','Τ':'Tau','Υ':'Upsilon','Φ':'Phi','Χ':'Chi','Ψ':'Psi','Ω':'Omega','α':'alpha','β':'beta','γ':'gamma','δ':'delta','ε':'epsilon','ζ':'zeta','η':'eta','θ':'theta','ι':'iota','κ':'kappa','λ':'lambda','μ':'mu','ν':'nu','ξ':'xi','ο':'omicron','π':'pi','ρ':'rho','ς':'sigmaf','σ':'sigma','τ':'tau','υ':'upsilon','φ':'phi','χ':'chi','ψ':'psi','ω':'omega'};for (e in B){FCKXHtmlEntities.Entities[e]=B[e];A+=e;};B=null;}}else{FCKXHtmlEntities.Entities={};A=' ';};var C='['+A+']';if (FCKConfig.ProcessNumericEntities) C='[^ -~]|'+C;var D=FCKConfig.AdditionalNumericEntities;if (D&&D.length>0) C+='|'+FCKConfig.AdditionalNumericEntities;FCKXHtmlEntities.EntitiesRegex=new RegExp(C,'g');}
+var FCKXHtml={};FCKXHtml.CurrentJobNum=0;FCKXHtml.GetXHTML=function(A,B,C){FCKXHtmlEntities.Initialize();this._NbspEntity=(FCKConfig.ProcessHTMLEntities?'nbsp':'#160');var D=FCK.IsDirty();this._CreateNode=FCKConfig.ForceStrongEm?FCKXHtml_CreateNode_StrongEm:FCKXHtml_CreateNode_Normal;FCKXHtml.SpecialBlocks=[];this.XML=FCKTools.CreateXmlObject('DOMDocument');this.MainNode=this.XML.appendChild(this.XML.createElement('xhtml'));FCKXHtml.CurrentJobNum++;if (B) this._AppendNode(this.MainNode,A);else this._AppendChildNodes(this.MainNode,A,false);var E=this._GetMainXmlString();this.XML=null;E=E.substr(7,E.length-15).Trim();if (FCKBrowserInfo.IsGecko) E=E.replace(/<br\/>$/,'');E=E.replace(FCKRegexLib.SpaceNoClose,' />');if (FCKConfig.ForceSimpleAmpersand) E=E.replace(FCKRegexLib.ForceSimpleAmpersand,'&');if (C) E=FCKCodeFormatter.Format(E);for (var i=0;i<FCKXHtml.SpecialBlocks.length;i++){var F=new RegExp('___FCKsi___'+i);E=E.replace(F,FCKXHtml.SpecialBlocks[i]);};E=E.replace(FCKRegexLib.GeckoEntitiesMarker,'&');if (!D) FCK.ResetIsDirty();return E;};FCKXHtml._AppendAttribute=function(A,B,C){try{if (C==undefined||C==null) C='';else if (C.replace){if (FCKConfig.ForceSimpleAmpersand) C=C.replace(/&/g,'___FCKAmp___');C=C.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity);};var D=this.XML.createAttribute(B);D.value=C;A.attributes.setNamedItem(D);}catch (e){}};FCKXHtml._AppendChildNodes=function(A,B,C){var D=B.firstChild;while (D){this._AppendNode(A,D);D=D.nextSibling;};if (C) FCKDomTools.TrimNode(A,true);if (A.childNodes.length==0){if (C&&FCKConfig.FillEmptyBlocks){this._AppendEntity(A,this._NbspEntity);return A;};var E=A.nodeName;if (FCKListsLib.InlineChildReqElements[E]) return null;if (!FCKListsLib.EmptyElements[E]) A.appendChild(this.XML.createTextNode(''));};return A;};FCKXHtml._AppendNode=function(A,B){if (!B) return false;switch (B.nodeType){case 1:if (B.getAttribute('_fckfakelement')) return FCKXHtml._AppendNode(A,FCK.GetRealElement(B));if (FCKBrowserInfo.IsGecko&&B.hasAttribute('_moz_editor_bogus_node')) return false;if (B.getAttribute('_fcktemp')) return false;var C=B.tagName.toLowerCase();if (FCKBrowserInfo.IsIE){if (B.scopeName&&B.scopeName!='HTML'&&B.scopeName!='FCK') C=B.scopeName.toLowerCase()+':'+C;}else{if (C.StartsWith('fck:')) C=C.Remove(0,4);};if (!FCKRegexLib.ElementName.test(C)) return false;if (C=='br'&&B.getAttribute('type',2)=='_moz') return false;if (B._fckxhtmljob&&B._fckxhtmljob==FCKXHtml.CurrentJobNum) return false;var D=this._CreateNode(C);FCKXHtml._AppendAttributes(A,B,D,C);B._fckxhtmljob=FCKXHtml.CurrentJobNum;var E=FCKXHtml.TagProcessors[C];if (E) D=E(D,B,A);else D=this._AppendChildNodes(D,B,Boolean(FCKListsLib.NonEmptyBlockElements[C]));if (!D) return false;A.appendChild(D);break;case 3:return this._AppendTextNode(A,B.nodeValue.ReplaceNewLineChars(' '));case 8:if (FCKBrowserInfo.IsIE&&!B.innerHTML) break;try { A.appendChild(this.XML.createComment(B.nodeValue));}catch (e) {/*Do nothing... probably this is a wrong format comment.*/};break;default:A.appendChild(this.XML.createComment("Element not supported - Type: "+B.nodeType+" Name: "+B.nodeName));break;};return true;};function FCKXHtml_CreateNode_StrongEm(A){switch (A){case 'b':A='strong';break;case 'i':A='em';break;};return this.XML.createElement(A);};function FCKXHtml_CreateNode_Normal(A){return this.XML.createElement(A);};FCKXHtml._AppendSpecialItem=function(A){return '___FCKsi___'+FCKXHtml.SpecialBlocks.AddItem(A);};FCKXHtml._AppendEntity=function(A,B){A.appendChild(this.XML.createTextNode('#?-:'+B+';'));};FCKXHtml._AppendTextNode=function(A,B){var C=B.length>0;if (C) A.appendChild(this.XML.createTextNode(B.replace(FCKXHtmlEntities.EntitiesRegex,FCKXHtml_GetEntity)));return C;};function FCKXHtml_GetEntity(A){var B=FCKXHtmlEntities.Entities[A]||('#'+A.charCodeAt(0));return '#?-:'+B+';';};FCKXHtml._RemoveAttribute=function(A,B,C){var D=A.attributes.getNamedItem(C);if (D&&B.test(D.nodeValue)){var E=D.nodeValue.replace(B,'');if (E.length==0) A.attributes.removeNamedItem(C);else D.nodeValue=E;}};FCKXHtml.TagProcessors={img:function(A,B){if (!A.attributes.getNamedItem('alt')) FCKXHtml._AppendAttribute(A,'alt','');var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'src',C);return A;},a:function(A,B){if (B.innerHTML.Trim().length==0&&!B.name) return false;var C=B.getAttribute('_fcksavedurl');if (C!=null) FCKXHtml._AppendAttribute(A,'href',C);if (FCKBrowserInfo.IsIE){FCKXHtml._RemoveAttribute(A,FCKRegexLib.FCK_Class,'class');if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);};A=FCKXHtml._AppendChildNodes(A,B,false);return A;},script:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/javascript');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.text)));return A;},style:function(A,B){if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text/css');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(B.innerHTML)));return A;},title:function(A,B){A.appendChild(FCKXHtml.XML.createTextNode(FCK.EditorDocument.title));return A;},table:function(A,B){if (FCKBrowserInfo.IsIE) FCKXHtml._RemoveAttribute(A,FCKRegexLib.FCK_Class,'class');A=FCKXHtml._AppendChildNodes(A,B,false);return A;},ol:function(A,B,C){if (B.innerHTML.Trim().length==0) return false;var D=C.lastChild;if (D&&D.nodeType==3) D=D.previousSibling;if (D&&D.nodeName.toUpperCase()=='LI'){B._fckxhtmljob=null;FCKXHtml._AppendNode(D,B);return false;};A=FCKXHtml._AppendChildNodes(A,B);return A;},span:function(A,B){if (B.innerHTML.length==0) return false;A=FCKXHtml._AppendChildNodes(A,B,false);return A;},iframe:function(A,B){var C=B.innerHTML;if (FCKBrowserInfo.IsGecko) C=FCKTools.HTMLDecode(C);C=C.replace(/\s_fcksavedurl="[^"]*"/g,'');A.appendChild(FCKXHtml.XML.createTextNode(FCKXHtml._AppendSpecialItem(C)));return A;}};FCKXHtml.TagProcessors.ul=FCKXHtml.TagProcessors.ol;
+FCKXHtml._GetMainXmlString=function(){return this.MainNode.xml;};FCKXHtml._AppendAttributes=function(A,B,C,D){var E=B.attributes;for (var n=0;n<E.length;n++){var F=E[n];if (F.specified){var G=F.nodeName.toLowerCase();var H;if (G.StartsWith('_fck')) continue;else if (G=='style') H=B.style.cssText.replace(FCKRegexLib.StyleProperties,FCKTools.ToLowerCase);else if (G=='class'||G.indexOf('on')==0) H=F.nodeValue;else if (D=='body'&&G=='contenteditable') continue;else if (F.nodeValue===true) H=G;else{try{H=B.getAttribute(G,2);}catch (e) {}};this._AppendAttribute(C,G,H||F.nodeValue);}}};FCKXHtml.TagProcessors['meta']=function(A,B){var C=A.attributes.getNamedItem('http-equiv');if (C==null||C.value.length==0){var D=B.outerHTML.match(FCKRegexLib.MetaHttpEquiv);if (D){D=D[1];FCKXHtml._AppendAttribute(A,'http-equiv',D);}};return A;};FCKXHtml.TagProcessors['font']=function(A,B){if (A.attributes.length==0) A=FCKXHtml.XML.createDocumentFragment();A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['input']=function(A,B){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);if (B.value&&!A.attributes.getNamedItem('value')) FCKXHtml._AppendAttribute(A,'value',B.value);if (!A.attributes.getNamedItem('type')) FCKXHtml._AppendAttribute(A,'type','text');return A;};FCKXHtml.TagProcessors['option']=function(A,B){if (B.selected&&!A.attributes.getNamedItem('selected')) FCKXHtml._AppendAttribute(A,'selected','selected');A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['area']=function(A,B){if (!A.attributes.getNamedItem('coords')){var C=B.getAttribute('coords',2);if (C&&C!='0,0,0') FCKXHtml._AppendAttribute(A,'coords',C);};if (!A.attributes.getNamedItem('shape')){var D=B.getAttribute('shape',2);if (D&&D.length>0) FCKXHtml._AppendAttribute(A,'shape',D);};return A;};FCKXHtml.TagProcessors['label']=function(A,B){if (B.htmlFor.length>0) FCKXHtml._AppendAttribute(A,'for',B.htmlFor);A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['form']=function(A,B){if (B.acceptCharset&&B.acceptCharset.length>0&&B.acceptCharset!='UNKNOWN') FCKXHtml._AppendAttribute(A,'accept-charset',B.acceptCharset);var C=B.attributes['name'];if (C&&C.value.length>0) FCKXHtml._AppendAttribute(A,'name',C.value);A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['textarea']=FCKXHtml.TagProcessors['select']=function(A,B){if (B.name) FCKXHtml._AppendAttribute(A,'name',B.name);A=FCKXHtml._AppendChildNodes(A,B);return A;};FCKXHtml.TagProcessors['div']=function(A,B){if (B.align.length>0) FCKXHtml._AppendAttribute(A,'align',B.align);A=FCKXHtml._AppendChildNodes(A,B,true);return A;}
+var FCKCodeFormatter={};FCKCodeFormatter.Init=function(){var A=this.Regex={};A.BlocksOpener=/\<(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.BlocksCloser=/\<\/(P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|TITLE|META|LINK|BASE|SCRIPT|LINK|TD|TH|AREA|OPTION)[^\>]*\>/gi;A.NewLineTags=/\<(BR|HR)[^\>]*\>/gi;A.MainTags=/\<\/?(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR)[^\>]*\>/gi;A.LineSplitter=/\s*\n+\s*/g;A.IncreaseIndent=/^\<(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \/\>]/i;A.DecreaseIndent=/^\<\/(HTML|HEAD|BODY|FORM|TABLE|TBODY|THEAD|TR|UL|OL)[ \>]/i;A.FormatIndentatorRemove=new RegExp('^'+FCKConfig.FormatIndentator);A.ProtectedTags=/(<PRE[^>]*>)([\s\S]*?)(<\/PRE>)/gi;};FCKCodeFormatter._ProtectData=function(A,B,C,D){return B+'___FCKpd___'+FCKCodeFormatter.ProtectedData.AddItem(C)+D;};FCKCodeFormatter.Format=function(A){if (!this.Regex) this.Init();FCKCodeFormatter.ProtectedData=[];var B=A.replace(this.Regex.ProtectedTags,FCKCodeFormatter._ProtectData);B=B.replace(this.Regex.BlocksOpener,'\n$&');B=B.replace(this.Regex.BlocksCloser,'$&\n');B=B.replace(this.Regex.NewLineTags,'$&\n');B=B.replace(this.Regex.MainTags,'\n$&\n');var C='';var D=B.split(this.Regex.LineSplitter);B='';for (var i=0;i<D.length;i++){var E=D[i];if (E.length==0) continue;if (this.Regex.DecreaseIndent.test(E)) C=C.replace(this.Regex.FormatIndentatorRemove,'');B+=C+E+'\n';if (this.Regex.IncreaseIndent.test(E)) C+=FCKConfig.FormatIndentator;};for (var j=0;j<FCKCodeFormatter.ProtectedData.length;j++){var F=new RegExp('___FCKpd___'+j);B=B.replace(F,FCKCodeFormatter.ProtectedData[j].replace(/\$/g,'$$$$'));};return B.Trim();}
+var FCKUndo={};FCKUndo.SavedData=[];FCKUndo.CurrentIndex=-1;FCKUndo.TypesCount=FCKUndo.MaxTypes=25;FCKUndo.Typing=false;FCKUndo.SaveUndoStep=function(){if (FCK.EditMode!=0) return;FCKUndo.SavedData=FCKUndo.SavedData.slice(0,FCKUndo.CurrentIndex+1);var A=FCK.EditorDocument.body.innerHTML;if (FCKUndo.CurrentIndex>=0&&A==FCKUndo.SavedData[FCKUndo.CurrentIndex][0]) return;if (FCKUndo.CurrentIndex+1>=FCKConfig.MaxUndoLevels) FCKUndo.SavedData.shift();else FCKUndo.CurrentIndex++;var B;if (FCK.EditorDocument.selection.type=='Text') B=FCK.EditorDocument.selection.createRange().getBookmark();FCKUndo.SavedData[FCKUndo.CurrentIndex]=[A,B];FCK.Events.FireEvent("OnSelectionChange");};FCKUndo.CheckUndoState=function(){return (FCKUndo.Typing||FCKUndo.CurrentIndex>0);};FCKUndo.CheckRedoState=function(){return (!FCKUndo.Typing&&FCKUndo.CurrentIndex<(FCKUndo.SavedData.length-1));};FCKUndo.Undo=function(){if (FCKUndo.CheckUndoState()){if (FCKUndo.CurrentIndex==(FCKUndo.SavedData.length-1)){FCKUndo.SaveUndoStep();};FCKUndo._ApplyUndoLevel(--FCKUndo.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo.Redo=function(){if (FCKUndo.CheckRedoState()){FCKUndo._ApplyUndoLevel(++FCKUndo.CurrentIndex);FCK.Events.FireEvent("OnSelectionChange");}};FCKUndo._ApplyUndoLevel=function(A){var B=FCKUndo.SavedData[A];if (!B) return;FCK.SetInnerHtml(B[0]);if (B[1]){var C=FCK.EditorDocument.selection.createRange();C.moveToBookmark(B[1]);C.select();};FCKUndo.TypesCount=0;FCKUndo.Typing=false;}
+var FCKEditingArea=function(A){this.TargetElement=A;this.Mode=0;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKEditingArea_Cleanup);};FCKEditingArea.prototype.Start=function(A,B){var C=this.TargetElement;var D=FCKTools.GetElementDocument(C);while(C.childNodes.length>0) C.removeChild(C.childNodes[0]);if (this.Mode==0){var E=this.IFrame=D.createElement('iframe');E.src='javascript:void(0)';E.frameBorder=0;E.width=E.height='100%';C.appendChild(E);if (FCKBrowserInfo.IsIE) A=A.replace(/(<base[^>]*?)\s*\/?>(?!\s*<\/base>)/gi,'$1></base>');else if (!B){if (FCKBrowserInfo.IsGecko) A=A.replace(/(<body[^>]*>)\s*(<\/body>)/i,'$1'+GECKO_BOGUS+'$2');var F=A.match(FCKRegexLib.BodyContents);if (F){A=F[1]+'&nbsp;'+F[3];this._BodyHTML=F[2];}else this._BodyHTML=A;};this.Window=E.contentWindow;var G=this.Document=this.Window.document;G.open();G.write(A);G.close();if (FCKBrowserInfo.IsGecko10&&!B){this.Start(A,true);return;};this.Window._FCKEditingArea=this;if (FCKBrowserInfo.IsGecko10) this.Window.setTimeout(FCKEditingArea_CompleteStart,500);else FCKEditingArea_CompleteStart.call(this.Window);}else{var H=this.Textarea=D.createElement('textarea');H.className='SourceField';H.dir='ltr';H.style.width=H.style.height='100%';H.style.border='none';C.appendChild(H);H.value=A;FCKTools.RunFunction(this.OnLoad);}};function FCKEditingArea_CompleteStart(){if (!this.document.body){this.setTimeout(FCKEditingArea_CompleteStart,50);return;};var A=this._FCKEditingArea;A.MakeEditable();FCKTools.RunFunction(A.OnLoad);};FCKEditingArea.prototype.MakeEditable=function(){var A=this.Document;if (FCKBrowserInfo.IsIE){A.body.contentEditable=true;}else{try{A.body.spellcheck=(this.FFSpellChecker!==false);if (this._BodyHTML){A.body.innerHTML=this._BodyHTML;this._BodyHTML=null;};A.designMode='on';try{A.execCommand('styleWithCSS',false,FCKConfig.GeckoUseSPAN);}catch (e){A.execCommand('useCSS',false,!FCKConfig.GeckoUseSPAN);};A.execCommand('enableObjectResizing',false,!FCKConfig.DisableObjectResizing);A.execCommand('enableInlineTableEditing',false,!FCKConfig.DisableFFTableHandles);}catch (e) {}}};FCKEditingArea.prototype.Focus=function(){try{if (this.Mode==0){if (FCKBrowserInfo.IsIE&&this.Document.hasFocus()) return;if (FCKBrowserInfo.IsSafari) this.IFrame.focus();else{this.Window.focus();}}else{var A=FCKTools.GetElementDocument(this.Textarea);if ((!A.hasFocus||A.hasFocus())&&A.activeElement==this.Textarea) return;this.Textarea.focus();}}catch(e) {}};function FCKEditingArea_Cleanup(){this.TargetElement=null;this.IFrame=null;this.Document=null;this.Textarea=null;if (this.Window){this.Window._FCKEditingArea=null;this.Window=null;}};
+var FCKKeystrokeHandler=function(A){this.Keystrokes={};this.CancelCtrlDefaults=(A!==false);};FCKKeystrokeHandler.prototype.AttachToElement=function(A){FCKTools.AddEventListenerEx(A,'keydown',_FCKKeystrokeHandler_OnKeyDown,this);if (FCKBrowserInfo.IsGecko10||FCKBrowserInfo.IsOpera||(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsMac)) FCKTools.AddEventListenerEx(A,'keypress',_FCKKeystrokeHandler_OnKeyPress,this);};FCKKeystrokeHandler.prototype.SetKeystrokes=function(){for (var i=0;i<arguments.length;i++){var A=arguments[i];if (typeof(A[0])=='object') this.SetKeystrokes.apply(this,A);else{if (A.length==1) delete this.Keystrokes[A[0]];else this.Keystrokes[A[0]]=A[1]===true?true:A;}}};function _FCKKeystrokeHandler_OnKeyDown(A,B){var C=A.keyCode||A.which;var D=0;if (A.ctrlKey||A.metaKey) D+=CTRL;if (A.shiftKey) D+=SHIFT;if (A.altKey) D+=ALT;var E=C+D;var F=B._CancelIt=false;var G=B.Keystrokes[E];if (G){if (G===true||!(B.OnKeystroke&&B.OnKeystroke.apply(B,G))) return true;F=true;};if (F||(B.CancelCtrlDefaults&&D==CTRL&&(C<33||C>40))){B._CancelIt=true;if (A.preventDefault) return A.preventDefault();A.returnValue=false;A.cancelBubble=true;return false;};return true;};function _FCKKeystrokeHandler_OnKeyPress(A,B){if (B._CancelIt){if (A.preventDefault) return A.preventDefault();return false;};return true;}
+var FCKListHandler={OutdentListItem:function(A){var B=A.parentNode;if (B.tagName.toUpperCase().Equals('UL','OL')){var C=FCKTools.GetElementDocument(A);var D=new FCKDocumentFragment(C);var E=D.RootNode;var F=false;var G=FCKDomTools.GetFirstChild(A,['UL','OL']);if (G){F=true;var H;while ((H=G.firstChild)) E.appendChild(G.removeChild(H));FCKDomTools.RemoveNode(G);};var I;var J=false;while ((I=A.nextSibling)){if (!F&&I.nodeType==1&&I.nodeName.toUpperCase()=='LI') J=F=true;E.appendChild(I.parentNode.removeChild(I));if (!J&&I.nodeType==1&&I.nodeName.toUpperCase().Equals('UL','OL')) FCKDomTools.RemoveNode(I,true);};var K=B.parentNode.tagName.toUpperCase();var L=(K=='LI');if (L||K.Equals('UL','OL')){if (F){var G=B.cloneNode(false);D.AppendTo(G);A.appendChild(G);}else if (L) D.InsertAfterNode(B.parentNode);else D.InsertAfterNode(B);if (L) FCKDomTools.InsertAfterNode(B.parentNode,B.removeChild(A));else FCKDomTools.InsertAfterNode(B,B.removeChild(A));}else{if (F){var N=B.cloneNode(false);D.AppendTo(N);FCKDomTools.InsertAfterNode(B,N);};var O=C.createElement(FCKConfig.EnterMode=='p'?'p':'div');FCKDomTools.MoveChildren(B.removeChild(A),O);FCKDomTools.InsertAfterNode(B,O);if (FCKConfig.EnterMode=='br'){if (FCKBrowserInfo.IsGecko) O.parentNode.insertBefore(FCKTools.CreateBogusBR(C),O);else FCKDomTools.InsertAfterNode(O,FCKTools.CreateBogusBR(C));FCKDomTools.RemoveNode(O,true);}};if (this.CheckEmptyList(B)) FCKDomTools.RemoveNode(B,true);}},CheckEmptyList:function(A){return (FCKDomTools.GetFirstChild(A,'LI')==null);},CheckListHasContents:function(A){var B=A.firstChild;while (B){switch (B.nodeType){case 1:if (!B.nodeName.IEquals('UL','LI')) return true;break;case 3:if (B.nodeValue.Trim().length>0) return true;};B=B.nextSibling;};return false;}};
+var FCKElementPath=function(A){var B=null;var C=null;var D=[];var e=A;while (e){if (e.nodeType==1){if (!this.LastElement) this.LastElement=e;var E=e.nodeName.toLowerCase();if (!C){if (!B&&FCKListsLib.PathBlockElements[E]!=null) B=e;if (FCKListsLib.PathBlockLimitElements[E]!=null) C=e;};D.push(e);if (E=='body') break;};e=e.parentNode;};this.Block=B;this.BlockLimit=C;this.Elements=D;};
+var FCKDomRange=function(A){this.Window=A;};FCKDomRange.prototype={_UpdateElementInfo:function(){if (!this._Range) this.Release(true);else{var A=this._Range.startContainer;var B=this._Range.endContainer;var C=new FCKElementPath(A);this.StartContainer=C.LastElement;this.StartBlock=C.Block;this.StartBlockLimit=C.BlockLimit;if (A!=B) C=new FCKElementPath(B);this.EndContainer=C.LastElement;this.EndBlock=C.Block;this.EndBlockLimit=C.BlockLimit;}},CreateRange:function(){return new FCKW3CRange(this.Window.document);},DeleteContents:function(){if (this._Range){this._Range.deleteContents();this._UpdateElementInfo();}},ExtractContents:function(){if (this._Range){var A=this._Range.extractContents();this._UpdateElementInfo();return A;}},CheckIsCollapsed:function(){if (this._Range) return this._Range.collapsed;},Collapse:function(A){if (this._Range) this._Range.collapse(A);this._UpdateElementInfo();},Clone:function(){var A=FCKTools.CloneObject(this);if (this._Range) A._Range=this._Range.cloneRange();return A;},MoveToNodeContents:function(A){if (!this._Range) this._Range=this.CreateRange();this._Range.selectNodeContents(A);this._UpdateElementInfo();},MoveToElementStart:function(A){this.SetStart(A,1);this.SetEnd(A,1);},MoveToElementEditStart:function(A){var B;while ((B=A.firstChild)&&B.nodeType==1&&FCKListsLib.EmptyElements[B.nodeName.toLowerCase()]==null) A=B;this.MoveToElementStart(A);},InsertNode:function(A){if (this._Range) this._Range.insertNode(A);},CheckIsEmpty:function(A){if (this.CheckIsCollapsed()) return true;var B=this.Window.document.createElement('div');this._Range.cloneContents().AppendTo(B);FCKDomTools.TrimNode(B,A);return (B.innerHTML.length==0);},CheckStartOfBlock:function(){var A=this.Clone();A.Collapse(true);A.SetStart(A.StartBlock||A.StartBlockLimit,1);var B=A.CheckIsEmpty();A.Release();return B;},CheckEndOfBlock:function(A){var B=this.Clone();B.Collapse(false);B.SetEnd(B.EndBlock||B.EndBlockLimit,2);var C=B.CheckIsCollapsed();if (!C){var D=this.Window.document.createElement('div');B._Range.cloneContents().AppendTo(D);FCKDomTools.TrimNode(D,true);C=true;var E=D;while ((E=E.lastChild)){if (E.previousSibling||E.nodeType!=1||FCKListsLib.InlineChildReqElements[E.nodeName.toLowerCase()]==null){C=false;break;}}};B.Release();if (A) this.Select();return C;},CreateBookmark:function(){var A={StartId:'fck_dom_range_start_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000),EndId:'fck_dom_range_end_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000)};var B=this.Window.document;var C;var D;if (!this.CheckIsCollapsed()){C=B.createElement('span');C.id=A.EndId;C.innerHTML='&nbsp;';D=this.Clone();D.Collapse(false);D.InsertNode(C);};C=B.createElement('span');C.id=A.StartId;C.innerHTML='&nbsp;';D=this.Clone();D.Collapse(true);D.InsertNode(C);return A;},MoveToBookmark:function(A,B){var C=this.Window.document;var D=C.getElementById(A.StartId);var E=C.getElementById(A.EndId);this.SetStart(D,3);if (!B) FCKDomTools.RemoveNode(D);if (E){this.SetEnd(E,3);if (!B) FCKDomTools.RemoveNode(E);}else this.Collapse(true);},SetStart:function(A,B){var C=this._Range;if (!C) C=this._Range=this.CreateRange();switch(B){case 1:C.setStart(A,0);break;case 2:C.setStart(A,A.childNodes.length);break;case 3:C.setStartBefore(A);break;case 4:C.setStartAfter(A);};this._UpdateElementInfo();},SetEnd:function(A,B){var C=this._Range;if (!C) C=this._Range=this.CreateRange();switch(B){case 1:C.setEnd(A,0);break;case 2:C.setEnd(A,A.childNodes.length);break;case 3:C.setEndBefore(A);break;case 4:C.setEndAfter(A);};this._UpdateElementInfo();},Expand:function(A){var B,oSibling;switch (A){case 'block_contents':if (this.StartBlock) this.SetStart(this.StartBlock,1);else{B=this._Range.startContainer;if (B.nodeType==1){if (!(B=B.childNodes[this._Range.startOffset])) B=B.firstChild;};if (!B) return;while (true){oSibling=B.previousSibling;if (!oSibling){if (B.parentNode!=this.StartBlockLimit) B=B.parentNode;else break;}else if (oSibling.nodeType!=1||!(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test(oSibling.nodeName.toUpperCase())){B=oSibling;}else break;};this._Range.setStartBefore(B);};if (this.EndBlock) this.SetEnd(this.EndBlock,2);else{B=this._Range.endContainer;if (B.nodeType==1) B=B.childNodes[this._Range.endOffset]||B.lastChild;if (!B) return;while (true){oSibling=B.nextSibling;if (!oSibling){if (B.parentNode!=this.EndBlockLimit) B=B.parentNode;else break;}else if (oSibling.nodeType!=1||!(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test(oSibling.nodeName.toUpperCase())){B=oSibling;}else break;};this._Range.setEndAfter(B);};this._UpdateElementInfo();}},Release:function(A){if (!A) this.Window=null;this.StartContainer=null;this.StartBlock=null;this.StartBlockLimit=null;this.EndContainer=null;this.EndBlock=null;this.EndBlockLimit=null;this._Range=null;}};
+FCKDomRange.prototype.MoveToSelection=function(){this.Release(true);this._Range=new FCKW3CRange(this.Window.document);var A=this.Window.document.selection;if (A.type!='Control'){B=this._GetSelectionMarkerTag(true);this._Range.setStart(B.parentNode,FCKDomTools.GetIndexOf(B));B.parentNode.removeChild(B);var B=this._GetSelectionMarkerTag(false);this._Range.setEnd(B.parentNode,FCKDomTools.GetIndexOf(B));B.parentNode.removeChild(B);this._UpdateElementInfo();}else{var C=A.createRange().item(0);if (C){this._Range.setStartBefore(C);this._Range.setEndAfter(C);this._UpdateElementInfo();}}};FCKDomRange.prototype.Select=function(){if (this._Range){var A=this.CheckIsCollapsed();var B=this._GetRangeMarkerTag(true);if (!A) var C=this._GetRangeMarkerTag(false);var D=this.Window.document.body.createTextRange();D.moveToElementText(B);D.moveStart('character',1);if (!A){var E=this.Window.document.body.createTextRange();E.moveToElementText(C);D.setEndPoint('EndToEnd',E);D.moveEnd('character',-1);};this._Range.setStartBefore(B);B.parentNode.removeChild(B);if (A){try{D.pasteHTML('&nbsp;');D.moveStart('character',-1);}catch (e){};D.select();D.pasteHTML('');}else{this._Range.setEndBefore(C);C.parentNode.removeChild(C);D.select();}}};FCKDomRange.prototype._GetSelectionMarkerTag=function(A){var B=this.Window.document.selection.createRange();B.collapse(A===true);var C='fck_dom_range_temp_'+(new Date()).valueOf()+'_'+Math.floor(Math.random()*1000);B.pasteHTML('<span id="'+C+'"></span>');return this.Window.document.getElementById(C);};FCKDomRange.prototype._GetRangeMarkerTag=function(A){var B=this._Range;if (!A){B=B.cloneRange();B.collapse(A===true);};var C=this.Window.document.createElement('span');C.innerHTML='&nbsp;';B.insertNode(C);return C;}
+var FCKDocumentFragment=function(A){this._Document=A;this.RootNode=A.createElement('div');};FCKDocumentFragment.prototype={AppendTo:function(A){FCKDomTools.MoveChildren(this.RootNode,A);},AppendHtml:function(A){var B=this._Document.createElement('div');B.innerHTML=A;FCKDomTools.MoveChildren(B,this.RootNode);},InsertAfterNode:function(A){var B=this.RootNode;var C;while((C=B.lastChild)) FCKDomTools.InsertAfterNode(A,B.removeChild(C));}};
+var FCKW3CRange=function(A){this._Document=A;this.startContainer=null;this.startOffset=null;this.endContainer=null;this.endOffset=null;this.collapsed=true;};FCKW3CRange.CreateRange=function(A){return new FCKW3CRange(A);};FCKW3CRange.CreateFromRange=function(A,B){var C=FCKW3CRange.CreateRange(A);C.setStart(B.startContainer,B.startOffset);C.setEnd(B.endContainer,B.endOffset);return C;};FCKW3CRange.prototype={_UpdateCollapsed:function(){this.collapsed=(this.startContainer==this.endContainer&&this.startOffset==this.endOffset);},setStart:function(A,B){this.startContainer=A;this.startOffset=B;if (!this.endContainer){this.endContainer=A;this.endOffset=B;};this._UpdateCollapsed();},setEnd:function(A,B){this.endContainer=A;this.endOffset=B;if (!this.startContainer){this.startContainer=A;this.startOffset=B;};this._UpdateCollapsed();},setStartAfter:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setStartBefore:function(A){this.setStart(A.parentNode,FCKDomTools.GetIndexOf(A));},setEndAfter:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A)+1);},setEndBefore:function(A){this.setEnd(A.parentNode,FCKDomTools.GetIndexOf(A));},collapse:function(A){if (A){this.endContainer=this.startContainer;this.endOffset=this.startOffset;}else{this.startContainer=this.endContainer;this.startOffset=this.endOffset;};this.collapsed=true;},selectNodeContents:function(A){this.setStart(A,0);this.setEnd(A,A.nodeType==3?A.data.length:A.childNodes.length);},insertNode:function(A){var B=this.startContainer;var C=this.startOffset;if (B.nodeType==3){B.splitText(C);if (B==this.endContainer) this.setEnd(B.nextSibling,this.endOffset-this.startOffset);FCKDomTools.InsertAfterNode(B,A);return;}else{B.insertBefore(A,B.childNodes[C]||null);if (B==this.endContainer){this.endOffset++;this.collapsed=false;}}},deleteContents:function(){if (this.collapsed) return;this._ExecContentsAction(0);},extractContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(1,A);return A;},cloneContents:function(){var A=new FCKDocumentFragment(this._Document);if (!this.collapsed) this._ExecContentsAction(2,A);return A;},_ExecContentsAction:function(A,B){var C=this.startContainer;var D=this.endContainer;var E=this.startOffset;var F=this.endOffset;var G=false;var H=false;if (D.nodeType==3) D=D.splitText(F);else{if (D.childNodes.length>0){if (F>D.childNodes.length-1){D=FCKDomTools.InsertAfterNode(D.lastChild,this._Document.createTextNode(''));H=true;}else D=D.childNodes[F];}};if (C.nodeType==3){C.splitText(E);if (C==D) D=C.nextSibling;}else{if (C.childNodes.length>0&&E<=C.childNodes.length-1){if (E==0){C=C.insertBefore(this._Document.createTextNode(''),C.firstChild);G=true;}else C=C.childNodes[E].previousSibling;}};var I=FCKDomTools.GetParents(C);var J=FCKDomTools.GetParents(D);var i,topStart,topEnd;for (i=0;i<I.length;i++){topStart=I[i];topEnd=J[i];if (topStart!=topEnd) break;};var K,levelStartNode,levelClone,currentNode,currentSibling;if (B) K=B.RootNode;for (var j=i;j<I.length;j++){levelStartNode=I[j];if (K&&levelStartNode!=C) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==C));currentNode=levelStartNode.nextSibling;while(currentNode){if (currentNode==J[j]||currentNode==D) break;currentSibling=currentNode.nextSibling;if (A==2) K.appendChild(currentNode.cloneNode(true));else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.appendChild(currentNode);};currentNode=currentSibling;};if (K) K=levelClone;};if (B) K=B.RootNode;for (var k=i;k<J.length;k++){levelStartNode=J[k];if (A>0&&levelStartNode!=D) levelClone=K.appendChild(levelStartNode.cloneNode(levelStartNode==D));if (!I[k]||levelStartNode.parentNode!=I[k].parentNode){currentNode=levelStartNode.previousSibling;while(currentNode){if (currentNode==I[k]||currentNode==C) break;currentSibling=currentNode.previousSibling;if (A==2) K.insertBefore(currentNode.cloneNode(true),K.firstChild);else{currentNode.parentNode.removeChild(currentNode);if (A==1) K.insertBefore(currentNode,K.firstChild);};currentNode=currentSibling;}};if (K) K=levelClone;};if (A==2){var L=this.startContainer;if (L.nodeType==3){L.data+=L.nextSibling.data;L.parentNode.removeChild(L.nextSibling);};var M=this.endContainer;if (M.nodeType==3&&M.nextSibling){M.data+=M.nextSibling.data;M.parentNode.removeChild(M.nextSibling);}}else{if (topStart&&topEnd&&(C.parentNode!=topStart.parentNode||D.parentNode!=topEnd.parentNode)) this.setStart(topEnd.parentNode,FCKDomTools.GetIndexOf(topEnd));this.collapse(true);};if(G) C.parentNode.removeChild(C);if(H&&D.parentNode) D.parentNode.removeChild(D);},cloneRange:function(){return FCKW3CRange.CreateFromRange(this._Document,this);},toString:function(){var A=this.cloneContents();var B=this._Document.createElement('div');A.AppendTo(B);return B.textContent||B.innerText;}};
+var FCKEnterKey=function(A,B,C){this.Window=A;this.EnterMode=B||'p';this.ShiftEnterMode=C||'br';var D=new FCKKeystrokeHandler(false);D._EnterKey=this;D.OnKeystroke=FCKEnterKey_OnKeystroke;D.SetKeystrokes([[13,'Enter'],[SHIFT+13,'ShiftEnter'],[8,'Backspace'],[46,'Delete']]);D.AttachToElement(A.document);};function FCKEnterKey_OnKeystroke(A,B){var C=this._EnterKey;try{switch (B){case 'Enter':return C.DoEnter();break;case 'ShiftEnter':return C.DoShiftEnter();break;case 'Backspace':return C.DoBackspace();break;case 'Delete':return C.DoDelete();}}catch (e){};return false;};FCKEnterKey.prototype.DoEnter=function(A,B){this._HasShift=(B===true);var C=A||this.EnterMode;if (C=='br') return this._ExecuteEnterBr();else return this._ExecuteEnterBlock(C);};FCKEnterKey.prototype.DoShiftEnter=function(){return this.DoEnter(this.ShiftEnterMode,true);};FCKEnterKey.prototype.DoBackspace=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (!B.CheckIsCollapsed()) return false;var C=B.StartBlock;var D=B.EndBlock;if (B.StartBlockLimit==B.EndBlockLimit&&C&&D){if (!B.CheckIsCollapsed()){var E=B.CheckEndOfBlock();B.DeleteContents();if (C!=D){B.SetStart(D,1);B.SetEnd(D,1);};B.Select();A=(C==D);};if (B.CheckStartOfBlock()){var F=B.StartBlock;var G=FCKDomTools.GetPreviousSourceElement(F,true,['BODY',B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,G,F);}else if (FCKBrowserInfo.IsGecko){B.Select();}};B.Release();return A;};FCKEnterKey.prototype._ExecuteBackspace=function(A,B,C){var D=false;if (!B&&C&&C.nodeName.IEquals('LI')&&C.parentNode.parentNode.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};if (B&&B.nodeName.IEquals('LI')){var E=FCKDomTools.GetLastChild(B,['UL','OL']);while (E){B=FCKDomTools.GetLastChild(E,'LI');E=FCKDomTools.GetLastChild(B,['UL','OL']);}};if (B&&C){if (C.nodeName.IEquals('LI')&&!B.nodeName.IEquals('LI')){this._OutdentWithSelection(C,A);return true;};var F=C.parentNode;var G=B.nodeName.toLowerCase();if (FCKListsLib.EmptyElements[G]!=null||G=='table'){FCKDomTools.RemoveNode(B);D=true;}else{FCKDomTools.RemoveNode(C);while (F.innerHTML.Trim().length==0){var H=F.parentNode;H.removeChild(F);F=H;};FCKDomTools.TrimNode(C);FCKDomTools.TrimNode(B);A.SetStart(B,2);A.Collapse(true);var I=A.CreateBookmark();FCKDomTools.MoveChildren(C,B);A.MoveToBookmark(I);A.Select();D=true;}};return D;};FCKEnterKey.prototype.DoDelete=function(){var A=false;var B=new FCKDomRange(this.Window);B.MoveToSelection();if (B.CheckIsCollapsed()&&B.CheckEndOfBlock(FCKBrowserInfo.IsGeckoLike)){var C=B.StartBlock;var D=FCKDomTools.GetNextSourceElement(C,true,[B.StartBlockLimit.nodeName],['UL','OL']);A=this._ExecuteBackspace(B,C,D);};B.Release();return A;};FCKEnterKey.prototype._ExecuteEnterBlock=function(A,B){var C=B||new FCKDomRange(this.Window);if (!B) C.MoveToSelection();if (C.StartBlockLimit==C.EndBlockLimit){if (!C.StartBlock) this._FixBlock(C,true,A);if (!C.EndBlock) this._FixBlock(C,false,A);var D=C.StartBlock;var E=C.EndBlock;if (!C.CheckIsEmpty()) C.DeleteContents();if (D==E){var F;var G=C.CheckStartOfBlock();var H=C.CheckEndOfBlock();if (G&&!H){F=D.cloneNode(false);if (FCKBrowserInfo.IsGeckoLike) F.innerHTML=GECKO_BOGUS;D.parentNode.insertBefore(F,D);if (FCKBrowserInfo.IsIE){C.MoveToNodeContents(F);C.Select();};C.MoveToElementEditStart(D);}else{if (H){var I=D.tagName.toUpperCase();if (G&&I=='LI'){this._OutdentWithSelection(D,C);C.Release();return true;}else{if ((/^H[1-6]$/).test(I)||this._HasShift) F=this.Window.document.createElement(A);else{F=D.cloneNode(false);this._RecreateEndingTree(D,F);};if (FCKBrowserInfo.IsGeckoLike){F.innerHTML=GECKO_BOGUS;if (G) D.innerHTML=GECKO_BOGUS;}}}else{C.SetEnd(D,2);var J=C.ExtractContents();F=D.cloneNode(false);FCKDomTools.TrimNode(J.RootNode);if (J.RootNode.firstChild.nodeType==1&&J.RootNode.firstChild.tagName.toUpperCase().Equals('UL','OL')) F.innerHTML=GECKO_BOGUS;J.AppendTo(F);if (FCKBrowserInfo.IsGecko){this._AppendBogusBr(D);this._AppendBogusBr(F);}};if (F){FCKDomTools.InsertAfterNode(D,F);C.MoveToElementEditStart(F);if (FCKBrowserInfo.IsGeckoLike) F.scrollIntoView(false);}}}else{C.MoveToElementEditStart(E);};C.Select();};C.Release();return true;};FCKEnterKey.prototype._ExecuteEnterBr=function(A){var B=new FCKDomRange(this.Window);B.MoveToSelection();if (B.StartBlockLimit==B.EndBlockLimit){B.DeleteContents();B.MoveToSelection();var C=B.CheckStartOfBlock();var D=B.CheckEndOfBlock();var E=B.StartBlock?B.StartBlock.tagName.toUpperCase():'';var F=this._HasShift;if (!F&&E=='LI') return this._ExecuteEnterBlock(null,B);if (!F&&D&&(/^H[1-6]$/).test(E)){FCKDebug.Output('BR - Header');FCKDomTools.InsertAfterNode(B.StartBlock,this.Window.document.createElement('br'));if (FCKBrowserInfo.IsGecko) FCKDomTools.InsertAfterNode(B.StartBlock,this.Window.document.createTextNode(''));B.SetStart(B.StartBlock.nextSibling,FCKBrowserInfo.IsIE?3:1);}else{FCKDebug.Output('BR - No Header');var G=this.Window.document.createElement('br');B.InsertNode(G);if (FCKBrowserInfo.IsGecko) FCKDomTools.InsertAfterNode(G,this.Window.document.createTextNode(''));if (D&&FCKBrowserInfo.IsGeckoLike) this._AppendBogusBr(G.parentNode);if (FCKBrowserInfo.IsIE) B.SetStart(G,4);else B.SetStart(G.nextSibling,1);};B.Collapse(true);B.Select();};B.Release();return true;};FCKEnterKey.prototype._FixBlock=function(A,B,C){var D=A.CreateBookmark();A.Collapse(B);A.Expand('block_contents');var E=this.Window.document.createElement(C);A.ExtractContents().AppendTo(E);FCKDomTools.TrimNode(E);A.InsertNode(E);A.MoveToBookmark(D);};FCKEnterKey.prototype._AppendBogusBr=function(A){if (!A) return;var B=FCKTools.GetLastItem(A.getElementsByTagName('br'));if (!B||B.getAttribute('type',2)!='_moz') A.appendChild(FCKTools.CreateBogusBR(this.Window.document));};FCKEnterKey.prototype._RecreateEndingTree=function(A,B){while ((A=A.lastChild)&&A.nodeType==1&&FCKListsLib.InlineChildReqElements[A.nodeName.toLowerCase()]!=null) B=B.insertBefore(A.cloneNode(false),B.firstChild);};FCKEnterKey.prototype._OutdentWithSelection=function(A,B){var C=B.CreateBookmark();FCKListHandler.OutdentListItem(A);B.MoveToBookmark(C);B.Select();}
+var FCKDocumentProcessor={};FCKDocumentProcessor._Items=[];FCKDocumentProcessor.AppendNew=function(){var A={};this._Items.AddItem(A);return A;};FCKDocumentProcessor.Process=function(A){var B,i=0;while((B=this._Items[i++])) B.ProcessDocument(A);};var FCKDocumentProcessor_CreateFakeImage=function(A,B){var C=FCK.EditorDocument.createElement('IMG');C.className=A;C.src=FCKConfig.FullBasePath+'images/spacer.gif';C.setAttribute('_fckfakelement','true',0);C.setAttribute('_fckrealelement',FCKTempBin.AddElement(B),0);return C;};if (FCKBrowserInfo.IsIE||FCKBrowserInfo.IsOpera){var FCKAnchorsProcessor=FCKDocumentProcessor.AppendNew();FCKAnchorsProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('A');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.name.length>0){if (C.innerHTML!==''){if (FCKBrowserInfo.IsIE) C.className+=' FCK__AnchorC';}else{var D=FCKDocumentProcessor_CreateFakeImage('FCK__Anchor',C.cloneNode(true));D.setAttribute('_fckanchor','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}}};var FCKPageBreaksProcessor=FCKDocumentProcessor.AppendNew();FCKPageBreaksProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('DIV');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.style.pageBreakAfter=='always'&&C.childNodes.length==1&&C.childNodes[0].style&&C.childNodes[0].style.display=='none'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',C.cloneNode(true));C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}};var FCKFlashProcessor=FCKDocumentProcessor.AppendNew();FCKFlashProcessor.ProcessDocument=function(A){var B=A.getElementsByTagName('EMBED');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=C.attributes['type'];if ((C.src&&C.src.EndsWith('.swf',true))||(D&&D.nodeValue=='application/x-shockwave-flash')){var E=C.cloneNode(true);if (FCKBrowserInfo.IsIE){var F=['scale','play','loop','menu','wmode','quality'];for (var G=0;G<F.length;G++){var H=C.getAttribute(F[G]);if (H) E.setAttribute(F[G],H);};E.setAttribute('type',D.nodeValue);};var I=FCKDocumentProcessor_CreateFakeImage('FCK__Flash',E);I.setAttribute('_fckflash','true',0);FCKFlashProcessor.RefreshView(I,C);C.parentNode.insertBefore(I,C);C.parentNode.removeChild(C);}}};FCKFlashProcessor.RefreshView=function(A,B){if (B.getAttribute('width')>0) A.style.width=FCKTools.ConvertHtmlSizeToStyle(B.getAttribute('width'));if (B.getAttribute('height')>0) A.style.height=FCKTools.ConvertHtmlSizeToStyle(B.getAttribute('height'));};FCK.GetRealElement=function(A){var e=FCKTempBin.Elements[A.getAttribute('_fckrealelement')];if (A.getAttribute('_fckflash')){if (A.style.width.length>0) e.width=FCKTools.ConvertStyleSizeToHtml(A.style.width);if (A.style.height.length>0) e.height=FCKTools.ConvertStyleSizeToHtml(A.style.height);};return e;};if (FCKBrowserInfo.IsIE){FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('HR');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){var D=A.createElement('hr');D.mergeAttributes(C,true);FCKDomTools.InsertAfterNode(C,D);C.parentNode.removeChild(C);}}};FCKDocumentProcessor.AppendNew().ProcessDocument=function(A){var B=A.getElementsByTagName('INPUT');var C;var i=B.length-1;while (i>=0&&(C=B[i--])){if (C.type=='hidden'){var D=FCKDocumentProcessor_CreateFakeImage('FCK__InputHidden',C.cloneNode(true));D.setAttribute('_fckinputhidden','true',0);C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);}}}
+var FCKSelection=FCK.Selection={};
+FCKSelection.GetType=function(){return FCK.EditorDocument.selection.type;};FCKSelection.GetSelectedElement=function(){if (this.GetType()=='Control'){var A=FCK.EditorDocument.selection.createRange();if (A&&A.item) return FCK.EditorDocument.selection.createRange().item(0);};return null;};FCKSelection.GetParentElement=function(){switch (this.GetType()){case 'Control':return FCKSelection.GetSelectedElement().parentElement;case 'None':return null;default:return FCK.EditorDocument.selection.createRange().parentElement();}};FCKSelection.SelectNode=function(A){FCK.Focus();FCK.EditorDocument.selection.empty();var B;try{B=FCK.EditorDocument.body.createControlRange();B.addElement(A);}catch(e){B=FCK.EditorDocument.body.createTextRange();B.moveToElementText(A);};B.select();};FCKSelection.Collapse=function(A){FCK.Focus();if (this.GetType()=='Text'){var B=FCK.EditorDocument.selection.createRange();B.collapse(A==null||A===true);B.select();}};FCKSelection.HasAncestorNode=function(A){var B;if (FCK.EditorDocument.selection.type=="Control"){B=this.GetSelectedElement();}else{var C=FCK.EditorDocument.selection.createRange();B=C.parentElement();};while (B){if (B.tagName==A) return true;B=B.parentNode;};return false;};FCKSelection.MoveToAncestorNode=function(A){var B,oRange;if (!FCK.EditorDocument) return null;if (FCK.EditorDocument.selection.type=="Control"){oRange=FCK.EditorDocument.selection.createRange();for (i=0;i<oRange.length;i++){if (oRange(i).parentNode){B=oRange(i).parentNode;break;}}}else{oRange=FCK.EditorDocument.selection.createRange();B=oRange.parentElement();};while (B&&B.nodeName!=A) B=B.parentNode;return B;};FCKSelection.Delete=function(){var A=FCK.EditorDocument.selection;if (A.type.toLowerCase()!="none"){A.clear();};return A;};
+var FCKTableHandler={};FCKTableHandler.InsertRow=function(){var A=FCKSelection.MoveToAncestorNode('TR');if (!A) return;var B=A.cloneNode(true);A.parentNode.insertBefore(B,A);FCKTableHandler.ClearRow(A);};FCKTableHandler.DeleteRows=function(A){if (!A) A=FCKSelection.MoveToAncestorNode('TR');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');if (B.rows.length==1){FCKTableHandler.DeleteTable(B);return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteTable=function(A){if (!A){A=FCKSelection.GetSelectedElement();if (!A||A.tagName!='TABLE') A=FCKSelection.MoveToAncestorNode('TABLE');};if (!A) return;FCKSelection.SelectNode(A);FCKSelection.Collapse();A.parentNode.removeChild(A);};FCKTableHandler.InsertColumn=function(){var A=FCKSelection.MoveToAncestorNode('TD')||FCKSelection.MoveToAncestorNode('TH');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');var C=A.cellIndex+1;for (var i=0;i<B.rows.length;i++){var D=B.rows[i];if (D.cells.length<C) continue;A=D.cells[C-1].cloneNode(false);if (FCKBrowserInfo.IsGecko) A.innerHTML=GECKO_BOGUS;var E=D.cells[C];if (E) D.insertBefore(A,E);else D.appendChild(A);}};FCKTableHandler.DeleteColumns=function(){var A=FCKSelection.MoveToAncestorNode('TD')||FCKSelection.MoveToAncestorNode('TH');if (!A) return;var B=FCKTools.GetElementAscensor(A,'TABLE');var C=A.cellIndex;for (var i=B.rows.length-1;i>=0;i--){var D=B.rows[i];if (C==0&&D.cells.length==1){FCKTableHandler.DeleteRows(D);continue;};if (D.cells[C]) D.removeChild(D.cells[C]);}};FCKTableHandler.InsertCell=function(A){var B=A?A:FCKSelection.MoveToAncestorNode('TD');if (!B) return null;var C=FCK.EditorDocument.createElement('TD');if (FCKBrowserInfo.IsGecko) C.innerHTML=GECKO_BOGUS;if (B.cellIndex==B.parentNode.cells.length-1){B.parentNode.appendChild(C);}else{B.parentNode.insertBefore(C,B.nextSibling);};return C;};FCKTableHandler.DeleteCell=function(A){if (A.parentNode.cells.length==1){FCKTableHandler.DeleteRows(FCKTools.GetElementAscensor(A,'TR'));return;};A.parentNode.removeChild(A);};FCKTableHandler.DeleteCells=function(){var A=FCKTableHandler.GetSelectedCells();for (var i=A.length-1;i>=0;i--){FCKTableHandler.DeleteCell(A[i]);}};FCKTableHandler.MergeCells=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length<2) return;if (A[0].parentNode!=A[A.length-1].parentNode) return;var B=isNaN(A[0].colSpan)?1:A[0].colSpan;var C='';var D=FCK.EditorDocument.createDocumentFragment();for (var i=A.length-1;i>=0;i--){var E=A[i];for (var c=E.childNodes.length-1;c>=0;c--){var F=E.removeChild(E.childNodes[c]);if ((F.hasAttribute&&F.hasAttribute('_moz_editor_bogus_node'))||(F.getAttribute&&F.getAttribute('type',2)=='_moz')) continue;D.insertBefore(F,D.firstChild);};if (i>0){B+=isNaN(E.colSpan)?1:E.colSpan;FCKTableHandler.DeleteCell(E);}};A[0].colSpan=B;if (FCKBrowserInfo.IsGecko&&D.childNodes.length==0) A[0].innerHTML=GECKO_BOGUS;else A[0].appendChild(D);};FCKTableHandler.SplitCell=function(){var A=FCKTableHandler.GetSelectedCells();if (A.length!=1) return;var B=this._CreateTableMap(A[0].parentNode.parentNode);var C=FCKTableHandler._GetCellIndexSpan(B,A[0].parentNode.rowIndex,A[0]);var D=this._GetCollumnCells(B,C);for (var i=0;i<D.length;i++){if (D[i]==A[0]){var E=this.InsertCell(A[0]);if (!isNaN(A[0].rowSpan)&&A[0].rowSpan>1) E.rowSpan=A[0].rowSpan;}else{if (isNaN(D[i].colSpan)) D[i].colSpan=2;else D[i].colSpan+=1;}}};FCKTableHandler._GetCellIndexSpan=function(A,B,C){if (A.length<B+1) return null;var D=A[B];for (var c=0;c<D.length;c++){if (D[c]==C) return c;};return null;};FCKTableHandler._GetCollumnCells=function(A,B){var C=[];for (var r=0;r<A.length;r++){var D=A[r][B];if (D&&(C.length==0||C[C.length-1]!=D)) C[C.length]=D;};return C;};FCKTableHandler._CreateTableMap=function(A){var B=A.rows;var r=-1;var C=[];for (var i=0;i<B.length;i++){r++;if (!C[r]) C[r]=[];var c=-1;for (var j=0;j<B[i].cells.length;j++){var D=B[i].cells[j];c++;while (C[r][c]) c++;var E=isNaN(D.colSpan)?1:D.colSpan;var F=isNaN(D.rowSpan)?1:D.rowSpan;for (var G=0;G<F;G++){if (!C[r+G]) C[r+G]=[];for (var H=0;H<E;H++){C[r+G][c+H]=B[i].cells[j];}};c+=E-1;}};return C;};FCKTableHandler.ClearRow=function(A){var B=A.cells;for (var i=0;i<B.length;i++){if (FCKBrowserInfo.IsGecko) B[i].innerHTML=GECKO_BOGUS;else B[i].innerHTML='';}};
+FCKTableHandler.GetSelectedCells=function(){var A=[];var B=FCK.EditorDocument.selection.createRange();var C=FCKSelection.GetParentElement();if (C&&C.tagName.Equals('TD','TH')) A[0]=C;else{C=FCKSelection.MoveToAncestorNode('TABLE');if (C){for (var i=0;i<C.cells.length;i++){var D=FCK.EditorDocument.selection.createRange();D.moveToElementText(C.cells[i]);if (B.inRange(D)||(B.compareEndPoints('StartToStart',D)>=0&&B.compareEndPoints('StartToEnd',D)<=0)||(B.compareEndPoints('EndToStart',D)>=0&&B.compareEndPoints('EndToEnd',D)<=0)){A[A.length]=C.cells[i];}}}};return A;};
+var FCKXml=function(){this.Error=false;};FCKXml.prototype.LoadUrl=function(A){this.Error=false;var B=FCKTools.CreateXmlObject('XmlHttp');if (!B){this.Error=true;return;};B.open("GET",A,false);B.send(null);if (B.status==200||B.status==304) this.DOMDocument=B.responseXML;else if (B.status==0&&B.readyState==4){this.DOMDocument=FCKTools.CreateXmlObject('DOMDocument');this.DOMDocument.async=false;this.DOMDocument.resolveExternals=false;this.DOMDocument.loadXML(B.responseText);}else{this.DOMDocument=null;};if (this.DOMDocument==null||this.DOMDocument.firstChild==null){this.Error=true;if (window.confirm('Error loading "'+A+'"\r\nDo you want to see more info?')) alert('URL requested: "'+A+'"\r\nServer response:\r\nStatus: '+B.status+'\r\nResponse text:\r\n'+B.responseText);}};FCKXml.prototype.SelectNodes=function(A,B){if (this.Error) return [];if (B) return B.selectNodes(A);else return this.DOMDocument.selectNodes(A);};FCKXml.prototype.SelectSingleNode=function(A,B){if (this.Error) return null;if (B) return B.selectSingleNode(A);else return this.DOMDocument.selectSingleNode(A);}
+var FCKStyleDef=function(A,B){this.Name=A;this.Element=B.toUpperCase();this.IsObjectElement=FCKRegexLib.ObjectElements.test(this.Element);this.Attributes={};};FCKStyleDef.prototype.AddAttribute=function(A,B){this.Attributes[A]=B;};FCKStyleDef.prototype.GetOpenerTag=function(){var s='<'+this.Element;for (var a in this.Attributes) s+=' '+a+'="'+this.Attributes[a]+'"';return s+'>';};FCKStyleDef.prototype.GetCloserTag=function(){return '</'+this.Element+'>';};FCKStyleDef.prototype.RemoveFromSelection=function(){if (FCKSelection.GetType()=='Control') this._RemoveMe(FCK.ToolbarSet.CurrentInstance.Selection.GetSelectedElement());else this._RemoveMe(FCK.ToolbarSet.CurrentInstance.Selection.GetParentElement());}
+FCKStyleDef.prototype.ApplyToSelection=function(){var A=FCK.ToolbarSet.CurrentInstance.EditorDocument.selection;if (A.type=='Text'){var B=A.createRange();var e=document.createElement(this.Element);e.innerHTML=B.htmlText;this._AddAttributes(e);this._RemoveDuplicates(e);B.pasteHTML(e.outerHTML);}else if (A.type=='Control'){var C=FCK.ToolbarSet.CurrentInstance.Selection.GetSelectedElement();if (C.tagName==this.Element) this._AddAttributes(C);}};FCKStyleDef.prototype._AddAttributes=function(A){for (var a in this.Attributes){switch (a.toLowerCase()){case 'style':A.style.cssText=this.Attributes[a];break;case 'class':A.setAttribute('className',this.Attributes[a],0);break;case 'src':A.setAttribute('_fcksavedurl',this.Attributes[a],0);default:A.setAttribute(a,this.Attributes[a],0);}}};FCKStyleDef.prototype._RemoveDuplicates=function(A){for (var i=0;i<A.children.length;i++){var B=A.children[i];this._RemoveDuplicates(B);if (this.IsEqual(B)) FCKTools.RemoveOuterTags(B);}};FCKStyleDef.prototype.IsEqual=function(e){if (e.tagName!=this.Element) return false;for (var a in this.Attributes){switch (a.toLowerCase()){case 'style':if (e.style.cssText.toLowerCase()!=this.Attributes[a].toLowerCase()) return false;break;case 'class':if (e.getAttribute('className',0)!=this.Attributes[a]) return false;break;default:if (e.getAttribute(a,0)!=this.Attributes[a]) return false;}};return true;};FCKStyleDef.prototype._RemoveMe=function(A){if (!A) return;var B=A.parentElement;if (this.IsEqual(A)){if (this.IsObjectElement){for (var a in this.Attributes){switch (a.toLowerCase()){case 'class':A.removeAttribute('className',0);break;default:A.removeAttribute(a,0);}};return;}else FCKTools.RemoveOuterTags(A);};this._RemoveMe(B);}
+var FCKStylesLoader=function(){this.Styles={};this.StyleGroups={};this.Loaded=false;this.HasObjectElements=false;};FCKStylesLoader.prototype.Load=function(A){var B=new FCKXml();B.LoadUrl(A);var C=B.SelectNodes('Styles/Style');for (var i=0;i<C.length;i++){var D=C[i].attributes.getNamedItem('element').value.toUpperCase();var E=new FCKStyleDef(C[i].attributes.getNamedItem('name').value,D);if (E.IsObjectElement) this.HasObjectElements=true;var F=B.SelectNodes('Attribute',C[i]);for (var j=0;j<F.length;j++){var G=F[j].attributes.getNamedItem('name').value;var H=F[j].attributes.getNamedItem('value').value;if (G.toLowerCase()=='style'){var I=document.createElement('SPAN');I.style.cssText=H;H=I.style.cssText;};E.AddAttribute(G,H);};this.Styles[E.Name]=E;var J=this.StyleGroups[D];if (J==null){this.StyleGroups[D]=[];J=this.StyleGroups[D];};J[J.length]=E;};this.Loaded=true;}
+var FCKNamedCommand=function(A){this.Name=A;};FCKNamedCommand.prototype.Execute=function(){FCK.ExecuteNamedCommand(this.Name);};FCKNamedCommand.prototype.GetState=function(){return FCK.GetNamedCommandState(this.Name);};
+var FCKDialogCommand=function(A,B,C,D,E,F,G){this.Name=A;this.Title=B;this.Url=C;this.Width=D;this.Height=E;this.GetStateFunction=F;this.GetStateParam=G;this.Resizable=false;};FCKDialogCommand.prototype.Execute=function(){FCKDialog.OpenDialog('FCKDialog_'+this.Name,this.Title,this.Url,this.Width,this.Height,null,null,this.Resizable);};FCKDialogCommand.prototype.GetState=function(){if (this.GetStateFunction) return this.GetStateFunction(this.GetStateParam);else return 0;};var FCKUndefinedCommand=function(){this.Name='Undefined';};FCKUndefinedCommand.prototype.Execute=function(){alert(FCKLang.NotImplemented);};FCKUndefinedCommand.prototype.GetState=function(){return 0;};var FCKFontNameCommand=function(){this.Name='FontName';};FCKFontNameCommand.prototype.Execute=function(A){if (A==null||A==""){}else FCK.ExecuteNamedCommand('FontName',A);};FCKFontNameCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FontName');};var FCKFontSizeCommand=function(){this.Name='FontSize';};FCKFontSizeCommand.prototype.Execute=function(A){if (typeof(A)=='string') A=parseInt(A,10);if (A==null||A==''){FCK.ExecuteNamedCommand('FontSize',3);}else FCK.ExecuteNamedCommand('FontSize',A);};FCKFontSizeCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FontSize');};var FCKFormatBlockCommand=function(){this.Name='FormatBlock';};FCKFormatBlockCommand.prototype.Execute=function(A){if (A==null||A=='') FCK.ExecuteNamedCommand('FormatBlock','<P>');else if (A=='div'&&FCKBrowserInfo.IsGecko) FCK.ExecuteNamedCommand('FormatBlock','div');else FCK.ExecuteNamedCommand('FormatBlock','<'+A+'>');};FCKFormatBlockCommand.prototype.GetState=function(){return FCK.GetNamedCommandValue('FormatBlock');};var FCKPreviewCommand=function(){this.Name='Preview';};FCKPreviewCommand.prototype.Execute=function(){FCK.Preview();};FCKPreviewCommand.prototype.GetState=function(){return 0;};var FCKSaveCommand=function(){this.Name='Save';};FCKSaveCommand.prototype.Execute=function(){var A=FCK.GetParentForm();if (typeof(A.onsubmit)=='function'){var B=A.onsubmit();if (B!=null&&B===false) return;};if (typeof(A.submit)=='function') A.submit();else A.submit.click();};FCKSaveCommand.prototype.GetState=function(){return 0;};var FCKNewPageCommand=function(){this.Name='NewPage';};FCKNewPageCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();FCK.SetHTML('');FCKUndo.Typing=true;};FCKNewPageCommand.prototype.GetState=function(){return 0;};var FCKSourceCommand=function(){this.Name='Source';};FCKSourceCommand.prototype.Execute=function(){if (FCKConfig.SourcePopup){var A=FCKConfig.ScreenWidth*0.65;var B=FCKConfig.ScreenHeight*0.65;FCKDialog.OpenDialog('FCKDialog_Source',FCKLang.Source,'dialog/fck_source.html',A,B,null,null,true);}else FCK.SwitchEditMode();};FCKSourceCommand.prototype.GetState=function(){return (FCK.EditMode==0?0:1);};var FCKUndoCommand=function(){this.Name='Undo';};FCKUndoCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsIE) FCKUndo.Undo();else FCK.ExecuteNamedCommand('Undo');};FCKUndoCommand.prototype.GetState=function(){if (FCKBrowserInfo.IsIE) return (FCKUndo.CheckUndoState()?0:-1);else return FCK.GetNamedCommandState('Undo');};var FCKRedoCommand=function(){this.Name='Redo';};FCKRedoCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsIE) FCKUndo.Redo();else FCK.ExecuteNamedCommand('Redo');};FCKRedoCommand.prototype.GetState=function(){if (FCKBrowserInfo.IsIE) return (FCKUndo.CheckRedoState()?0:-1);else return FCK.GetNamedCommandState('Redo');};var FCKPageBreakCommand=function(){this.Name='PageBreak';};FCKPageBreakCommand.prototype.Execute=function(){var e=FCK.EditorDocument.createElement('DIV');e.style.pageBreakAfter='always';e.innerHTML='<span style="DISPLAY:none">&nbsp;</span>';var A=FCKDocumentProcessor_CreateFakeImage('FCK__PageBreak',e);A=FCK.InsertElement(A);};FCKPageBreakCommand.prototype.GetState=function(){return 0;};var FCKUnlinkCommand=function(){this.Name='Unlink';};FCKUnlinkCommand.prototype.Execute=function(){if (FCKBrowserInfo.IsGecko){var A=FCK.Selection.MoveToAncestorNode('A');if (A) FCKTools.RemoveOuterTags(A);return;};FCK.ExecuteNamedCommand(this.Name);};FCKUnlinkCommand.prototype.GetState=function(){var A=FCK.GetNamedCommandState(this.Name);if (A==0&&FCK.EditMode==0){var B=FCKSelection.MoveToAncestorNode('A');var C=(B&&B.name.length>0&&B.href.length==0);if (C) A=-1;};return A;};var FCKSelectAllCommand=function(){this.Name='SelectAll';};FCKSelectAllCommand.prototype.Execute=function(){if (FCK.EditMode==0){FCK.ExecuteNamedCommand('SelectAll');}else{var A=FCK.EditingArea.Textarea;if (FCKBrowserInfo.IsIE){A.createTextRange().execCommand('SelectAll');}else{A.selectionStart=0;A.selectionEnd=A.value.length;};A.focus();}};FCKSelectAllCommand.prototype.GetState=function(){return 0;};var FCKPasteCommand=function(){this.Name='Paste';};FCKPasteCommand.prototype={Execute:function(){if (FCKBrowserInfo.IsIE) FCK.Paste();else FCK.ExecuteNamedCommand('Paste');},GetState:function(){return FCK.GetNamedCommandState('Paste');}};
+var FCKSpellCheckCommand=function(){this.Name='SpellCheck';this.IsEnabled=(FCKConfig.SpellChecker=='ieSpell'||FCKConfig.SpellChecker=='SpellerPages');};FCKSpellCheckCommand.prototype.Execute=function(){switch (FCKConfig.SpellChecker){case 'ieSpell':this._RunIeSpell();break;case 'SpellerPages':FCKDialog.OpenDialog('FCKDialog_SpellCheck','Spell Check','dialog/fck_spellerpages.html',440,480);break;}};FCKSpellCheckCommand.prototype._RunIeSpell=function(){try{var A=new ActiveXObject("ieSpell.ieSpellExtension");A.CheckAllLinkedDocuments(FCK.EditorDocument);}catch(e){if(e.number==-2146827859){if (confirm(FCKLang.IeSpellDownload)) window.open(FCKConfig.IeSpellDownloadUrl,'IeSpellDownload');}else alert('Error Loading ieSpell: '+e.message+' ('+e.number+')');}};FCKSpellCheckCommand.prototype.GetState=function(){return this.IsEnabled?0:-1;}
+var FCKTextColorCommand=function(A){this.Name=A=='ForeColor'?'TextColor':'BGColor';this.Type=A;var B;if (FCKBrowserInfo.IsIE) B=window;else if (FCK.ToolbarSet._IFrame) B=FCKTools.GetElementWindow(FCK.ToolbarSet._IFrame);else B=window.parent;this._Panel=new FCKPanel(B);this._Panel.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');this._Panel.MainNode.className='FCK_Panel';this._CreatePanelBody(this._Panel.Document,this._Panel.MainNode);FCKTools.DisableSelection(this._Panel.Document.body);};FCKTextColorCommand.prototype.Execute=function(A,B,C){FCK._ActiveColorPanelType=this.Type;this._Panel.Show(A,B,C);};FCKTextColorCommand.prototype.SetColor=function(A){if (FCK._ActiveColorPanelType=='ForeColor') FCK.ExecuteNamedCommand('ForeColor',A);else if (FCKBrowserInfo.IsGeckoLike){if (FCKBrowserInfo.IsGecko&&!FCKConfig.GeckoUseSPAN) FCK.EditorDocument.execCommand('useCSS',false,false);FCK.ExecuteNamedCommand('hilitecolor',A);if (FCKBrowserInfo.IsGecko&&!FCKConfig.GeckoUseSPAN) FCK.EditorDocument.execCommand('useCSS',false,true);}else FCK.ExecuteNamedCommand('BackColor',A);delete FCK._ActiveColorPanelType;};FCKTextColorCommand.prototype.GetState=function(){return 0;};function FCKTextColorCommand_OnMouseOver() { this.className='ColorSelected';};function FCKTextColorCommand_OnMouseOut() { this.className='ColorDeselected';};function FCKTextColorCommand_OnClick(){this.className='ColorDeselected';this.Command.SetColor('#'+this.Color);this.Command._Panel.Hide();};function FCKTextColorCommand_AutoOnClick(){this.className='ColorDeselected';this.Command.SetColor('');this.Command._Panel.Hide();};function FCKTextColorCommand_MoreOnClick(){this.className='ColorDeselected';this.Command._Panel.Hide();FCKDialog.OpenDialog('FCKDialog_Color',FCKLang.DlgColorTitle,'dialog/fck_colorselector.html',400,330,this.Command.SetColor);};FCKTextColorCommand.prototype._CreatePanelBody=function(A,B){function CreateSelectionDiv(){var C=A.createElement("DIV");C.className='ColorDeselected';C.onmouseover=FCKTextColorCommand_OnMouseOver;C.onmouseout=FCKTextColorCommand_OnMouseOut;return C;};var D=B.appendChild(A.createElement("TABLE"));D.className='ForceBaseFont';D.style.tableLayout='fixed';D.cellPadding=0;D.cellSpacing=0;D.border=0;D.width=150;var E=D.insertRow(-1).insertCell(-1);E.colSpan=8;var C=E.appendChild(CreateSelectionDiv());C.innerHTML='<table cellspacing="0" cellpadding="0" width="100%" border="0">\n <tr>\n <td><div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #000000"></div></div></td>\n <td nowrap width="100%" align="center">'+FCKLang.ColorAutomatic+'</td>\n </tr>\n </table>';C.Command=this;C.onclick=FCKTextColorCommand_AutoOnClick;var G=FCKConfig.FontColors.toString().split(',');var H=0;while (H<G.length){var I=D.insertRow(-1);for (var i=0;i<8&&H<G.length;i++,H++){C=I.insertCell(-1).appendChild(CreateSelectionDiv());C.Color=G[H];C.innerHTML='<div class="ColorBoxBorder"><div class="ColorBox" style="background-color: #'+G[H]+'"></div></div>';C.Command=this;C.onclick=FCKTextColorCommand_OnClick;}};E=D.insertRow(-1).insertCell(-1);E.colSpan=8;C=E.appendChild(CreateSelectionDiv());C.innerHTML='<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td nowrap align="center">'+FCKLang.ColorMoreColors+'</td></tr></table>';C.Command=this;C.onclick=FCKTextColorCommand_MoreOnClick;}
+var FCKPastePlainTextCommand=function(){this.Name='PasteText';};FCKPastePlainTextCommand.prototype.Execute=function(){FCK.PasteAsPlainText();};FCKPastePlainTextCommand.prototype.GetState=function(){return FCK.GetNamedCommandState('Paste');};
+var FCKPasteWordCommand=function(){this.Name='PasteWord';};FCKPasteWordCommand.prototype.Execute=function(){FCK.PasteFromWord();};FCKPasteWordCommand.prototype.GetState=function(){if (FCKConfig.ForcePasteAsPlainText) return -1;else return FCK.GetNamedCommandState('Paste');};
+var FCKTableCommand=function(A){this.Name=A;};FCKTableCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();switch (this.Name){case 'TableInsertRow':FCKTableHandler.InsertRow();break;case 'TableDeleteRows':FCKTableHandler.DeleteRows();break;case 'TableInsertColumn':FCKTableHandler.InsertColumn();break;case 'TableDeleteColumns':FCKTableHandler.DeleteColumns();break;case 'TableInsertCell':FCKTableHandler.InsertCell();break;case 'TableDeleteCells':FCKTableHandler.DeleteCells();break;case 'TableMergeCells':FCKTableHandler.MergeCells();break;case 'TableSplitCell':FCKTableHandler.SplitCell();break;case 'TableDelete':FCKTableHandler.DeleteTable();break;default:alert(FCKLang.UnknownCommand.replace(/%1/g,this.Name));}};FCKTableCommand.prototype.GetState=function(){return 0;}
+var FCKStyleCommand=function(){this.Name='Style';this.StylesLoader=new FCKStylesLoader();this.StylesLoader.Load(FCKConfig.StylesXmlPath);this.Styles=this.StylesLoader.Styles;};FCKStyleCommand.prototype.Execute=function(A,B){FCKUndo.SaveUndoStep();if (B.Selected) B.Style.RemoveFromSelection();else B.Style.ApplyToSelection();FCKUndo.SaveUndoStep();FCK.Focus();FCK.Events.FireEvent("OnSelectionChange");};FCKStyleCommand.prototype.GetState=function(){if (!FCK.EditorDocument) return -1;var A=FCK.EditorDocument.selection;if (FCKSelection.GetType()=='Control'){var e=FCKSelection.GetSelectedElement();if (e) return this.StylesLoader.StyleGroups[e.tagName]?0:-1;};return 0;};FCKStyleCommand.prototype.GetActiveStyles=function(){var A=[];if (FCKSelection.GetType()=='Control') this._CheckStyle(FCKSelection.GetSelectedElement(),A,false);else this._CheckStyle(FCKSelection.GetParentElement(),A,true);return A;};FCKStyleCommand.prototype._CheckStyle=function(A,B,C){if (!A) return;if (A.nodeType==1){var D=this.StylesLoader.StyleGroups[A.tagName];if (D){for (var i=0;i<D.length;i++){if (D[i].IsEqual(A)) B[B.length]=D[i];}}};if (C) this._CheckStyle(A.parentNode,B,C);}
+var FCKFitWindow=function(){this.Name='FitWindow';};FCKFitWindow.prototype.Execute=function(){var A=window.frameElement;var B=A.style;var C=parent;var D=C.document.documentElement;var E=C.document.body;var F=E.style;var G;if (!this.IsMaximized){if(FCKBrowserInfo.IsIE) C.attachEvent('onresize',FCKFitWindow_Resize);else C.addEventListener('resize',FCKFitWindow_Resize,true);this._ScrollPos=FCKTools.GetScrollPosition(C);G=A;while((G=G.parentNode)){if (G.nodeType==1) G._fckSavedStyles=FCKTools.SaveStyles(G);};if (FCKBrowserInfo.IsIE){this.documentElementOverflow=D.style.overflow;D.style.overflow='hidden';F.overflow='hidden';}else{F.overflow='hidden';F.width='0px';F.height='0px';};this._EditorFrameStyles=FCKTools.SaveStyles(A);var H=FCKTools.GetViewPaneSize(C);B.position="absolute";B.zIndex=FCKConfig.FloatingPanelsZIndex-1;B.left="0px";B.top="0px";B.width=H.Width+"px";B.height=H.Height+"px";if (!FCKBrowserInfo.IsIE){B.borderRight=B.borderBottom="9999px solid white";B.backgroundColor="white";};C.scrollTo(0,0);this.IsMaximized=true;}else{if(FCKBrowserInfo.IsIE) C.detachEvent("onresize",FCKFitWindow_Resize);else C.removeEventListener("resize",FCKFitWindow_Resize,true);G=A;while((G=G.parentNode)){if (G._fckSavedStyles){FCKTools.RestoreStyles(G,G._fckSavedStyles);G._fckSavedStyles=null;}};if (FCKBrowserInfo.IsIE) D.style.overflow=this.documentElementOverflow;FCKTools.RestoreStyles(A,this._EditorFrameStyles);C.scrollTo(this._ScrollPos.X,this._ScrollPos.Y);this.IsMaximized=false;};FCKToolbarItems.GetItem('FitWindow').RefreshState();FCK.EditingArea.MakeEditable();FCK.Focus();};FCKFitWindow.prototype.GetState=function(){if (FCKConfig.ToolbarLocation!='In') return -1;else return (this.IsMaximized?1:0);};function FCKFitWindow_Resize(){var A=FCKTools.GetViewPaneSize(parent);var B=window.frameElement.style;B.width=A.Width+'px';B.height=A.Height+'px';};
+var FCKCommands=FCK.Commands={};FCKCommands.LoadedCommands={};FCKCommands.RegisterCommand=function(A,B){this.LoadedCommands[A]=B;};FCKCommands.GetCommand=function(A){var B=FCKCommands.LoadedCommands[A];if (B) return B;switch (A){case 'DocProps':B=new FCKDialogCommand('DocProps',FCKLang.DocProps,'dialog/fck_docprops.html',400,390,FCKCommands.GetFullPageState);break;case 'Templates':B=new FCKDialogCommand('Templates',FCKLang.DlgTemplatesTitle,'dialog/fck_template.html',380,450);break;case 'Link':B=new FCKDialogCommand('Link',FCKLang.DlgLnkWindowTitle,'dialog/fck_link.html',400,330);break;case 'Unlink':B=new FCKUnlinkCommand();break;case 'Anchor':B=new FCKDialogCommand('Anchor',FCKLang.DlgAnchorTitle,'dialog/fck_anchor.html',370,170);break;case 'BulletedList':B=new FCKDialogCommand('BulletedList',FCKLang.BulletedListProp,'dialog/fck_listprop.html?UL',370,170);break;case 'NumberedList':B=new FCKDialogCommand('NumberedList',FCKLang.NumberedListProp,'dialog/fck_listprop.html?OL',370,170);break;case 'About':B=new FCKDialogCommand('About',FCKLang.About,'dialog/fck_about.html',400,330);break;case 'Find':B=new FCKDialogCommand('Find',FCKLang.DlgFindTitle,'dialog/fck_find.html',340,170);break;case 'Replace':B=new FCKDialogCommand('Replace',FCKLang.DlgReplaceTitle,'dialog/fck_replace.html',340,200);break;case 'Image':B=new FCKDialogCommand('Image',FCKLang.DlgImgTitle,'dialog/fck_image.html',450,400);break;case 'Flash':B=new FCKDialogCommand('Flash',FCKLang.DlgFlashTitle,'dialog/fck_flash.html',450,400);break;case 'SpecialChar':B=new FCKDialogCommand('SpecialChar',FCKLang.DlgSpecialCharTitle,'dialog/fck_specialchar.html',400,320);break;case 'Smiley':B=new FCKDialogCommand('Smiley',FCKLang.DlgSmileyTitle,'dialog/fck_smiley.html',FCKConfig.SmileyWindowWidth,FCKConfig.SmileyWindowHeight);break;case 'Table':B=new FCKDialogCommand('Table',FCKLang.DlgTableTitle,'dialog/fck_table.html',450,250);break;case 'TableProp':B=new FCKDialogCommand('Table',FCKLang.DlgTableTitle,'dialog/fck_table.html?Parent',400,250);break;case 'TableCellProp':B=new FCKDialogCommand('TableCell',FCKLang.DlgCellTitle,'dialog/fck_tablecell.html',550,250);break;case 'Style':B=new FCKStyleCommand();break;case 'FontName':B=new FCKFontNameCommand();break;case 'FontSize':B=new FCKFontSizeCommand();break;case 'FontFormat':B=new FCKFormatBlockCommand();break;case 'Source':B=new FCKSourceCommand();break;case 'Preview':B=new FCKPreviewCommand();break;case 'Save':B=new FCKSaveCommand();break;case 'NewPage':B=new FCKNewPageCommand();break;case 'PageBreak':B=new FCKPageBreakCommand();break;case 'TextColor':B=new FCKTextColorCommand('ForeColor');break;case 'BGColor':B=new FCKTextColorCommand('BackColor');break;case 'Paste':B=new FCKPasteCommand();break;case 'PasteText':B=new FCKPastePlainTextCommand();break;case 'PasteWord':B=new FCKPasteWordCommand();break;case 'TableInsertRow':B=new FCKTableCommand('TableInsertRow');break;case 'TableDeleteRows':B=new FCKTableCommand('TableDeleteRows');break;case 'TableInsertColumn':B=new FCKTableCommand('TableInsertColumn');break;case 'TableDeleteColumns':B=new FCKTableCommand('TableDeleteColumns');break;case 'TableInsertCell':B=new FCKTableCommand('TableInsertCell');break;case 'TableDeleteCells':B=new FCKTableCommand('TableDeleteCells');break;case 'TableMergeCells':B=new FCKTableCommand('TableMergeCells');break;case 'TableSplitCell':B=new FCKTableCommand('TableSplitCell');break;case 'TableDelete':B=new FCKTableCommand('TableDelete');break;case 'Form':B=new FCKDialogCommand('Form',FCKLang.Form,'dialog/fck_form.html',380,230);break;case 'Checkbox':B=new FCKDialogCommand('Checkbox',FCKLang.Checkbox,'dialog/fck_checkbox.html',380,230);break;case 'Radio':B=new FCKDialogCommand('Radio',FCKLang.RadioButton,'dialog/fck_radiobutton.html',380,230);break;case 'TextField':B=new FCKDialogCommand('TextField',FCKLang.TextField,'dialog/fck_textfield.html',380,230);break;case 'Textarea':B=new FCKDialogCommand('Textarea',FCKLang.Textarea,'dialog/fck_textarea.html',380,230);break;case 'HiddenField':B=new FCKDialogCommand('HiddenField',FCKLang.HiddenField,'dialog/fck_hiddenfield.html',380,230);break;case 'Button':B=new FCKDialogCommand('Button',FCKLang.Button,'dialog/fck_button.html',380,230);break;case 'Select':B=new FCKDialogCommand('Select',FCKLang.SelectionField,'dialog/fck_select.html',400,380);break;case 'ImageButton':B=new FCKDialogCommand('ImageButton',FCKLang.ImageButton,'dialog/fck_image.html?ImageButton',450,400);break;case 'SpellCheck':B=new FCKSpellCheckCommand();break;case 'FitWindow':B=new FCKFitWindow();break;case 'Undo':B=new FCKUndoCommand();break;case 'Redo':B=new FCKRedoCommand();break;case 'SelectAll':B=new FCKSelectAllCommand();break;case 'Undefined':B=new FCKUndefinedCommand();break;default:if (FCKRegexLib.NamedCommands.test(A)) B=new FCKNamedCommand(A);else{alert(FCKLang.UnknownCommand.replace(/%1/g,A));return null;}};FCKCommands.LoadedCommands[A]=B;return B;};FCKCommands.GetFullPageState=function(){return FCKConfig.FullPage?0:-1;};
+var FCKPanel=function(A){this.IsRTL=(FCKLang.Dir=='rtl');this.IsContextMenu=false;this._LockCounter=0;this._Window=A||window;var B;if (FCKBrowserInfo.IsIE){this._Popup=this._Window.createPopup();B=this.Document=this._Popup.document;FCK.IECleanup.AddItem(this,FCKPanel_Cleanup);}else{var C=this._IFrame=this._Window.document.createElement('iframe');C.src='javascript:void(0)';C.allowTransparency=true;C.frameBorder='0';C.scrolling='no';C.style.position='absolute';C.style.zIndex=FCKConfig.FloatingPanelsZIndex;C.width=C.height=0;if (this._Window==window.parent&&window.frameElement) window.frameElement.parentNode.insertBefore(C,window.frameElement);else this._Window.document.body.appendChild(C);var D=C.contentWindow;B=this.Document=D.document;var E='';if (FCKBrowserInfo.IsSafari) E='<base href="'+window.document.location+'">';B.open();B.write('<html><head>'+E+'<\/head><body style="margin:0px;padding:0px;"><\/body><\/html>');B.close();FCKTools.AddEventListenerEx(D,'focus',FCKPanel_Window_OnFocus,this);FCKTools.AddEventListenerEx(D,'blur',FCKPanel_Window_OnBlur,this);};B.dir=FCKLang.Dir;B.oncontextmenu=FCKTools.CancelEvent;this.MainNode=B.body.appendChild(B.createElement('DIV'));this.MainNode.style.cssFloat=this.IsRTL?'right':'left';};FCKPanel.prototype.AppendStyleSheet=function(A){FCKTools.AppendStyleSheet(this.Document,A);};FCKPanel.prototype.Preload=function(x,y,A){if (this._Popup) this._Popup.show(x,y,0,0,A);};FCKPanel.prototype.Show=function(x,y,A,B,C){var D;if (this._Popup){this._Popup.show(x,y,0,0,A);this.MainNode.style.width=B?B+'px':'';this.MainNode.style.height=C?C+'px':'';D=this.MainNode.offsetWidth;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=(x*-1)+A.offsetWidth-D;};this._Popup.show(x,y,D,this.MainNode.offsetHeight,A);if (this.OnHide){if (this._Timer) CheckPopupOnHide.call(this,true);this._Timer=FCKTools.SetInterval(CheckPopupOnHide,100,this);}}else{if (typeof(FCKFocusManager)!='undefined') FCKFocusManager.Lock();if (this.ParentPanel) this.ParentPanel.Lock();this.MainNode.style.width=B?B+'px':'';this.MainNode.style.height=C?C+'px':'';D=this.MainNode.offsetWidth;if (!B) this._IFrame.width=1;if (!C) this._IFrame.height=1;D=this.MainNode.offsetWidth;var E=FCKTools.GetElementPosition(A.nodeType==9?(FCKTools.IsStrictMode(A)?A.documentElement:A.body):A,this._Window);if (this.IsRTL&&!this.IsContextMenu) x=(x*-1);x+=E.X;y+=E.Y;if (this.IsRTL){if (this.IsContextMenu) x=x-D+1;else if (A) x=x+A.offsetWidth-D;}else{var F=FCKTools.GetViewPaneSize(this._Window);var G=FCKTools.GetScrollPosition(this._Window);var H=F.Height+G.Y;var I=F.Width+G.X;if ((x+D)>I) x-=x+D-I;if ((y+this.MainNode.offsetHeight)>H) y-=y+this.MainNode.offsetHeight-H;};if (x<0) x=0;this._IFrame.style.left=x+'px';this._IFrame.style.top=y+'px';var J=D;var K=this.MainNode.offsetHeight;this._IFrame.width=J;this._IFrame.height=K;this._IFrame.contentWindow.focus();};this._IsOpened=true;FCKTools.RunFunction(this.OnShow,this);};FCKPanel.prototype.Hide=function(A){if (this._Popup) this._Popup.hide();else{if (!this._IsOpened) return;if (typeof(FCKFocusManager)!='undefined') FCKFocusManager.Unlock();this._IFrame.width=this._IFrame.height=0;this._IsOpened=false;if (this.ParentPanel) this.ParentPanel.Unlock();if (!A) FCKTools.RunFunction(this.OnHide,this);}};FCKPanel.prototype.CheckIsOpened=function(){if (this._Popup) return this._Popup.isOpen;else return this._IsOpened;};FCKPanel.prototype.CreateChildPanel=function(){var A=this._Popup?FCKTools.GetDocumentWindow(this.Document):this._Window;var B=new FCKPanel(A);B.ParentPanel=this;return B;};FCKPanel.prototype.Lock=function(){this._LockCounter++;};FCKPanel.prototype.Unlock=function(){if (--this._LockCounter==0&&!this.HasFocus) this.Hide();};function FCKPanel_Window_OnFocus(e,A){A.HasFocus=true;};function FCKPanel_Window_OnBlur(e,A){A.HasFocus=false;if (A._LockCounter==0) FCKTools.RunFunction(A.Hide,A);};function CheckPopupOnHide(A){if (A||!this._Popup.isOpen){window.clearInterval(this._Timer);this._Timer=null;FCKTools.RunFunction(this.OnHide,this);}};function FCKPanel_Cleanup(){this._Popup=null;this._Window=null;this.Document=null;this.MainNode=null;}
+var FCKIcon=function(A){var B=A?typeof(A):'undefined';switch (B){case 'number':this.Path=FCKConfig.SkinPath+'fck_strip.gif';this.Size=16;this.Position=A;break;case 'undefined':this.Path=FCK_SPACER_PATH;break;case 'string':this.Path=A;break;default:this.Path=A[0];this.Size=A[1];this.Position=A[2];}};FCKIcon.prototype.CreateIconElement=function(A){var B,eIconImage;if (this.Position){var C='-'+((this.Position-1)*this.Size)+'px';if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path;eIconImage.style.top=C;}else{B=A.createElement('IMG');B.src=FCK_SPACER_PATH;B.style.backgroundPosition='0px '+C;B.style.backgroundImage='url('+this.Path+')';}}else{if (FCKBrowserInfo.IsIE){B=A.createElement('DIV');eIconImage=B.appendChild(A.createElement('IMG'));eIconImage.src=this.Path?this.Path:FCK_SPACER_PATH;}else{B=A.createElement('IMG');B.src=this.Path?this.Path:FCK_SPACER_PATH;}};B.className='TB_Button_Image';return B;}
+var FCKToolbarButtonUI=function(A,B,C,D,E,F){this.Name=A;this.Label=B||A;this.Tooltip=C||this.Label;this.Style=E||0;this.State=F||0;this.Icon=new FCKIcon(D);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarButtonUI_Cleanup);};FCKToolbarButtonUI.prototype._CreatePaddingElement=function(A){var B=A.createElement('IMG');B.className='TB_Button_Padding';B.src=FCK_SPACER_PATH;return B;};FCKToolbarButtonUI.prototype.Create=function(A){var B=this.MainElement;if (B){FCKToolbarButtonUI_Cleanup.call(this);if (B.parentNode) B.parentNode.removeChild(B);B=this.MainElement=null;};var C=FCKTools.GetElementDocument(A);B=this.MainElement=C.createElement('DIV');B._FCKButton=this;B.title=this.Tooltip;if (FCKBrowserInfo.IsGecko) B.onmousedown=FCKTools.CancelEvent;this.ChangeState(this.State,true);if (this.Style==0&&!this.ShowArrow){B.appendChild(this.Icon.CreateIconElement(C));}else{var D=B.appendChild(C.createElement('TABLE'));D.cellPadding=0;D.cellSpacing=0;var E=D.insertRow(-1);var F=E.insertCell(-1);if (this.Style==0||this.Style==2) F.appendChild(this.Icon.CreateIconElement(C));else F.appendChild(this._CreatePaddingElement(C));if (this.Style==1||this.Style==2){F=E.insertCell(-1);F.className='TB_Button_Text';F.noWrap=true;F.appendChild(C.createTextNode(this.Label));};if (this.ShowArrow){if (this.Style!=0){E.insertCell(-1).appendChild(this._CreatePaddingElement(C));};F=E.insertCell(-1);var G=F.appendChild(C.createElement('IMG'));G.src=FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif';G.width=5;G.height=3;};F=E.insertCell(-1);F.appendChild(this._CreatePaddingElement(C));};A.appendChild(B);};FCKToolbarButtonUI.prototype.ChangeState=function(A,B){if (!B&&this.State==A) return;var e=this.MainElement;switch (parseInt(A,10)){case 0:e.className='TB_Button_Off';e.onmouseover=FCKToolbarButton_OnMouseOverOff;e.onmouseout=FCKToolbarButton_OnMouseOutOff;e.onclick=FCKToolbarButton_OnClick;break;case 1:e.className='TB_Button_On';e.onmouseover=FCKToolbarButton_OnMouseOverOn;e.onmouseout=FCKToolbarButton_OnMouseOutOn;e.onclick=FCKToolbarButton_OnClick;break;case -1:e.className='TB_Button_Disabled';e.onmouseover=null;e.onmouseout=null;e.onclick=null;break;};this.State=A;};function FCKToolbarButtonUI_Cleanup(){if (this.MainElement){this.MainElement._FCKButton=null;this.MainElement=null;}};function FCKToolbarButton_OnMouseOverOn(){this.className='TB_Button_On_Over';};function FCKToolbarButton_OnMouseOutOn(){this.className='TB_Button_On';};function FCKToolbarButton_OnMouseOverOff(){this.className='TB_Button_Off_Over';};function FCKToolbarButton_OnMouseOutOff(){this.className='TB_Button_Off';};function FCKToolbarButton_OnClick(e){if (this._FCKButton.OnClick) this._FCKButton.OnClick(this._FCKButton);};
+var FCKToolbarButton=function(A,B,C,D,E,F,G){this.CommandName=A;this.Label=B;this.Tooltip=C;this.Style=D;this.SourceView=E?true:false;this.ContextSensitive=F?true:false;if (G==null) this.IconPath=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(G)=='number') this.IconPath=[FCKConfig.SkinPath+'fck_strip.gif',16,G];};FCKToolbarButton.prototype.Create=function(A){this._UIButton=new FCKToolbarButtonUI(this.CommandName,this.Label,this.Tooltip,this.IconPath,this.Style);this._UIButton.OnClick=this.Click;this._UIButton._ToolbarButton=this;this._UIButton.Create(A);};FCKToolbarButton.prototype.RefreshState=function(){var A=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (A==this._UIButton.State) return;this._UIButton.ChangeState(A);};FCKToolbarButton.prototype.Click=function(){var A=this._ToolbarButton||this;FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(A.CommandName).Execute();};FCKToolbarButton.prototype.Enable=function(){this.RefreshState();};FCKToolbarButton.prototype.Disable=function(){this._UIButton.ChangeState(-1);}
+var FCKSpecialCombo=function(A,B,C,D,E){this.FieldWidth=B||100;this.PanelWidth=C||150;this.PanelMaxHeight=D||150;this.Label='&nbsp;';this.Caption=A;this.Tooltip=A;this.Style=2;this.Enabled=true;this.Items={};this._Panel=new FCKPanel(E||window);this._Panel.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');this._PanelBox=this._Panel.MainNode.appendChild(this._Panel.Document.createElement('DIV'));this._PanelBox.className='SC_Panel';this._PanelBox.style.width=this.PanelWidth+'px';this._PanelBox.innerHTML='<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>';this._ItemsHolderEl=this._PanelBox.getElementsByTagName('TD')[0];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKSpecialCombo_Cleanup);};function FCKSpecialCombo_ItemOnMouseOver(){this.className+=' SC_ItemOver';};function FCKSpecialCombo_ItemOnMouseOut(){this.className=this.originalClass;};function FCKSpecialCombo_ItemOnClick(){this.className=this.originalClass;this.FCKSpecialCombo._Panel.Hide();this.FCKSpecialCombo.SetLabel(this.FCKItemLabel);if (typeof(this.FCKSpecialCombo.OnSelect)=='function') this.FCKSpecialCombo.OnSelect(this.FCKItemID,this);};FCKSpecialCombo.prototype.AddItem=function(A,B,C,D){var E=this._ItemsHolderEl.appendChild(this._Panel.Document.createElement('DIV'));E.className=E.originalClass='SC_Item';E.innerHTML=B;E.FCKItemID=A;E.FCKItemLabel=C||A;E.FCKSpecialCombo=this;E.Selected=false;if (FCKBrowserInfo.IsIE) E.style.width='100%';if (D) E.style.backgroundColor=D;E.onmouseover=FCKSpecialCombo_ItemOnMouseOver;E.onmouseout=FCKSpecialCombo_ItemOnMouseOut;E.onclick=FCKSpecialCombo_ItemOnClick;this.Items[A.toString().toLowerCase()]=E;return E;};FCKSpecialCombo.prototype.SelectItem=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];if (B){B.className=B.originalClass='SC_ItemSelected';B.Selected=true;}};FCKSpecialCombo.prototype.SelectItemByLabel=function(A,B){for (var C in this.Items){var D=this.Items[C];if (D.FCKItemLabel==A){D.className=D.originalClass='SC_ItemSelected';D.Selected=true;if (B) this.SetLabel(A);}}};FCKSpecialCombo.prototype.DeselectAll=function(A){for (var i in this.Items){this.Items[i].className=this.Items[i].originalClass='SC_Item';this.Items[i].Selected=false;};if (A) this.SetLabel('');};FCKSpecialCombo.prototype.SetLabelById=function(A){A=A?A.toString().toLowerCase():'';var B=this.Items[A];this.SetLabel(B?B.FCKItemLabel:'');};FCKSpecialCombo.prototype.SetLabel=function(A){this.Label=A.length==0?'&nbsp;':A;if (this._LabelEl){this._LabelEl.innerHTML=this.Label;FCKTools.DisableSelection(this._LabelEl);}};FCKSpecialCombo.prototype.SetEnabled=function(A){this.Enabled=A;this._OuterTable.className=A?'':'SC_FieldDisabled';};FCKSpecialCombo.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var C=this._OuterTable=A.appendChild(B.createElement('TABLE'));C.cellPadding=0;C.cellSpacing=0;C.insertRow(-1);var D;var E;switch (this.Style){case 0:D='TB_ButtonType_Icon';E=false;break;case 1:D='TB_ButtonType_Text';E=false;break;case 2:E=true;break;};if (this.Caption&&this.Caption.length>0&&E){var F=C.rows[0].insertCell(-1);F.innerHTML=this.Caption;F.className='SC_FieldCaption';};var G=FCKTools.AppendElement(C.rows[0].insertCell(-1),'div');if (E){G.className='SC_Field';G.style.width=this.FieldWidth+'px';G.innerHTML='<table width="100%" cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldLabel"><label>&nbsp;</label></td><td class="SC_FieldButton">&nbsp;</td></tr></tbody></table>';this._LabelEl=G.getElementsByTagName('label')[0];this._LabelEl.innerHTML=this.Label;}else{G.className='TB_Button_Off';G.innerHTML='<table title="'+this.Tooltip+'" class="'+D+'" cellspacing="0" cellpadding="0" border="0"><tr><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td><td class="TB_Text">'+this.Caption+'</td><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td><td class="TB_ButtonArrow"><img src="'+FCKConfig.SkinPath+'images/toolbar.buttonarrow.gif" width="5" height="3"></td><td><img class="TB_Button_Padding" src="'+FCK_SPACER_PATH+'" /></td></tr></table>';};G.SpecialCombo=this;G.onmouseover=FCKSpecialCombo_OnMouseOver;G.onmouseout=FCKSpecialCombo_OnMouseOut;G.onclick=FCKSpecialCombo_OnClick;FCKTools.DisableSelection(this._Panel.Document.body);};function FCKSpecialCombo_Cleanup(){this._LabelEl=null;this._OuterTable=null;this._ItemsHolderEl=null;this._PanelBox=null;if (this.Items){for (var A in this.Items) this.Items[A]=null;}};function FCKSpecialCombo_OnMouseOver(){if (this.SpecialCombo.Enabled){switch (this.SpecialCombo.Style){case 0:this.className='TB_Button_On_Over';break;case 1:this.className='TB_Button_On_Over';break;case 2:this.className='SC_Field SC_FieldOver';break;}}};function FCKSpecialCombo_OnMouseOut(){switch (this.SpecialCombo.Style){case 0:this.className='TB_Button_Off';break;case 1:this.className='TB_Button_Off';break;case 2:this.className='SC_Field';break;}};function FCKSpecialCombo_OnClick(e){var A=this.SpecialCombo;if (A.Enabled){var B=A._Panel;var C=A._PanelBox;var D=A._ItemsHolderEl;var E=A.PanelMaxHeight;if (A.OnBeforeClick) A.OnBeforeClick(A);if (FCKBrowserInfo.IsIE) B.Preload(0,this.offsetHeight,this);if (D.offsetHeight>E) C.style.height=E+'px';else C.style.height='';B.Show(0,this.offsetHeight,this);}};
+var FCKToolbarSpecialCombo=function(){this.SourceView=false;this.ContextSensitive=true;this._LastValue=null;};function FCKToolbarSpecialCombo_OnSelect(A,B){FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Execute(A,B);};FCKToolbarSpecialCombo.prototype.Create=function(A){this._Combo=new FCKSpecialCombo(this.GetLabel(),this.FieldWidth,this.PanelWidth,this.PanelMaxHeight,FCKBrowserInfo.IsIE?window:FCKTools.GetElementWindow(A).parent);this._Combo.Tooltip=this.Tooltip;this._Combo.Style=this.Style;this.CreateItems(this._Combo);this._Combo.Create(A);this._Combo.CommandName=this.CommandName;this._Combo.OnSelect=FCKToolbarSpecialCombo_OnSelect;};function FCKToolbarSpecialCombo_RefreshActiveItems(A,B){A.DeselectAll();A.SelectItem(B);A.SetLabelById(B);};FCKToolbarSpecialCombo.prototype.RefreshState=function(){var A;var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetState();if (B!=-1){A=1;if (this.RefreshActiveItems) this.RefreshActiveItems(this._Combo,B);else{if (this._LastValue!=B){this._LastValue=B;FCKToolbarSpecialCombo_RefreshActiveItems(this._Combo,B);}}}else A=-1;if (A==this.State) return;if (A==-1){this._Combo.DeselectAll();this._Combo.SetLabel('');};this.State=A;this._Combo.SetEnabled(A!=-1);};FCKToolbarSpecialCombo.prototype.Enable=function(){this.RefreshState();};FCKToolbarSpecialCombo.prototype.Disable=function(){this.State=-1;this._Combo.DeselectAll();this._Combo.SetLabel('');this._Combo.SetEnabled(false);};
+var FCKToolbarFontsCombo=function(A,B){this.CommandName='FontName';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarFontsCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontsCombo.prototype.GetLabel=function(){return FCKLang.Font;};FCKToolbarFontsCombo.prototype.CreateItems=function(A){var B=FCKConfig.FontNames.split(';');for (var i=0;i<B.length;i++) this._Combo.AddItem(B[i],'<font face="'+B[i]+'" style="font-size: 12px">'+B[i]+'</font>');}
+var FCKToolbarFontSizeCombo=function(A,B){this.CommandName='FontSize';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarFontSizeCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontSizeCombo.prototype.GetLabel=function(){return FCKLang.FontSize;};FCKToolbarFontSizeCombo.prototype.CreateItems=function(A){A.FieldWidth=70;var B=FCKConfig.FontSizes.split(';');for (var i=0;i<B.length;i++){var C=B[i].split('/');this._Combo.AddItem(C[0],'<font size="'+C[0]+'">'+C[1]+'</font>',C[1]);}}
+var FCKToolbarFontFormatCombo=function(A,B){this.CommandName='FontFormat';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;this.NormalLabel='Normal';this.PanelWidth=190;};FCKToolbarFontFormatCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarFontFormatCombo.prototype.GetLabel=function(){return FCKLang.FontFormat;};FCKToolbarFontFormatCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) B.body.id=FCKConfig.BodyId;if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) B.body.className+=' '+FCKConfig.BodyClass;var C=FCKLang['FontFormats'].split(';');var D={p:C[0],pre:C[1],address:C[2],h1:C[3],h2:C[4],h3:C[5],h4:C[6],h5:C[7],h6:C[8],div:C[9]};var E=FCKConfig.FontFormats.split(';');for (var i=0;i<E.length;i++){var F=E[i];var G=D[F];if (F=='p') this.NormalLabel=G;this._Combo.AddItem(F,'<div class="BaseFont"><'+F+'>'+G+'</'+F+'></div>',G);}};if (FCKBrowserInfo.IsIE){FCKToolbarFontFormatCombo.prototype.RefreshActiveItems=function(A,B){if (B==this.NormalLabel){if (A.Label!='&nbsp;') A.DeselectAll(true);}else{if (this._LastValue==B) return;A.SelectItemByLabel(B,true);};this._LastValue=B;}}
+var FCKToolbarStyleCombo=function(A,B){this.CommandName='Style';this.Label=this.GetLabel();this.Tooltip=A?A:this.Label;this.Style=B?B:2;};FCKToolbarStyleCombo.prototype=new FCKToolbarSpecialCombo;FCKToolbarStyleCombo.prototype.GetLabel=function(){return FCKLang.Style;};FCKToolbarStyleCombo.prototype.CreateItems=function(A){var B=A._Panel.Document;FCKTools.AppendStyleSheet(B,FCKConfig.ToolbarComboPreviewCSS);B.body.className+=' ForceBaseFont';if (FCKConfig.BodyId&&FCKConfig.BodyId.length>0) B.body.id=FCKConfig.BodyId;if (FCKConfig.BodyClass&&FCKConfig.BodyClass.length>0) B.body.className+=' '+FCKConfig.BodyClass;if (!(FCKBrowserInfo.IsGecko&&FCKBrowserInfo.IsGecko10)) A.OnBeforeClick=this.RefreshVisibleItems;var C=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).Styles;for (var s in C){var D=C[s];var E;if (D.IsObjectElement) E=A.AddItem(s,s);else E=A.AddItem(s,D.GetOpenerTag()+s+D.GetCloserTag());E.Style=D;}};FCKToolbarStyleCombo.prototype.RefreshActiveItems=function(A){A.DeselectAll();var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName).GetActiveStyles();if (B.length>0){for (var i=0;i<B.length;i++) A.SelectItem(B[i].Name);A.SetLabelById(B[0].Name);}else A.SetLabel('');};FCKToolbarStyleCombo.prototype.RefreshVisibleItems=function(A){if (FCKSelection.GetType()=='Control') var B=FCKSelection.GetSelectedElement().tagName;for (var i in A.Items){var C=A.Items[i];if ((B&&C.Style.Element==B)||(!B&&!C.Style.IsObjectElement)) C.style.display='';else C.style.display='none';}}
+var FCKToolbarPanelButton=function(A,B,C,D,E){this.CommandName=A;var F;if (E==null) F=FCKConfig.SkinPath+'toolbar/'+A.toLowerCase()+'.gif';else if (typeof(E)=='number') F=[FCKConfig.SkinPath+'fck_strip.gif',16,E];var G=this._UIButton=new FCKToolbarButtonUI(A,B,C,F,D);G._FCKToolbarPanelButton=this;G.ShowArrow=true;G.OnClick=FCKToolbarPanelButton_OnButtonClick;};FCKToolbarPanelButton.prototype.TypeName='FCKToolbarPanelButton';FCKToolbarPanelButton.prototype.Create=function(A){A.className+='Menu';this._UIButton.Create(A);var B=FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(this.CommandName)._Panel;B._FCKToolbarPanelButton=this;var C=B.Document.body.appendChild(B.Document.createElement('div'));C.style.position='absolute';C.style.top='0px';var D=this.LineImg=C.appendChild(B.Document.createElement('IMG'));D.className='TB_ConnectionLine';D.src=FCK_SPACER_PATH;B.OnHide=FCKToolbarPanelButton_OnPanelHide;};function FCKToolbarPanelButton_OnButtonClick(A){var B=this._FCKToolbarPanelButton;var e=B._UIButton.MainElement;B._UIButton.ChangeState(1);B.LineImg.style.width=(e.offsetWidth-2)+'px';FCK.ToolbarSet.CurrentInstance.Commands.GetCommand(B.CommandName).Execute(0,e.offsetHeight-1,e);};function FCKToolbarPanelButton_OnPanelHide(){var A=this._FCKToolbarPanelButton;A._UIButton.ChangeState(0);};FCKToolbarPanelButton.prototype.RefreshState=FCKToolbarButton.prototype.RefreshState;FCKToolbarPanelButton.prototype.Enable=FCKToolbarButton.prototype.Enable;FCKToolbarPanelButton.prototype.Disable=FCKToolbarButton.prototype.Disable;
+var FCKToolbarItems={};FCKToolbarItems.LoadedItems={};FCKToolbarItems.RegisterItem=function(A,B){this.LoadedItems[A]=B;};FCKToolbarItems.GetItem=function(A){var B=FCKToolbarItems.LoadedItems[A];if (B) return B;switch (A){case 'Source':B=new FCKToolbarButton('Source',FCKLang.Source,null,2,true,true,1);break;case 'DocProps':B=new FCKToolbarButton('DocProps',FCKLang.DocProps,null,null,null,null,2);break;case 'Save':B=new FCKToolbarButton('Save',FCKLang.Save,null,null,true,null,3);break;case 'NewPage':B=new FCKToolbarButton('NewPage',FCKLang.NewPage,null,null,true,null,4);break;case 'Preview':B=new FCKToolbarButton('Preview',FCKLang.Preview,null,null,true,null,5);break;case 'Templates':B=new FCKToolbarButton('Templates',FCKLang.Templates,null,null,null,null,6);break;case 'About':B=new FCKToolbarButton('About',FCKLang.About,null,null,true,null,47);break;case 'Cut':B=new FCKToolbarButton('Cut',FCKLang.Cut,null,null,false,true,7);break;case 'Copy':B=new FCKToolbarButton('Copy',FCKLang.Copy,null,null,false,true,8);break;case 'Paste':B=new FCKToolbarButton('Paste',FCKLang.Paste,null,null,false,true,9);break;case 'PasteText':B=new FCKToolbarButton('PasteText',FCKLang.PasteText,null,null,false,true,10);break;case 'PasteWord':B=new FCKToolbarButton('PasteWord',FCKLang.PasteWord,null,null,false,true,11);break;case 'Print':B=new FCKToolbarButton('Print',FCKLang.Print,null,null,false,true,12);break;case 'SpellCheck':B=new FCKToolbarButton('SpellCheck',FCKLang.SpellCheck,null,null,null,null,13);break;case 'Undo':B=new FCKToolbarButton('Undo',FCKLang.Undo,null,null,false,true,14);break;case 'Redo':B=new FCKToolbarButton('Redo',FCKLang.Redo,null,null,false,true,15);break;case 'SelectAll':B=new FCKToolbarButton('SelectAll',FCKLang.SelectAll,null,null,true,null,18);break;case 'RemoveFormat':B=new FCKToolbarButton('RemoveFormat',FCKLang.RemoveFormat,null,null,false,true,19);break;case 'FitWindow':B=new FCKToolbarButton('FitWindow',FCKLang.FitWindow,null,null,true,true,66);break;case 'Bold':B=new FCKToolbarButton('Bold',FCKLang.Bold,null,null,false,true,20);break;case 'Italic':B=new FCKToolbarButton('Italic',FCKLang.Italic,null,null,false,true,21);break;case 'Underline':B=new FCKToolbarButton('Underline',FCKLang.Underline,null,null,false,true,22);break;case 'StrikeThrough':B=new FCKToolbarButton('StrikeThrough',FCKLang.StrikeThrough,null,null,false,true,23);break;case 'Subscript':B=new FCKToolbarButton('Subscript',FCKLang.Subscript,null,null,false,true,24);break;case 'Superscript':B=new FCKToolbarButton('Superscript',FCKLang.Superscript,null,null,false,true,25);break;case 'OrderedList':B=new FCKToolbarButton('InsertOrderedList',FCKLang.NumberedListLbl,FCKLang.NumberedList,null,false,true,26);break;case 'UnorderedList':B=new FCKToolbarButton('InsertUnorderedList',FCKLang.BulletedListLbl,FCKLang.BulletedList,null,false,true,27);break;case 'Outdent':B=new FCKToolbarButton('Outdent',FCKLang.DecreaseIndent,null,null,false,true,28);break;case 'Indent':B=new FCKToolbarButton('Indent',FCKLang.IncreaseIndent,null,null,false,true,29);break;case 'Link':B=new FCKToolbarButton('Link',FCKLang.InsertLinkLbl,FCKLang.InsertLink,null,false,true,34);break;case 'Unlink':B=new FCKToolbarButton('Unlink',FCKLang.RemoveLink,null,null,false,true,35);break;case 'Anchor':B=new FCKToolbarButton('Anchor',FCKLang.Anchor,null,null,null,null,36);break;case 'Image':B=new FCKToolbarButton('Image',FCKLang.InsertImageLbl,FCKLang.InsertImage,null,false,true,37);break;case 'Flash':B=new FCKToolbarButton('Flash',FCKLang.InsertFlashLbl,FCKLang.InsertFlash,null,false,true,38);break;case 'Table':B=new FCKToolbarButton('Table',FCKLang.InsertTableLbl,FCKLang.InsertTable,null,false,true,39);break;case 'SpecialChar':B=new FCKToolbarButton('SpecialChar',FCKLang.InsertSpecialCharLbl,FCKLang.InsertSpecialChar,null,false,true,42);break;case 'Smiley':B=new FCKToolbarButton('Smiley',FCKLang.InsertSmileyLbl,FCKLang.InsertSmiley,null,false,true,41);break;case 'PageBreak':B=new FCKToolbarButton('PageBreak',FCKLang.PageBreakLbl,FCKLang.PageBreak,null,false,true,43);break;case 'Rule':B=new FCKToolbarButton('InsertHorizontalRule',FCKLang.InsertLineLbl,FCKLang.InsertLine,null,false,true,40);break;case 'JustifyLeft':B=new FCKToolbarButton('JustifyLeft',FCKLang.LeftJustify,null,null,false,true,30);break;case 'JustifyCenter':B=new FCKToolbarButton('JustifyCenter',FCKLang.CenterJustify,null,null,false,true,31);break;case 'JustifyRight':B=new FCKToolbarButton('JustifyRight',FCKLang.RightJustify,null,null,false,true,32);break;case 'JustifyFull':B=new FCKToolbarButton('JustifyFull',FCKLang.BlockJustify,null,null,false,true,33);break;case 'Style':B=new FCKToolbarStyleCombo();break;case 'FontName':B=new FCKToolbarFontsCombo();break;case 'FontSize':B=new FCKToolbarFontSizeCombo();break;case 'FontFormat':B=new FCKToolbarFontFormatCombo();break;case 'TextColor':B=new FCKToolbarPanelButton('TextColor',FCKLang.TextColor,null,null,45);break;case 'BGColor':B=new FCKToolbarPanelButton('BGColor',FCKLang.BGColor,null,null,46);break;case 'Find':B=new FCKToolbarButton('Find',FCKLang.Find,null,null,null,null,16);break;case 'Replace':B=new FCKToolbarButton('Replace',FCKLang.Replace,null,null,null,null,17);break;case 'Form':B=new FCKToolbarButton('Form',FCKLang.Form,null,null,null,null,48);break;case 'Checkbox':B=new FCKToolbarButton('Checkbox',FCKLang.Checkbox,null,null,null,null,49);break;case 'Radio':B=new FCKToolbarButton('Radio',FCKLang.RadioButton,null,null,null,null,50);break;case 'TextField':B=new FCKToolbarButton('TextField',FCKLang.TextField,null,null,null,null,51);break;case 'Textarea':B=new FCKToolbarButton('Textarea',FCKLang.Textarea,null,null,null,null,52);break;case 'HiddenField':B=new FCKToolbarButton('HiddenField',FCKLang.HiddenField,null,null,null,null,56);break;case 'Button':B=new FCKToolbarButton('Button',FCKLang.Button,null,null,null,null,54);break;case 'Select':B=new FCKToolbarButton('Select',FCKLang.SelectionField,null,null,null,null,53);break;case 'ImageButton':B=new FCKToolbarButton('ImageButton',FCKLang.ImageButton,null,null,null,null,55);break;default:alert(FCKLang.UnknownToolbarItem.replace(/%1/g,A));return null;};FCKToolbarItems.LoadedItems[A]=B;return B;}
+var FCKToolbar=function(){this.Items=[];if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbar_Cleanup);};FCKToolbar.prototype.AddItem=function(A){return this.Items[this.Items.length]=A;};FCKToolbar.prototype.AddButton=function(A,B,C,D,E,F){if (typeof(D)=='number') D=[this.DefaultIconsStrip,this.DefaultIconSize,D];var G=new FCKToolbarButtonUI(A,B,C,D,E,F);G._FCKToolbar=this;G.OnClick=FCKToolbar_OnItemClick;return this.AddItem(G);};function FCKToolbar_OnItemClick(A){var B=A._FCKToolbar;if (B.OnItemClick) B.OnItemClick(B,A);};FCKToolbar.prototype.AddSeparator=function(){this.AddItem(new FCKToolbarSeparator());};FCKToolbar.prototype.Create=function(A){if (this.MainElement){if (this.MainElement.parentNode) this.MainElement.parentNode.removeChild(this.MainElement);this.MainElement=null;};var B=FCKTools.GetElementDocument(A);var e=this.MainElement=B.createElement('table');e.className='TB_Toolbar';e.style.styleFloat=e.style.cssFloat=(FCKLang.Dir=='ltr'?'left':'right');e.dir=FCKLang.Dir;e.cellPadding=0;e.cellSpacing=0;this.RowElement=e.insertRow(-1);var C;if (!this.HideStart){C=this.RowElement.insertCell(-1);C.appendChild(B.createElement('div')).className='TB_Start';};for (var i=0;i<this.Items.length;i++){this.Items[i].Create(this.RowElement.insertCell(-1));};if (!this.HideEnd){C=this.RowElement.insertCell(-1);C.appendChild(B.createElement('div')).className='TB_End';};A.appendChild(e);};function FCKToolbar_Cleanup(){this.MainElement=null;this.RowElement=null;};var FCKToolbarSeparator=function(){};FCKToolbarSeparator.prototype.Create=function(A){FCKTools.AppendElement(A,'div').className='TB_Separator';}
+var FCKToolbarBreak=function(){};FCKToolbarBreak.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A).createElement('div');B.className='TB_Break';B.style.clear=FCKLang.Dir=='rtl'?'left':'right';A.appendChild(B);}
+function FCKToolbarSet_Create(A){var B;var C=A||FCKConfig.ToolbarLocation;switch (C){case 'In':document.getElementById('xToolbarRow').style.display='';B=new FCKToolbarSet(document);break;default:FCK.Events.AttachEvent('OnBlur',FCK_OnBlur);FCK.Events.AttachEvent('OnFocus',FCK_OnFocus);var D;var E=C.match(/^Out:(.+)\((\w+)\)$/);if (E){D=eval('parent.'+E[1]).document.getElementById(E[2]);}else{E=C.match(/^Out:(\w+)$/);if (E) D=parent.document.getElementById(E[1]);};if (!D){alert('Invalid value for "ToolbarLocation"');return this._Init('In');};B=D.__FCKToolbarSet;if (B) break;var F=FCKTools.GetElementDocument(D).createElement('iframe');F.src='javascript:void(0)';F.frameBorder=0;F.width='100%';F.height='10';D.appendChild(F);F.unselectable='on';var G=F.contentWindow.document;G.open();G.write('<html><head><script type="text/javascript"> window.onload = window.onresize = function() { window.frameElement.height = document.body.scrollHeight ; } </script></head><body style="overflow: hidden">'+document.getElementById('xToolbarSpace').innerHTML+'</body></html>');G.close();G.oncontextmenu=FCKTools.CancelEvent;FCKTools.AppendStyleSheet(G,FCKConfig.SkinPath+'fck_editor.css');B=D.__FCKToolbarSet=new FCKToolbarSet(G);B._IFrame=F;if (FCK.IECleanup) FCK.IECleanup.AddItem(D,FCKToolbarSet_Target_Cleanup);};B.CurrentInstance=FCK;FCK.AttachToOnSelectionChange(B.RefreshItemsState);return B;};function FCK_OnBlur(A){var B=A.ToolbarSet;if (B.CurrentInstance==A) B.Disable();};function FCK_OnFocus(A){var B=A.ToolbarSet;var C=A||FCK;B.CurrentInstance.FocusManager.RemoveWindow(B._IFrame.contentWindow);B.CurrentInstance=C;C.FocusManager.AddWindow(B._IFrame.contentWindow,true);B.Enable();};function FCKToolbarSet_Cleanup(){this._TargetElement=null;this._IFrame=null;};function FCKToolbarSet_Target_Cleanup(){this.__FCKToolbarSet=null;};var FCKToolbarSet=function(A){this._Document=A;this._TargetElement=A.getElementById('xToolbar');var B=A.getElementById('xExpandHandle');var C=A.getElementById('xCollapseHandle');B.title=FCKLang.ToolbarExpand;B.onclick=FCKToolbarSet_Expand_OnClick;C.title=FCKLang.ToolbarCollapse;C.onclick=FCKToolbarSet_Collapse_OnClick;if (!FCKConfig.ToolbarCanCollapse||FCKConfig.ToolbarStartExpanded) this.Expand();else this.Collapse();C.style.display=FCKConfig.ToolbarCanCollapse?'':'none';if (FCKConfig.ToolbarCanCollapse) C.style.display='';else A.getElementById('xTBLeftBorder').style.display='';this.Toolbars=[];this.IsLoaded=false;if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKToolbarSet_Cleanup);};function FCKToolbarSet_Expand_OnClick(){FCK.ToolbarSet.Expand();};function FCKToolbarSet_Collapse_OnClick(){FCK.ToolbarSet.Collapse();};FCKToolbarSet.prototype.Expand=function(){this._ChangeVisibility(false);};FCKToolbarSet.prototype.Collapse=function(){this._ChangeVisibility(true);};FCKToolbarSet.prototype._ChangeVisibility=function(A){this._Document.getElementById('xCollapsed').style.display=A?'':'none';this._Document.getElementById('xExpanded').style.display=A?'none':'';if (FCKBrowserInfo.IsGecko){FCKTools.RunFunction(window.onresize);}};FCKToolbarSet.prototype.Load=function(A){this.Name=A;this.Items=[];this.ItemsWysiwygOnly=[];this.ItemsContextSensitive=[];this._TargetElement.innerHTML='';var B=FCKConfig.ToolbarSets[A];if (!B){alert(FCKLang.UnknownToolbarSet.replace(/%1/g,A));return;};this.Toolbars=[];for (var x=0;x<B.length;x++){var C=B[x];if (!C) continue;var D;if (typeof(C)=='string'){if (C=='/') D=new FCKToolbarBreak();}else{D=new FCKToolbar();for (var j=0;j<C.length;j++){var E=C[j];if (E=='-') D.AddSeparator();else{var F=FCKToolbarItems.GetItem(E);if (F){D.AddItem(F);this.Items.push(F);if (!F.SourceView) this.ItemsWysiwygOnly.push(F);if (F.ContextSensitive) this.ItemsContextSensitive.push(F);}}}};D.Create(this._TargetElement);this.Toolbars[this.Toolbars.length]=D;};FCKTools.DisableSelection(this._Document.getElementById('xCollapseHandle').parentNode);if (FCK.Status!=2) FCK.Events.AttachEvent('OnStatusChange',this.RefreshModeState);else this.RefreshModeState();this.IsLoaded=true;this.IsEnabled=true;FCKTools.RunFunction(this.OnLoad);};FCKToolbarSet.prototype.Enable=function(){if (this.IsEnabled) return;this.IsEnabled=true;var A=this.Items;for (var i=0;i<A.length;i++) A[i].RefreshState();};FCKToolbarSet.prototype.Disable=function(){if (!this.IsEnabled) return;this.IsEnabled=false;var A=this.Items;for (var i=0;i<A.length;i++) A[i].Disable();};FCKToolbarSet.prototype.RefreshModeState=function(A){if (FCK.Status!=2) return;var B=A?A.ToolbarSet:this;var C=B.ItemsWysiwygOnly;if (FCK.EditMode==0){for (var i=0;i<C.length;i++) C[i].Enable();B.RefreshItemsState(A);}else{B.RefreshItemsState(A);for (var j=0;j<C.length;j++) C[j].Disable();}};FCKToolbarSet.prototype.RefreshItemsState=function(A){var B=(A?A.ToolbarSet:this).ItemsContextSensitive;for (var i=0;i<B.length;i++) B[i].RefreshState();};
+var FCKDialog={};FCKDialog.OpenDialog=function(A,B,C,D,E,F,G,H){var I={};I.Title=B;I.Page=C;I.Editor=window;I.CustomValue=F;var J=FCKConfig.BasePath+'fckdialog.html';this.Show(I,A,J,D,E,G,H);};
+FCKDialog.Show=function(A,B,C,D,E,F,G){if (!F) F=window;var H='help:no;scroll:no;status:no;resizable:'+(G?'yes':'no')+';dialogWidth:'+D+'px;dialogHeight:'+E+'px';FCKFocusManager.Lock();var I='B';try{I=F.showModalDialog(C,A,H);}catch(e) {};if ('B'===I) alert(FCKLang.DialogBlocked);FCKFocusManager.Unlock();};
+var FCKMenuItem=function(A,B,C,D,E){this.Name=B;this.Label=C||B;this.IsDisabled=E;this.Icon=new FCKIcon(D);this.SubMenu=new FCKMenuBlockPanel();this.SubMenu.Parent=A;this.SubMenu.OnClick=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnClick,this);if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuItem_Cleanup);};FCKMenuItem.prototype.AddItem=function(A,B,C,D){this.HasSubMenu=true;return this.SubMenu.AddItem(A,B,C,D);};FCKMenuItem.prototype.AddSeparator=function(){this.SubMenu.AddSeparator();};FCKMenuItem.prototype.Create=function(A){var B=this.HasSubMenu;var C=FCKTools.GetElementDocument(A);var r=this.MainElement=A.insertRow(-1);r.className=this.IsDisabled?'MN_Item_Disabled':'MN_Item';if (!this.IsDisabled){FCKTools.AddEventListenerEx(r,'mouseover',FCKMenuItem_OnMouseOver,[this]);FCKTools.AddEventListenerEx(r,'click',FCKMenuItem_OnClick,[this]);if (!B) FCKTools.AddEventListenerEx(r,'mouseout',FCKMenuItem_OnMouseOut,[this]);};var D=r.insertCell(-1);D.className='MN_Icon';D.appendChild(this.Icon.CreateIconElement(C));D=r.insertCell(-1);D.className='MN_Label';D.noWrap=true;D.appendChild(C.createTextNode(this.Label));D=r.insertCell(-1);if (B){D.className='MN_Arrow';var E=D.appendChild(C.createElement('IMG'));E.src=FCK_IMAGES_PATH+'arrow_'+FCKLang.Dir+'.gif';E.width=4;E.height=7;this.SubMenu.Create();this.SubMenu.Panel.OnHide=FCKTools.CreateEventListener(FCKMenuItem_SubMenu_OnHide,this);}};FCKMenuItem.prototype.Activate=function(){this.MainElement.className='MN_Item_Over';if (this.HasSubMenu){this.SubMenu.Show(this.MainElement.offsetWidth+2,-2,this.MainElement);};FCKTools.RunFunction(this.OnActivate,this);};FCKMenuItem.prototype.Deactivate=function(){this.MainElement.className='MN_Item';if (this.HasSubMenu) this.SubMenu.Hide();};function FCKMenuItem_SubMenu_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuItem_SubMenu_OnHide(A){A.Deactivate();};function FCKMenuItem_OnClick(A,B){if (B.HasSubMenu) B.Activate();else{B.Deactivate();FCKTools.RunFunction(B.OnClick,B,[B]);}};function FCKMenuItem_OnMouseOver(A,B){B.Activate();};function FCKMenuItem_OnMouseOut(A,B){B.Deactivate();};function FCKMenuItem_Cleanup(){this.MainElement=null;}
+var FCKMenuBlock=function(){this._Items=[];};FCKMenuBlock.prototype.Count=function(){return this._Items.length;};FCKMenuBlock.prototype.AddItem=function(A,B,C,D){var E=new FCKMenuItem(this,A,B,C,D);E.OnClick=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnClick,this);E.OnActivate=FCKTools.CreateEventListener(FCKMenuBlock_Item_OnActivate,this);this._Items.push(E);return E;};FCKMenuBlock.prototype.AddSeparator=function(){this._Items.push(new FCKMenuSeparator());};FCKMenuBlock.prototype.RemoveAllItems=function(){this._Items=[];var A=this._ItemsTable;if (A){while (A.rows.length>0) A.deleteRow(0);}};FCKMenuBlock.prototype.Create=function(A){if (!this._ItemsTable){if (FCK.IECleanup) FCK.IECleanup.AddItem(this,FCKMenuBlock_Cleanup);this._Window=FCKTools.GetElementWindow(A);var B=FCKTools.GetElementDocument(A);var C=A.appendChild(B.createElement('table'));C.cellPadding=0;C.cellSpacing=0;FCKTools.DisableSelection(C);var D=C.insertRow(-1).insertCell(-1);D.className='MN_Menu';var E=this._ItemsTable=D.appendChild(B.createElement('table'));E.cellPadding=0;E.cellSpacing=0;};for (var i=0;i<this._Items.length;i++) this._Items[i].Create(this._ItemsTable);};function FCKMenuBlock_Item_OnClick(A,B){FCKTools.RunFunction(B.OnClick,B,[A]);};function FCKMenuBlock_Item_OnActivate(A){var B=A._ActiveItem;if (B&&B!=this){if (!FCKBrowserInfo.IsIE&&B.HasSubMenu&&!this.HasSubMenu) A._Window.focus();B.Deactivate();};A._ActiveItem=this;};function FCKMenuBlock_Cleanup(){this._Window=null;this._ItemsTable=null;};var FCKMenuSeparator=function(){};FCKMenuSeparator.prototype.Create=function(A){var B=FCKTools.GetElementDocument(A);var r=A.insertRow(-1);var C=r.insertCell(-1);C.className='MN_Separator MN_Icon';C=r.insertCell(-1);C.className='MN_Separator';C.appendChild(B.createElement('DIV')).className='MN_Separator_Line';C=r.insertCell(-1);C.className='MN_Separator';C.appendChild(B.createElement('DIV')).className='MN_Separator_Line';}
+var FCKMenuBlockPanel=function(){FCKMenuBlock.call(this);};FCKMenuBlockPanel.prototype=new FCKMenuBlock();FCKMenuBlockPanel.prototype.Create=function(){var A=this.Panel=(this.Parent&&this.Parent.Panel?this.Parent.Panel.CreateChildPanel():new FCKPanel());A.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');FCKMenuBlock.prototype.Create.call(this,A.MainNode);};FCKMenuBlockPanel.prototype.Show=function(x,y,A){if (!this.Panel.CheckIsOpened()) this.Panel.Show(x,y,A);};FCKMenuBlockPanel.prototype.Hide=function(){if (this.Panel.CheckIsOpened()) this.Panel.Hide();}
+var FCKContextMenu=function(A,B){this.CtrlDisable=false;var C=this._Panel=new FCKPanel(A);C.AppendStyleSheet(FCKConfig.SkinPath+'fck_editor.css');C.IsContextMenu=true;if (FCKBrowserInfo.IsGecko) C.Document.addEventListener('draggesture',function(e) {e.preventDefault();return false;},true);var D=this._MenuBlock=new FCKMenuBlock();D.Panel=C;D.OnClick=FCKTools.CreateEventListener(FCKContextMenu_MenuBlock_OnClick,this);this._Redraw=true;};FCKContextMenu.prototype.SetMouseClickWindow=function(A){if (!FCKBrowserInfo.IsIE){this._Document=A.document;this._Document.addEventListener('contextmenu',FCKContextMenu_Document_OnContextMenu,false);}};FCKContextMenu.prototype.AddItem=function(A,B,C,D){var E=this._MenuBlock.AddItem(A,B,C,D);this._Redraw=true;return E;};FCKContextMenu.prototype.AddSeparator=function(){this._MenuBlock.AddSeparator();this._Redraw=true;};FCKContextMenu.prototype.RemoveAllItems=function(){this._MenuBlock.RemoveAllItems();this._Redraw=true;};FCKContextMenu.prototype.AttachToElement=function(A){if (FCKBrowserInfo.IsIE) FCKTools.AddEventListenerEx(A,'contextmenu',FCKContextMenu_AttachedElement_OnContextMenu,this);else A._FCKContextMenu=this;};function FCKContextMenu_Document_OnContextMenu(e){var A=e.target;while (A){if (A._FCKContextMenu){if (A._FCKContextMenu.CtrlDisable&&(e.ctrlKey||e.metaKey)) return true;FCKTools.CancelEvent(e);FCKContextMenu_AttachedElement_OnContextMenu(e,A._FCKContextMenu,A);};A=A.parentNode;}};function FCKContextMenu_AttachedElement_OnContextMenu(A,B,C){if (B.CtrlDisable&&(A.ctrlKey||A.metaKey)) return true;var D=C||this;if (B.OnBeforeOpen) B.OnBeforeOpen.call(B,D);if (B._MenuBlock.Count()==0) return false;if (B._Redraw){B._MenuBlock.Create(B._Panel.MainNode);B._Redraw=false;};FCKTools.DisableSelection(B._Panel.Document.body);B._Panel.Show(A.pageX||A.screenX,A.pageY||A.screenY,A.currentTarget||null);return false;};function FCKContextMenu_MenuBlock_OnClick(A,B){B._Panel.Hide();FCKTools.RunFunction(B.OnItemClick,B,A);}
+FCK.ContextMenu={};FCK.ContextMenu.Listeners=[];FCK.ContextMenu.RegisterListener=function(A){if (A) this.Listeners.push(A);};function FCK_ContextMenu_Init(){var A=FCK.ContextMenu._InnerContextMenu=new FCKContextMenu(FCKBrowserInfo.IsIE?window:window.parent,FCKLang.Dir);A.CtrlDisable=FCKConfig.BrowserContextMenuOnCtrl;A.OnBeforeOpen=FCK_ContextMenu_OnBeforeOpen;A.OnItemClick=FCK_ContextMenu_OnItemClick;var B=FCK.ContextMenu;for (var i=0;i<FCKConfig.ContextMenu.length;i++) B.RegisterListener(FCK_ContextMenu_GetListener(FCKConfig.ContextMenu[i]));};function FCK_ContextMenu_GetListener(A){switch (A){case 'Generic':return {AddItems:function(menu,tag,tagName){menu.AddItem('Cut',FCKLang.Cut,7,FCKCommands.GetCommand('Cut').GetState()==-1);menu.AddItem('Copy',FCKLang.Copy,8,FCKCommands.GetCommand('Copy').GetState()==-1);menu.AddItem('Paste',FCKLang.Paste,9,FCKCommands.GetCommand('Paste').GetState()==-1);}};case 'Table':return {AddItems:function(menu,tag,tagName){var B=(tagName=='TABLE');var C=(!B&&FCKSelection.HasAncestorNode('TABLE'));if (C){menu.AddSeparator();var D=menu.AddItem('Cell',FCKLang.CellCM);D.AddItem('TableInsertCell',FCKLang.InsertCell,58);D.AddItem('TableDeleteCells',FCKLang.DeleteCells,59);D.AddItem('TableMergeCells',FCKLang.MergeCells,60);D.AddItem('TableSplitCell',FCKLang.SplitCell,61);D.AddSeparator();D.AddItem('TableCellProp',FCKLang.CellProperties,57);menu.AddSeparator();D=menu.AddItem('Row',FCKLang.RowCM);D.AddItem('TableInsertRow',FCKLang.InsertRow,62);D.AddItem('TableDeleteRows',FCKLang.DeleteRows,63);menu.AddSeparator();D=menu.AddItem('Column',FCKLang.ColumnCM);D.AddItem('TableInsertColumn',FCKLang.InsertColumn,64);D.AddItem('TableDeleteColumns',FCKLang.DeleteColumns,65);};if (B||C){menu.AddSeparator();menu.AddItem('TableDelete',FCKLang.TableDelete);menu.AddItem('TableProp',FCKLang.TableProperties,39);}}};case 'Link':return {AddItems:function(menu,tag,tagName){var E=(tagName=='A'||FCKSelection.HasAncestorNode('A'));if (E||FCK.GetNamedCommandState('Unlink')!=-1){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0&&F.href.length==0);if (G) return;menu.AddSeparator();if (E) menu.AddItem('Link',FCKLang.EditLink,34);menu.AddItem('Unlink',FCKLang.RemoveLink,35);}}};case 'Image':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&!tag.getAttribute('_fckfakelement')){menu.AddSeparator();menu.AddItem('Image',FCKLang.ImageProperties,37);}}};case 'Anchor':return {AddItems:function(menu,tag,tagName){var F=FCKSelection.MoveToAncestorNode('A');var G=(F&&F.name.length>0);if (G||(tagName=='IMG'&&tag.getAttribute('_fckanchor'))){menu.AddSeparator();menu.AddItem('Anchor',FCKLang.AnchorProp,36);}}};case 'Flash':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckflash')){menu.AddSeparator();menu.AddItem('Flash',FCKLang.FlashProperties,38);}}};case 'Form':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('FORM')){menu.AddSeparator();menu.AddItem('Form',FCKLang.FormProp,48);}}};case 'Checkbox':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='checkbox'){menu.AddSeparator();menu.AddItem('Checkbox',FCKLang.CheckboxProp,49);}}};case 'Radio':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='radio'){menu.AddSeparator();menu.AddItem('Radio',FCKLang.RadioButtonProp,50);}}};case 'TextField':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='text'||tag.type=='password')){menu.AddSeparator();menu.AddItem('TextField',FCKLang.TextFieldProp,51);}}};case 'HiddenField':return {AddItems:function(menu,tag,tagName){if (tagName=='IMG'&&tag.getAttribute('_fckinputhidden')){menu.AddSeparator();menu.AddItem('HiddenField',FCKLang.HiddenFieldProp,56);}}};case 'ImageButton':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&tag.type=='image'){menu.AddSeparator();menu.AddItem('ImageButton',FCKLang.ImageButtonProp,55);}}};case 'Button':return {AddItems:function(menu,tag,tagName){if (tagName=='INPUT'&&(tag.type=='button'||tag.type=='submit'||tag.type=='reset')){menu.AddSeparator();menu.AddItem('Button',FCKLang.ButtonProp,54);}}};case 'Select':return {AddItems:function(menu,tag,tagName){if (tagName=='SELECT'){menu.AddSeparator();menu.AddItem('Select',FCKLang.SelectionFieldProp,53);}}};case 'Textarea':return {AddItems:function(menu,tag,tagName){if (tagName=='TEXTAREA'){menu.AddSeparator();menu.AddItem('Textarea',FCKLang.TextareaProp,52);}}};case 'BulletedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('UL')){menu.AddSeparator();menu.AddItem('BulletedList',FCKLang.BulletedListProp,27);}}};case 'NumberedList':return {AddItems:function(menu,tag,tagName){if (FCKSelection.HasAncestorNode('OL')){menu.AddSeparator();menu.AddItem('NumberedList',FCKLang.NumberedListProp,26);}}};};return null;};function FCK_ContextMenu_OnBeforeOpen(){FCK.Events.FireEvent('OnSelectionChange');var A,sTagName;if ((A=FCKSelection.GetSelectedElement())) sTagName=A.tagName;var B=FCK.ContextMenu._InnerContextMenu;B.RemoveAllItems();var C=FCK.ContextMenu.Listeners;for (var i=0;i<C.length;i++) C[i].AddItems(B,A,sTagName);};function FCK_ContextMenu_OnItemClick(A){FCK.Focus();FCKCommands.GetCommand(A.Name).Execute();};
+var FCKPlugin=function(A,B,C){this.Name=A;this.BasePath=C?C:FCKConfig.PluginsPath;this.Path=this.BasePath+A+'/';if (!B||B.length==0) this.AvailableLangs=[];else this.AvailableLangs=B.split(',');};FCKPlugin.prototype.Load=function(){if (this.AvailableLangs.length>0){var A;if (this.AvailableLangs.IndexOf(FCKLanguageManager.ActiveLanguage.Code)>=0) A=FCKLanguageManager.ActiveLanguage.Code;else A=this.AvailableLangs[0];LoadScript(this.Path+'lang/'+A+'.js');};LoadScript(this.Path+'fckplugin.js');}
+var FCKPlugins=FCK.Plugins={};FCKPlugins.ItemsCount=0;FCKPlugins.Items={};FCKPlugins.Load=function(){var A=FCKPlugins.Items;for (var i=0;i<FCKConfig.Plugins.Items.length;i++){var B=FCKConfig.Plugins.Items[i];var C=A[B[0]]=new FCKPlugin(B[0],B[1],B[2]);FCKPlugins.ItemsCount++;};for (var s in A) A[s].Load();FCKPlugins.Load=null;}
diff --git a/httemplate/elements/fckeditor/editor/lang/_getfontformat.html b/httemplate/elements/fckeditor/editor/lang/_getfontformat.html
new file mode 100644
index 000000000..a408642cd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/_getfontformat.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+-->
+<html>
+ <head>
+ <title></title>
+ </head>
+ <script language="javascript">
+
+window.onload = function()
+{
+ var oRange = document.selection.createRange() ;
+
+ var sNormal ;
+ var sFormats = '' ;
+ for ( var i = 1 ; i <= 9 ; i++ )
+ {
+ oRange.moveToElementText( document.getElementById( 'x' + i ) ) ;
+ sFormats += oRange.queryCommandValue( 'FormatBlock' ) ;
+ if ( i == 1 )
+ sNormal = sFormats ;
+ sFormats += ';' ;
+ }
+
+ document.getElementById('xFontFormats').innerHTML = sFormats + sNormal + ' (DIV)' ;
+}
+ </script>
+ <body>
+ <table width="70%" align="center">
+ <tr>
+ <td>
+ <h3>FontFormats Localization</h3>
+ <p>
+ IE has some limits when handling the "Font Format". It actually uses localized
+ strings to retrieve the current format value. This makes it very difficult to
+ make a system that works on every single computer in the world.
+ </p>
+ <p>
+ With FCKeditor, this problem impacts in the "Format" toolbar command that
+ doesn't reflects the format of the current cursor position.
+ </p>
+ <p>
+ There is only one way to make it work. We must localize FCKeditor using the
+ strings used by IE. In this way, we will have the expected behavior at least
+ when using FCKeditor in the same language as the browser. So, when localizing
+ FCKeditor, go to a computer with IE in the target language, open this page and
+ use the following string to the "FontFormats" value:
+ </p>
+ <div style="white-space: nowrap">
+ FontFormats : "<span id="xFontFormats" style="COLOR: #000099"></span>",
+ </div>
+ </td>
+ </tr>
+ </table>
+ <div style="DISPLAY: none">
+ <p id="x1">&nbsp;</p>
+ <pre id="x2">&nbsp;</pre>
+ <address id="x3">&nbsp;</address>
+ <h1 id="x4">&nbsp;</h1>
+ <h2 id="x5">&nbsp;</h2>
+ <h3 id="x6">&nbsp;</h3>
+ <h4 id="x7">&nbsp;</h4>
+ <h5 id="x8">&nbsp;</h5>
+ <h6 id="x9">&nbsp;</h6>
+ </div>
+ </body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/lang/_translationstatus.txt b/httemplate/elements/fckeditor/editor/lang/_translationstatus.txt
new file mode 100644
index 000000000..a53ea8fd4
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/_translationstatus.txt
@@ -0,0 +1,76 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Translations Status.
+ */
+
+af.js Found: 401 Missing: 1
+ar.js Found: 401 Missing: 1
+bg.js Found: 378 Missing: 24
+bn.js Found: 386 Missing: 16
+bs.js Found: 230 Missing: 172
+ca.js Found: 402 Missing: 0
+cs.js Found: 400 Missing: 2
+da.js Found: 386 Missing: 16
+de.js Found: 401 Missing: 1
+el.js Found: 401 Missing: 1
+en-au.js Found: 402 Missing: 0
+en-ca.js Found: 402 Missing: 0
+en-uk.js Found: 402 Missing: 0
+eo.js Found: 350 Missing: 52
+es.js Found: 386 Missing: 16
+et.js Found: 402 Missing: 0
+eu.js Found: 386 Missing: 16
+fa.js Found: 402 Missing: 0
+fi.js Found: 402 Missing: 0
+fo.js Found: 401 Missing: 1
+fr.js Found: 401 Missing: 1
+gl.js Found: 386 Missing: 16
+he.js Found: 402 Missing: 0
+hi.js Found: 401 Missing: 1
+hr.js Found: 401 Missing: 1
+hu.js Found: 401 Missing: 1
+it.js Found: 401 Missing: 1
+ja.js Found: 401 Missing: 1
+km.js Found: 376 Missing: 26
+ko.js Found: 373 Missing: 29
+lt.js Found: 381 Missing: 21
+lv.js Found: 386 Missing: 16
+mn.js Found: 230 Missing: 172
+ms.js Found: 356 Missing: 46
+nb.js Found: 400 Missing: 2
+nl.js Found: 401 Missing: 1
+no.js Found: 400 Missing: 2
+pl.js Found: 386 Missing: 16
+pt-br.js Found: 401 Missing: 1
+pt.js Found: 386 Missing: 16
+ro.js Found: 400 Missing: 2
+ru.js Found: 401 Missing: 1
+sk.js Found: 401 Missing: 1
+sl.js Found: 378 Missing: 24
+sr-latn.js Found: 373 Missing: 29
+sr.js Found: 373 Missing: 29
+sv.js Found: 401 Missing: 1
+th.js Found: 398 Missing: 4
+tr.js Found: 401 Missing: 1
+uk.js Found: 402 Missing: 0
+vi.js Found: 401 Missing: 1
+zh-cn.js Found: 401 Missing: 1
+zh.js Found: 401 Missing: 1
diff --git a/httemplate/elements/fckeditor/editor/lang/af.js b/httemplate/elements/fckeditor/editor/lang/af.js
new file mode 100644
index 000000000..857dc3e9d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/af.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Afrikaans language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Vou Gereedskaps balk toe",
+ToolbarExpand : "Vou Gereedskaps balk oop",
+
+// Toolbar Items and Context Menu
+Save : "Bewaar",
+NewPage : "Nuwe Bladsy",
+Preview : "Voorskou",
+Cut : "Uitsny ",
+Copy : "Kopieer",
+Paste : "Byvoeg",
+PasteText : "Slegs inhoud byvoeg",
+PasteWord : "Van Word af byvoeg",
+Print : "Druk",
+SelectAll : "Selekteer alles",
+RemoveFormat : "Formaat verweider",
+InsertLinkLbl : "Skakel",
+InsertLink : "Skakel byvoeg/verander",
+RemoveLink : "Skakel verweider",
+Anchor : "Plekhouer byvoeg/verander",
+InsertImageLbl : "Beeld",
+InsertImage : "Beeld byvoeg/verander",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash byvoeg/verander",
+InsertTableLbl : "Tabel",
+InsertTable : "Tabel byvoeg/verander",
+InsertLineLbl : "Lyn",
+InsertLine : "Horisontale lyn byvoeg",
+InsertSpecialCharLbl: "Spesiaale karakter",
+InsertSpecialChar : "Spesiaale Karakter byvoeg",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Smiley byvoeg",
+About : "Meer oor FCKeditor",
+Bold : "Vet",
+Italic : "Skuins",
+Underline : "Onderstreep",
+StrikeThrough : "Gestreik",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Links rig",
+CenterJustify : "Rig Middel",
+RightJustify : "Regs rig",
+BlockJustify : "Blok paradeer",
+DecreaseIndent : "Paradeering verkort",
+IncreaseIndent : "Paradeering verleng",
+Undo : "Ont-skep",
+Redo : "Her-skep",
+NumberedListLbl : "Genommerde lys",
+NumberedList : "Genommerde lys byvoeg/verweider",
+BulletedListLbl : "Gepunkte lys",
+BulletedList : "Gepunkte lys byvoeg/verweider",
+ShowTableBorders : "Wys tabel kante",
+ShowDetails : "Wys informasie",
+Style : "Styl",
+FontFormat : "Karakter formaat",
+Font : "Karakters",
+FontSize : "Karakter grote",
+TextColor : "Karakter kleur",
+BGColor : "Agtergrond kleur",
+Source : "Source",
+Find : "Vind",
+Replace : "Vervang",
+SpellCheck : "Spelling nagaan",
+UniversalKeyboard : "Universeele Sleutelbord",
+PageBreakLbl : "Bladsy breek",
+PageBreak : "Bladsy breek byvoeg",
+
+Form : "Form",
+Checkbox : "HakBox",
+RadioButton : "PuntBox",
+TextField : "Byvoegbare karakter strook",
+Textarea : "Byvoegbare karakter area",
+HiddenField : "Blinde strook",
+Button : "Knop",
+SelectionField : "Opklapbare keuse strook",
+ImageButton : "Beeld knop",
+
+FitWindow : "Maksimaliseer venster grote",
+
+// Context Menu
+EditLink : "Verander skakel",
+CellCM : "Cell",
+RowCM : "Ry",
+ColumnCM : "Kolom",
+InsertRow : "Ry byvoeg",
+DeleteRows : "Ry verweider",
+InsertColumn : "Kolom byvoeg",
+DeleteColumns : "Kolom verweider",
+InsertCell : "Cell byvoeg",
+DeleteCells : "Cell verweider",
+MergeCells : "Cell verenig",
+SplitCell : "Cell verdeel",
+TableDelete : "Tabel verweider",
+CellProperties : "Cell eienskappe",
+TableProperties : "Tabel eienskappe",
+ImageProperties : "Beeld eienskappe",
+FlashProperties : "Flash eienskappe",
+
+AnchorProp : "Plekhouer eienskappe",
+ButtonProp : "Knop eienskappe",
+CheckboxProp : "HakBox eienskappe",
+HiddenFieldProp : "Blinde strook eienskappe",
+RadioButtonProp : "PuntBox eienskappe",
+ImageButtonProp : "Beeld knop eienskappe",
+TextFieldProp : "Karakter strook eienskappe",
+SelectionFieldProp : "Opklapbare keuse strook eienskappe",
+TextareaProp : "Karakter area eienskappe",
+FormProp : "Form eienskappe",
+
+FontFormats : "Normaal;Geformateerd;Adres;Opskrif 1;Opskrif 2;Opskrif 3;Opskrif 4;Opskrif 5;Opskrif 6;Normaal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML word verarbeit. U geduld asseblief...",
+Done : "Kompleet",
+PasteWordConfirm : "Die informasie wat U probeer byvoeg is warskynlik van Word. Wil U dit reinig voor die byvoeging?",
+NotCompatiblePaste : "Die instruksie is beskikbaar vir Internet Explorer weergawe 5.5 of hor. Wil U dir byvoeg sonder reiniging?",
+UnknownToolbarItem : "Unbekende gereedskaps balk item \"%1\"",
+UnknownCommand : "Unbekende instruksie naam \"%1\"",
+NotImplemented : "Instruksie is nie geimplementeer nie.",
+UnknownToolbarSet : "Gereedskaps balk \"%1\" bestaan nie",
+NoActiveX : "U browser sekuriteit instellings kan die funksies van die editor behinder. U moet die opsie \"Run ActiveX controls and plug-ins\" aktiveer. U ondervinding mag problematies geskiet of sekere funksionaliteit mag verhinder word.",
+BrowseServerBlocked : "Die vorraad venster word geblok! Verseker asseblief dat U die \"popup blocker\" instelling verander.",
+DialogBlocked : "Die dialoog venster vir verdere informasie word geblok. De-aktiveer asseblief die \"popup blocker\" instellings wat dit behinder.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Kanseleer",
+DlgBtnClose : "Sluit",
+DlgBtnBrowseServer : "Server deurblaai",
+DlgAdvancedTag : "Ingewikkeld",
+DlgOpOther : "<Ander>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Voeg asseblief die URL in",
+
+// General Dialogs Labels
+DlgGenNotSet : "<geen instelling>",
+DlgGenId : "Id",
+DlgGenLangDir : "Taal rigting",
+DlgGenLangDirLtr : "Links na regs (LTR)",
+DlgGenLangDirRtl : "Regs na links (RTL)",
+DlgGenLangCode : "Taal kode",
+DlgGenAccessKey : "Toegang sleutel",
+DlgGenName : "Naam",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Lang beskreiwing URL",
+DlgGenClass : "Skakel Tiepe",
+DlgGenTitle : "Voorbeveelings Titel",
+DlgGenContType : "Voorbeveelings inhoud soort",
+DlgGenLinkCharset : "Geskakelde voorbeeld karakterstel",
+DlgGenStyle : "Styl",
+
+// Image Dialog
+DlgImgTitle : "Beeld eienskappe",
+DlgImgInfoTab : "Beeld informasie",
+DlgImgBtnUpload : "Stuur dit na die Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Uplaai",
+DlgImgAlt : "Alternatiewe beskrywing",
+DlgImgWidth : "Weidte",
+DlgImgHeight : "Hoogde",
+DlgImgLockRatio : "Behou preporsie",
+DlgBtnResetSize : "Herstel groote",
+DlgImgBorder : "Kant",
+DlgImgHSpace : "HSpasie",
+DlgImgVSpace : "VSpasie",
+DlgImgAlign : "Paradeer",
+DlgImgAlignLeft : "Links",
+DlgImgAlignAbsBottom: "Abs Onder",
+DlgImgAlignAbsMiddle: "Abs Middel",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Onder",
+DlgImgAlignMiddle : "Middel",
+DlgImgAlignRight : "Regs",
+DlgImgAlignTextTop : "Text Bo",
+DlgImgAlignTop : "Bo",
+DlgImgPreview : "Voorskou",
+DlgImgAlertUrl : "Voeg asseblief Beeld URL in.",
+DlgImgLinkTab : "Skakel",
+
+// Flash Dialog
+DlgFlashTitle : "Flash eienskappe",
+DlgFlashChkPlay : "Automaties Speel",
+DlgFlashChkLoop : "Herhaling",
+DlgFlashChkMenu : "Laat Flash Menu toe",
+DlgFlashScale : "Scale",
+DlgFlashScaleAll : "Wys alles",
+DlgFlashScaleNoBorder : "Geen kante",
+DlgFlashScaleFit : "Presiese pas",
+
+// Link Dialog
+DlgLnkWindowTitle : "Skakel",
+DlgLnkInfoTab : "Skakel informasie",
+DlgLnkTargetTab : "Mikpunt",
+
+DlgLnkType : "Skakel soort",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Skakel na plekhouers in text",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<ander>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Kies 'n plekhouer",
+DlgLnkAnchorByName : "Volgens plekhouer naam",
+DlgLnkAnchorById : "Volgens element Id",
+DlgLnkNoAnchors : "<Geen plekhouers beskikbaar in dokument>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Adres",
+DlgLnkEMailSubject : "Boodskap Opskrif",
+DlgLnkEMailBody : "Boodskap Inhoud",
+DlgLnkUpload : "Oplaai",
+DlgLnkBtnUpload : "Stuur na Server",
+
+DlgLnkTarget : "Mikpunt",
+DlgLnkTargetFrame : "<raam>",
+DlgLnkTargetPopup : "<popup venster>",
+DlgLnkTargetBlank : "Nuwe Venster (_blank)",
+DlgLnkTargetParent : "Vorige Venster (_parent)",
+DlgLnkTargetSelf : "Selfde Venster (_self)",
+DlgLnkTargetTop : "Boonste Venster (_top)",
+DlgLnkTargetFrameName : "Mikpunt Venster Naam",
+DlgLnkPopWinName : "Popup Venster Naam",
+DlgLnkPopWinFeat : "Popup Venster Geaartheid",
+DlgLnkPopResize : "Verstelbare Groote",
+DlgLnkPopLocation : "Adres Balk",
+DlgLnkPopMenu : "Menu Balk",
+DlgLnkPopScroll : "Gleibalkstuk",
+DlgLnkPopStatus : "Status Balk",
+DlgLnkPopToolbar : "Gereedskap Balk",
+DlgLnkPopFullScrn : "Voll Skerm (IE)",
+DlgLnkPopDependent : "Afhanklik (Netscape)",
+DlgLnkPopWidth : "Weite",
+DlgLnkPopHeight : "Hoogde",
+DlgLnkPopLeft : "Links Posisie",
+DlgLnkPopTop : "Bo Posisie",
+
+DlnLnkMsgNoUrl : "Voeg asseblief die URL in",
+DlnLnkMsgNoEMail : "Voeg asseblief die e-mail adres in",
+DlnLnkMsgNoAnchor : "Kies asseblief 'n plekhouer",
+DlnLnkMsgInvPopName : "Die popup naam moet begin met alphabetiese karakters sonder spasies.",
+
+// Color Dialog
+DlgColorTitle : "Kies Kleur",
+DlgColorBtnClear : "Maak skoon",
+DlgColorHighlight : "Highlight",
+DlgColorSelected : "Geselekteer",
+
+// Smiley Dialog
+DlgSmileyTitle : "Voeg Smiley by",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Kies spesiale karakter",
+
+// Table Dialog
+DlgTableTitle : "Tabel eienskappe",
+DlgTableRows : "Reie",
+DlgTableColumns : "Kolome",
+DlgTableBorder : "Kant groote",
+DlgTableAlign : "Parideering",
+DlgTableAlignNotSet : "<geen instelling>",
+DlgTableAlignLeft : "Links",
+DlgTableAlignCenter : "Middel",
+DlgTableAlignRight : "Regs",
+DlgTableWidth : "Weite",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Hoogde",
+DlgTableCellSpace : "Cell spasieering",
+DlgTableCellPad : "Cell buffer",
+DlgTableCaption : "Beskreiwing",
+DlgTableSummary : "Opsomming",
+
+// Table Cell Dialog
+DlgCellTitle : "Cell eienskappe",
+DlgCellWidth : "Weite",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Hoogde",
+DlgCellWordWrap : "Woord Wrap",
+DlgCellWordWrapNotSet : "<geen instelling>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nee",
+DlgCellHorAlign : "Horisontale rigting",
+DlgCellHorAlignNotSet : "<geen instelling>",
+DlgCellHorAlignLeft : "Links",
+DlgCellHorAlignCenter : "Middel",
+DlgCellHorAlignRight: "Regs",
+DlgCellVerAlign : "Vertikale rigting",
+DlgCellVerAlignNotSet : "<geen instelling>",
+DlgCellVerAlignTop : "Bo",
+DlgCellVerAlignMiddle : "Middel",
+DlgCellVerAlignBottom : "Onder",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rei strekking",
+DlgCellCollSpan : "Kolom strekking",
+DlgCellBackColor : "Agtergrond Kleur",
+DlgCellBorderColor : "Kant Kleur",
+DlgCellBtnSelect : "Keuse...",
+
+// Find Dialog
+DlgFindTitle : "Vind",
+DlgFindFindBtn : "Vind",
+DlgFindNotFoundMsg : "Die gespesifiseerde karakters word nie gevind nie.",
+
+// Replace Dialog
+DlgReplaceTitle : "Vervang",
+DlgReplaceFindLbl : "Soek wat:",
+DlgReplaceReplaceLbl : "Vervang met:",
+DlgReplaceCaseChk : "Vergelyk karakter skryfweise",
+DlgReplaceReplaceBtn : "Vervang",
+DlgReplaceReplAllBtn : "Vervang alles",
+DlgReplaceWordChk : "Vergelyk komplete woord",
+
+// Paste Operations / Dialog
+PasteErrorCut : "U browser se sekuriteit instelling behinder die uitsny aksie. Gebruik asseblief die sleutel kombenasie(Ctrl+X).",
+PasteErrorCopy : "U browser se sekuriteit instelling behinder die kopieerings aksie. Gebruik asseblief die sleutel kombenasie(Ctrl+C).",
+
+PasteAsText : "Voeg slegs karakters by",
+PasteFromWord : "Byvoeging uit Word",
+
+DlgPasteMsg2 : "Voeg asseblief die inhoud in die gegewe box by met sleutel kombenasie(<STRONG>Ctrl+V</STRONG>) en druk <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoreer karakter soort defenisies",
+DlgPasteRemoveStyles : "Verweider Styl defenisies",
+DlgPasteCleanBox : "Maak Box Skoon",
+
+// Color Picker
+ColorAutomatic : "Automaties",
+ColorMoreColors : "Meer Kleure...",
+
+// Document Properties
+DocProps : "Dokument Eienskappe",
+
+// Anchor Dialog
+DlgAnchorTitle : "Plekhouer Eienskappe",
+DlgAnchorName : "Plekhouer Naam",
+DlgAnchorErrorName : "Voltooi die plekhouer naam asseblief",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nie in woordeboek nie",
+DlgSpellChangeTo : "Verander na",
+DlgSpellBtnIgnore : "Ignoreer",
+DlgSpellBtnIgnoreAll : "Ignoreer na-volgende",
+DlgSpellBtnReplace : "Vervang",
+DlgSpellBtnReplaceAll : "vervang na-volgende",
+DlgSpellBtnUndo : "Ont-skep",
+DlgSpellNoSuggestions : "- Geen voorstel -",
+DlgSpellProgress : "Spelling word beproef...",
+DlgSpellNoMispell : "Spellproef kompleet: Geen foute",
+DlgSpellNoChanges : "Spellproef kompleet: Geen woord veranderings",
+DlgSpellOneChange : "Spellproef kompleet: Een woord verander",
+DlgSpellManyChanges : "Spellproef kompleet: %1 woorde verander",
+
+IeSpellDownload : "Geen Spellproefer geinstaleer nie. Wil U dit aflaai?",
+
+// Button Dialog
+DlgButtonText : "Karakters (Waarde)",
+DlgButtonType : "Soort",
+DlgButtonTypeBtn : "Knop",
+DlgButtonTypeSbm : "Indien",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Naam",
+DlgCheckboxValue : "Waarde",
+DlgCheckboxSelected : "Uitgekies",
+
+// Form Dialog
+DlgFormName : "Naam",
+DlgFormAction : "Aksie",
+DlgFormMethod : "Metode",
+
+// Select Field Dialog
+DlgSelectName : "Naam",
+DlgSelectValue : "Waarde",
+DlgSelectSize : "Grote",
+DlgSelectLines : "lyne",
+DlgSelectChkMulti : "Laat meerere keuses toe",
+DlgSelectOpAvail : "Beskikbare Opsies",
+DlgSelectOpText : "Karakters",
+DlgSelectOpValue : "Waarde",
+DlgSelectBtnAdd : "Byvoeg",
+DlgSelectBtnModify : "Verander",
+DlgSelectBtnUp : "Op",
+DlgSelectBtnDown : "Af",
+DlgSelectBtnSetValue : "Stel as uitgekiesde waarde",
+DlgSelectBtnDelete : "Verweider",
+
+// Textarea Dialog
+DlgTextareaName : "Naam",
+DlgTextareaCols : "Kolom",
+DlgTextareaRows : "Reie",
+
+// Text Field Dialog
+DlgTextName : "Naam",
+DlgTextValue : "Waarde",
+DlgTextCharWidth : "Karakter weite",
+DlgTextMaxChars : "Maximale karakters",
+DlgTextType : "Soort",
+DlgTextTypeText : "Karakters",
+DlgTextTypePass : "Wagwoord",
+
+// Hidden Field Dialog
+DlgHiddenName : "Naam",
+DlgHiddenValue : "Waarde",
+
+// Bulleted List Dialog
+BulletedListProp : "Gepunkte lys eienskappe",
+NumberedListProp : "Genommerde lys eienskappe",
+DlgLstStart : "Begin",
+DlgLstType : "Soort",
+DlgLstTypeCircle : "Sirkel",
+DlgLstTypeDisc : "Skyf",
+DlgLstTypeSquare : "Vierkant",
+DlgLstTypeNumbers : "Nommer (1, 2, 3)",
+DlgLstTypeLCase : "Klein Letters (a, b, c)",
+DlgLstTypeUCase : "Hoof Letters (A, B, C)",
+DlgLstTypeSRoman : "Klein Romeinse nommers (i, ii, iii)",
+DlgLstTypeLRoman : "Groot Romeinse nommers (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Algemeen",
+DlgDocBackTab : "Agtergrond",
+DlgDocColorsTab : "Kleure en Rante",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Bladsy Opskrif",
+DlgDocLangDir : "Taal rigting",
+DlgDocLangDirLTR : "Link na Regs (LTR)",
+DlgDocLangDirRTL : "Regs na Links (RTL)",
+DlgDocLangCode : "Taal Kode",
+DlgDocCharSet : "Karakterstel Kodeering",
+DlgDocCharSetCE : "Sentraal Europa",
+DlgDocCharSetCT : "Chinees Traditioneel (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Grieks",
+DlgDocCharSetJP : "Japanees",
+DlgDocCharSetKR : "Koreans",
+DlgDocCharSetTR : "Turks",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "Ander Karakterstel Kodeering",
+
+DlgDocDocType : "Dokument Opskrif Soort",
+DlgDocDocTypeOther : "Ander Dokument Opskrif Soort",
+DlgDocIncXHTML : "Voeg XHTML verklaring by",
+DlgDocBgColor : "Agtergrond kleur",
+DlgDocBgImage : "Agtergrond Beeld URL",
+DlgDocBgNoScroll : "Vasgeklemde Agtergrond",
+DlgDocCText : "Karakters",
+DlgDocCLink : "Skakel",
+DlgDocCVisited : "Besoekte Skakel",
+DlgDocCActive : "Aktiewe Skakel",
+DlgDocMargins : "Bladsy Rante",
+DlgDocMaTop : "Bo",
+DlgDocMaLeft : "Links",
+DlgDocMaRight : "Regs",
+DlgDocMaBottom : "Onder",
+DlgDocMeIndex : "Dokument Index Sleutelwoorde(comma verdeelt)",
+DlgDocMeDescr : "Dokument Beskrywing",
+DlgDocMeAuthor : "Skrywer",
+DlgDocMeCopy : "Kopiereg",
+DlgDocPreview : "Voorskou",
+
+// Templates Dialog
+Templates : "Templates",
+DlgTemplatesTitle : "Inhoud Templates",
+DlgTemplatesSelMsg : "Kies die template om te gebruik in die editor<br>(Inhoud word vervang!):",
+DlgTemplatesLoading : "Templates word gelaai. U geduld asseblief...",
+DlgTemplatesNoTpl : "(Geen templates gedefinieerd)",
+DlgTemplatesReplace : "Vervang bestaande inhoud",
+
+// About Dialog
+DlgAboutAboutTab : "Meer oor",
+DlgAboutBrowserInfoTab : "Blaai Informasie deur",
+DlgAboutLicenseTab : "Lesensie",
+DlgAboutVersion : "weergawe",
+DlgAboutInfo : "Vir meer informasie gaan na "
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ar.js b/httemplate/elements/fckeditor/editor/lang/ar.js
new file mode 100644
index 000000000..91d34f11e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ar.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Arabic language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "rtl",
+
+ToolbarCollapse : "ضم شريط الأدوات",
+ToolbarExpand : "تمدد شريط الأدوات",
+
+// Toolbar Items and Context Menu
+Save : "حفظ",
+NewPage : "صفحة جديدة",
+Preview : "معاينة الصفحة",
+Cut : "قص",
+Copy : "نسخ",
+Paste : "لصق",
+PasteText : "لصق كنص بسيط",
+PasteWord : "لصق من وورد",
+Print : "طباعة",
+SelectAll : "تحديد الكل",
+RemoveFormat : "إزالة التنسيقات",
+InsertLinkLbl : "رابط",
+InsertLink : "إدراج/تحرير رابط",
+RemoveLink : "إزالة رابط",
+Anchor : "إدراج/تحرير إشارة مرجعية",
+InsertImageLbl : "صورة",
+InsertImage : "إدراج/تحرير صورة",
+InsertFlashLbl : "فلاش",
+InsertFlash : "إدراج/تحرير فيلم فلاش",
+InsertTableLbl : "جدول",
+InsertTable : "إدراج/تحرير جدول",
+InsertLineLbl : "خط فاصل",
+InsertLine : "إدراج خط فاصل",
+InsertSpecialCharLbl: "رموز",
+InsertSpecialChar : "إدراج رموز..ِ",
+InsertSmileyLbl : "ابتسامات",
+InsertSmiley : "إدراج ابتسامات",
+About : "حول FCKeditor",
+Bold : "غامق",
+Italic : "مائل",
+Underline : "تسطير",
+StrikeThrough : "يتوسطه خط",
+Subscript : "منخفض",
+Superscript : "مرتفع",
+LeftJustify : "محاذاة إلى اليسار",
+CenterJustify : "توسيط",
+RightJustify : "محاذاة إلى اليمين",
+BlockJustify : "ضبط",
+DecreaseIndent : "إنقاص المسافة البادئة",
+IncreaseIndent : "زيادة المسافة البادئة",
+Undo : "تراجع",
+Redo : "إعادة",
+NumberedListLbl : "تعداد رقمي",
+NumberedList : "إدراج/إلغاء تعداد رقمي",
+BulletedListLbl : "تعداد نقطي",
+BulletedList : "إدراج/إلغاء تعداد نقطي",
+ShowTableBorders : "معاينة حدود الجداول",
+ShowDetails : "معاينة التفاصيل",
+Style : "نمط",
+FontFormat : "تنسيق",
+Font : "خط",
+FontSize : "حجم الخط",
+TextColor : "لون النص",
+BGColor : "لون الخلفية",
+Source : "شفرة المصدر",
+Find : "بحث",
+Replace : "إستبدال",
+SpellCheck : "تدقيق إملائي",
+UniversalKeyboard : "لوحة المفاتيح العالمية",
+PageBreakLbl : "فصل الصفحة",
+PageBreak : "إدخال صفحة جديدة",
+
+Form : "نموذج",
+Checkbox : "خانة إختيار",
+RadioButton : "زر خيار",
+TextField : "مربع نص",
+Textarea : "ناحية نص",
+HiddenField : "إدراج حقل خفي",
+Button : "زر ضغط",
+SelectionField : "قائمة منسدلة",
+ImageButton : "زر صورة",
+
+FitWindow : "تكبير حجم المحرر",
+
+// Context Menu
+EditLink : "تحرير رابط",
+CellCM : "خلية",
+RowCM : "صف",
+ColumnCM : "عمود",
+InsertRow : "إدراج صف",
+DeleteRows : "حذف صفوف",
+InsertColumn : "إدراج عمود",
+DeleteColumns : "حذف أعمدة",
+InsertCell : "إدراج خلية",
+DeleteCells : "حذف خلايا",
+MergeCells : "دمج خلايا",
+SplitCell : "تقسيم خلية",
+TableDelete : "حذف الجدول",
+CellProperties : "خصائص الخلية",
+TableProperties : "خصائص الجدول",
+ImageProperties : "خصائص الصورة",
+FlashProperties : "خصائص فيلم الفلاش",
+
+AnchorProp : "خصائص الإشارة المرجعية",
+ButtonProp : "خصائص زر الضغط",
+CheckboxProp : "خصائص خانة الإختيار",
+HiddenFieldProp : "خصائص الحقل الخفي",
+RadioButtonProp : "خصائص زر الخيار",
+ImageButtonProp : "خصائص زر الصورة",
+TextFieldProp : "خصائص مربع النص",
+SelectionFieldProp : "خصائص القائمة المنسدلة",
+TextareaProp : "خصائص ناحية النص",
+FormProp : "خصائص النموذج",
+
+FontFormats : "عادي;منسّق;دوس;العنوان 1;العنوان 2;العنوان 3;العنوان 4;العنوان 5;العنوان 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "إنتظر قليلاً ريثما تتم معالَجة‏ XHTML. لن يستغرق طويلاً...",
+Done : "تم",
+PasteWordConfirm : "يبدو أن النص المراد لصقه منسوخ من برنامج وورد. هل تود تنظيفه قبل الشروع في عملية اللصق؟",
+NotCompatiblePaste : "هذه الميزة تحتاج لمتصفح من النوعInternet Explorer إصدار 5.5 فما فوق. هل تود اللصق دون تنظيف الكود؟",
+UnknownToolbarItem : "عنصر شريط أدوات غير معروف \"%1\"",
+UnknownCommand : "أمر غير معروف \"%1\"",
+NotImplemented : "لم يتم دعم هذا الأمر",
+UnknownToolbarSet : "لم أتمكن من العثور على طقم الأدوات \"%1\" ",
+NoActiveX : "لتأمين متصفحك يجب أن تحدد بعض مميزات المحرر. يتوجب عليك تمكين الخيار \"Run ActiveX controls and plug-ins\". قد تواجة أخطاء وتلاحظ مميزات مفقودة",
+BrowseServerBlocked : "لايمكن فتح مصدر المتصفح. فضلا يجب التأكد بأن جميع موانع النوافذ المنبثقة معطلة",
+DialogBlocked : "لايمكن فتح نافذة الحوار . فضلا تأكد من أن مانع النوافذ المنبثة معطل .",
+
+// Dialogs
+DlgBtnOK : "موافق",
+DlgBtnCancel : "إلغاء الأمر",
+DlgBtnClose : "إغلاق",
+DlgBtnBrowseServer : "تصفح الخادم",
+DlgAdvancedTag : "متقدم",
+DlgOpOther : "<أخرى>",
+DlgInfoTab : "معلومات",
+DlgAlertUrl : "الرجاء كتابة عنوان الإنترنت",
+
+// General Dialogs Labels
+DlgGenNotSet : "<بدون تحديد>",
+DlgGenId : "الرقم",
+DlgGenLangDir : "إتجاه النص",
+DlgGenLangDirLtr : "اليسار لليمين (LTR)",
+DlgGenLangDirRtl : "اليمين لليسار (RTL)",
+DlgGenLangCode : "رمز اللغة",
+DlgGenAccessKey : "مفاتيح الإختصار",
+DlgGenName : "الاسم",
+DlgGenTabIndex : "الترتيب",
+DlgGenLongDescr : "عنوان الوصف المفصّل",
+DlgGenClass : "فئات التنسيق",
+DlgGenTitle : "تلميح الشاشة",
+DlgGenContType : "نوع التلميح",
+DlgGenLinkCharset : "ترميز المادة المطلوبة",
+DlgGenStyle : "نمط",
+
+// Image Dialog
+DlgImgTitle : "خصائص الصورة",
+DlgImgInfoTab : "معلومات الصورة",
+DlgImgBtnUpload : "أرسلها للخادم",
+DlgImgURL : "موقع الصورة",
+DlgImgUpload : "رفع",
+DlgImgAlt : "الوصف",
+DlgImgWidth : "العرض",
+DlgImgHeight : "الإرتفاع",
+DlgImgLockRatio : "تناسق الحجم",
+DlgBtnResetSize : "إستعادة الحجم الأصلي",
+DlgImgBorder : "سمك الحدود",
+DlgImgHSpace : "تباعد أفقي",
+DlgImgVSpace : "تباعد عمودي",
+DlgImgAlign : "محاذاة",
+DlgImgAlignLeft : "يسار",
+DlgImgAlignAbsBottom: "أسفل النص",
+DlgImgAlignAbsMiddle: "وسط السطر",
+DlgImgAlignBaseline : "على السطر",
+DlgImgAlignBottom : "أسفل",
+DlgImgAlignMiddle : "وسط",
+DlgImgAlignRight : "يمين",
+DlgImgAlignTextTop : "أعلى النص",
+DlgImgAlignTop : "أعلى",
+DlgImgPreview : "معاينة",
+DlgImgAlertUrl : "فضلاً أكتب الموقع الذي توجد عليه هذه الصورة.",
+DlgImgLinkTab : "الرابط",
+
+// Flash Dialog
+DlgFlashTitle : "خصائص فيلم الفلاش",
+DlgFlashChkPlay : "تشغيل تلقائي",
+DlgFlashChkLoop : "تكرار",
+DlgFlashChkMenu : "تمكين قائمة فيلم الفلاش",
+DlgFlashScale : "الحجم",
+DlgFlashScaleAll : "إظهار الكل",
+DlgFlashScaleNoBorder : "بلا حدود",
+DlgFlashScaleFit : "ضبط تام",
+
+// Link Dialog
+DlgLnkWindowTitle : "إرتباط تشعبي",
+DlgLnkInfoTab : "معلومات الرابط",
+DlgLnkTargetTab : "الهدف",
+
+DlgLnkType : "نوع الربط",
+DlgLnkTypeURL : "العنوان",
+DlgLnkTypeAnchor : "مكان في هذا المستند",
+DlgLnkTypeEMail : "بريد إلكتروني",
+DlgLnkProto : "البروتوكول",
+DlgLnkProtoOther : "<أخرى>",
+DlgLnkURL : "الموقع",
+DlgLnkAnchorSel : "اختر علامة مرجعية",
+DlgLnkAnchorByName : "حسب اسم العلامة",
+DlgLnkAnchorById : "حسب تعريف العنصر",
+DlgLnkNoAnchors : "<لا يوجد علامات مرجعية في هذا المستند>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "عنوان بريد إلكتروني",
+DlgLnkEMailSubject : "موضوع الرسالة",
+DlgLnkEMailBody : "محتوى الرسالة",
+DlgLnkUpload : "رفع",
+DlgLnkBtnUpload : "أرسلها للخادم",
+
+DlgLnkTarget : "الهدف",
+DlgLnkTargetFrame : "<إطار>",
+DlgLnkTargetPopup : "<نافذة منبثقة>",
+DlgLnkTargetBlank : "إطار جديد (_blank)",
+DlgLnkTargetParent : "الإطار الأصل (_parent)",
+DlgLnkTargetSelf : "نفس الإطار (_self)",
+DlgLnkTargetTop : "صفحة كاملة (_top)",
+DlgLnkTargetFrameName : "اسم الإطار الهدف",
+DlgLnkPopWinName : "تسمية النافذة المنبثقة",
+DlgLnkPopWinFeat : "خصائص النافذة المنبثقة",
+DlgLnkPopResize : "قابلة للتحجيم",
+DlgLnkPopLocation : "شريط العنوان",
+DlgLnkPopMenu : "القوائم الرئيسية",
+DlgLnkPopScroll : "أشرطة التمرير",
+DlgLnkPopStatus : "شريط الحالة السفلي",
+DlgLnkPopToolbar : "شريط الأدوات",
+DlgLnkPopFullScrn : "ملئ الشاشة (IE)",
+DlgLnkPopDependent : "تابع (Netscape)",
+DlgLnkPopWidth : "العرض",
+DlgLnkPopHeight : "الإرتفاع",
+DlgLnkPopLeft : "التمركز لليسار",
+DlgLnkPopTop : "التمركز للأعلى",
+
+DlnLnkMsgNoUrl : "فضلاً أدخل عنوان الموقع الذي يشير إليه الرابط",
+DlnLnkMsgNoEMail : "فضلاً أدخل عنوان البريد الإلكتروني",
+DlnLnkMsgNoAnchor : "فضلاً حدد العلامة المرجعية المرغوبة",
+DlnLnkMsgInvPopName : "اسم النافذة المنبثقة يجب أن يبدأ بحرف أبجدي دون مسافات",
+
+// Color Dialog
+DlgColorTitle : "اختر لوناً",
+DlgColorBtnClear : "مسح",
+DlgColorHighlight : "تحديد",
+DlgColorSelected : "إختيار",
+
+// Smiley Dialog
+DlgSmileyTitle : "إدراج إبتسامات ",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "إدراج رمز",
+
+// Table Dialog
+DlgTableTitle : "إدراج جدول",
+DlgTableRows : "صفوف",
+DlgTableColumns : "أعمدة",
+DlgTableBorder : "سمك الحدود",
+DlgTableAlign : "المحاذاة",
+DlgTableAlignNotSet : "<بدون تحديد>",
+DlgTableAlignLeft : "يسار",
+DlgTableAlignCenter : "وسط",
+DlgTableAlignRight : "يمين",
+DlgTableWidth : "العرض",
+DlgTableWidthPx : "بكسل",
+DlgTableWidthPc : "بالمئة",
+DlgTableHeight : "الإرتفاع",
+DlgTableCellSpace : "تباعد الخلايا",
+DlgTableCellPad : "المسافة البادئة",
+DlgTableCaption : "الوصف",
+DlgTableSummary : "الخلاصة",
+
+// Table Cell Dialog
+DlgCellTitle : "خصائص الخلية",
+DlgCellWidth : "العرض",
+DlgCellWidthPx : "بكسل",
+DlgCellWidthPc : "بالمئة",
+DlgCellHeight : "الإرتفاع",
+DlgCellWordWrap : "التفاف النص",
+DlgCellWordWrapNotSet : "<بدون تحديد>",
+DlgCellWordWrapYes : "نعم",
+DlgCellWordWrapNo : "لا",
+DlgCellHorAlign : "المحاذاة الأفقية",
+DlgCellHorAlignNotSet : "<بدون تحديد>",
+DlgCellHorAlignLeft : "يسار",
+DlgCellHorAlignCenter : "وسط",
+DlgCellHorAlignRight: "يمين",
+DlgCellVerAlign : "المحاذاة العمودية",
+DlgCellVerAlignNotSet : "<بدون تحديد>",
+DlgCellVerAlignTop : "أعلى",
+DlgCellVerAlignMiddle : "وسط",
+DlgCellVerAlignBottom : "أسفل",
+DlgCellVerAlignBaseline : "على السطر",
+DlgCellRowSpan : "إمتداد الصفوف",
+DlgCellCollSpan : "إمتداد الأعمدة",
+DlgCellBackColor : "لون الخلفية",
+DlgCellBorderColor : "لون الحدود",
+DlgCellBtnSelect : "حدّد...",
+
+// Find Dialog
+DlgFindTitle : "بحث",
+DlgFindFindBtn : "ابحث",
+DlgFindNotFoundMsg : "لم يتم العثور على النص المحدد.",
+
+// Replace Dialog
+DlgReplaceTitle : "إستبدال",
+DlgReplaceFindLbl : "البحث عن:",
+DlgReplaceReplaceLbl : "إستبدال بـ:",
+DlgReplaceCaseChk : "مطابقة حالة الأحرف",
+DlgReplaceReplaceBtn : "إستبدال",
+DlgReplaceReplAllBtn : "إستبدال الكل",
+DlgReplaceWordChk : "الكلمة بالكامل فقط",
+
+// Paste Operations / Dialog
+PasteErrorCut : "الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع القص التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl+X).",
+PasteErrorCopy : "الإعدادات الأمنية للمتصفح الذي تستخدمه تمنع النسخ التلقائي. فضلاً إستخدم لوحة المفاتيح لفعل ذلك (Ctrl+C).",
+
+PasteAsText : "لصق كنص بسيط",
+PasteFromWord : "لصق من وورد",
+
+DlgPasteMsg2 : "الصق داخل الصندوق بإستخدام زرّي (<STRONG>Ctrl+V</STRONG>) في لوحة المفاتيح، ثم اضغط زر <STRONG>موافق</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "تجاهل تعريفات أسماء الخطوط",
+DlgPasteRemoveStyles : "إزالة تعريفات الأنماط",
+DlgPasteCleanBox : "نظّف محتوى الصندوق",
+
+// Color Picker
+ColorAutomatic : "تلقائي",
+ColorMoreColors : "ألوان إضافية...",
+
+// Document Properties
+DocProps : "خصائص الصفحة",
+
+// Anchor Dialog
+DlgAnchorTitle : "خصائص إشارة مرجعية",
+DlgAnchorName : "اسم الإشارة المرجعية",
+DlgAnchorErrorName : "الرجاء كتابة اسم الإشارة المرجعية",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "ليست في القاموس",
+DlgSpellChangeTo : "التغيير إلى",
+DlgSpellBtnIgnore : "تجاهل",
+DlgSpellBtnIgnoreAll : "تجاهل الكل",
+DlgSpellBtnReplace : "تغيير",
+DlgSpellBtnReplaceAll : "تغيير الكل",
+DlgSpellBtnUndo : "تراجع",
+DlgSpellNoSuggestions : "- لا توجد إقتراحات -",
+DlgSpellProgress : "جاري التدقيق إملائياً",
+DlgSpellNoMispell : "تم إكمال التدقيق الإملائي: لم يتم العثور على أي أخطاء إملائية",
+DlgSpellNoChanges : "تم إكمال التدقيق الإملائي: لم يتم تغيير أي كلمة",
+DlgSpellOneChange : "تم إكمال التدقيق الإملائي: تم تغيير كلمة واحدة فقط",
+DlgSpellManyChanges : "تم إكمال التدقيق الإملائي: تم تغيير %1 كلمات\كلمة",
+
+IeSpellDownload : "المدقق الإملائي (الإنجليزي) غير مثبّت. هل تود تحميله الآن؟",
+
+// Button Dialog
+DlgButtonText : "القيمة/التسمية",
+DlgButtonType : "نوع الزر",
+DlgButtonTypeBtn : "زر",
+DlgButtonTypeSbm : "إرسال",
+DlgButtonTypeRst : "إعادة تعيين",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "الاسم",
+DlgCheckboxValue : "القيمة",
+DlgCheckboxSelected : "محدد",
+
+// Form Dialog
+DlgFormName : "الاسم",
+DlgFormAction : "اسم الملف",
+DlgFormMethod : "الأسلوب",
+
+// Select Field Dialog
+DlgSelectName : "الاسم",
+DlgSelectValue : "القيمة",
+DlgSelectSize : "الحجم",
+DlgSelectLines : "الأسطر",
+DlgSelectChkMulti : "السماح بتحديدات متعددة",
+DlgSelectOpAvail : "الخيارات المتاحة",
+DlgSelectOpText : "النص",
+DlgSelectOpValue : "القيمة",
+DlgSelectBtnAdd : "إضافة",
+DlgSelectBtnModify : "تعديل",
+DlgSelectBtnUp : "تحريك لأعلى",
+DlgSelectBtnDown : "تحريك لأسفل",
+DlgSelectBtnSetValue : "إجعلها محددة",
+DlgSelectBtnDelete : "إزالة",
+
+// Textarea Dialog
+DlgTextareaName : "الاسم",
+DlgTextareaCols : "الأعمدة",
+DlgTextareaRows : "الصفوف",
+
+// Text Field Dialog
+DlgTextName : "الاسم",
+DlgTextValue : "القيمة",
+DlgTextCharWidth : "العرض بالأحرف",
+DlgTextMaxChars : "عدد الحروف الأقصى",
+DlgTextType : "نوع المحتوى",
+DlgTextTypeText : "نص",
+DlgTextTypePass : "كلمة مرور",
+
+// Hidden Field Dialog
+DlgHiddenName : "الاسم",
+DlgHiddenValue : "القيمة",
+
+// Bulleted List Dialog
+BulletedListProp : "خصائص التعداد النقطي",
+NumberedListProp : "خصائص التعداد الرقمي",
+DlgLstStart : "البدء عند",
+DlgLstType : "النوع",
+DlgLstTypeCircle : "دائرة",
+DlgLstTypeDisc : "قرص",
+DlgLstTypeSquare : "مربع",
+DlgLstTypeNumbers : "أرقام (1، 2، 3)َ",
+DlgLstTypeLCase : "حروف صغيرة (a, b, c)َ",
+DlgLstTypeUCase : "حروف كبيرة (A, B, C)َ",
+DlgLstTypeSRoman : "ترقيم روماني صغير (i, ii, iii)َ",
+DlgLstTypeLRoman : "ترقيم روماني كبير (I, II, III)َ",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "عام",
+DlgDocBackTab : "الخلفية",
+DlgDocColorsTab : "الألوان والهوامش",
+DlgDocMetaTab : "المعرّفات الرأسية",
+
+DlgDocPageTitle : "عنوان الصفحة",
+DlgDocLangDir : "إتجاه اللغة",
+DlgDocLangDirLTR : "اليسار لليمين (LTR)",
+DlgDocLangDirRTL : "اليمين لليسار (RTL)",
+DlgDocLangCode : "رمز اللغة",
+DlgDocCharSet : "ترميز الحروف",
+DlgDocCharSetCE : "أوروبا الوسطى",
+DlgDocCharSetCT : "الصينية التقليدية (Big5)",
+DlgDocCharSetCR : "السيريلية",
+DlgDocCharSetGR : "اليونانية",
+DlgDocCharSetJP : "اليابانية",
+DlgDocCharSetKR : "الكورية",
+DlgDocCharSetTR : "التركية",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "أوروبا الغربية",
+DlgDocCharSetOther : "ترميز آخر",
+
+DlgDocDocType : "ترويسة نوع الصفحة",
+DlgDocDocTypeOther : "ترويسة نوع صفحة أخرى",
+DlgDocIncXHTML : "تضمين إعلانات‏ لغة XHTMLَ",
+DlgDocBgColor : "لون الخلفية",
+DlgDocBgImage : "رابط الصورة الخلفية",
+DlgDocBgNoScroll : "جعلها علامة مائية",
+DlgDocCText : "النص",
+DlgDocCLink : "الروابط",
+DlgDocCVisited : "المزارة",
+DlgDocCActive : "النشطة",
+DlgDocMargins : "هوامش الصفحة",
+DlgDocMaTop : "علوي",
+DlgDocMaLeft : "أيسر",
+DlgDocMaRight : "أيمن",
+DlgDocMaBottom : "سفلي",
+DlgDocMeIndex : "الكلمات الأساسية (مفصولة بفواصل)َ",
+DlgDocMeDescr : "وصف الصفحة",
+DlgDocMeAuthor : "الكاتب",
+DlgDocMeCopy : "المالك",
+DlgDocPreview : "معاينة",
+
+// Templates Dialog
+Templates : "القوالب",
+DlgTemplatesTitle : "قوالب المحتوى",
+DlgTemplatesSelMsg : "اختر القالب الذي تود وضعه في المحرر <br>(سيتم فقدان المحتوى الحالي):",
+DlgTemplatesLoading : "جاري تحميل قائمة القوالب، الرجاء الإنتظار...",
+DlgTemplatesNoTpl : "(لم يتم تعريف أي قالب)",
+DlgTemplatesReplace : "استبدال المحتوى",
+
+// About Dialog
+DlgAboutAboutTab : "نبذة",
+DlgAboutBrowserInfoTab : "معلومات متصفحك",
+DlgAboutLicenseTab : "الترخيص",
+DlgAboutVersion : "الإصدار",
+DlgAboutInfo : "لمزيد من المعلومات تفضل بزيارة"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/bg.js b/httemplate/elements/fckeditor/editor/lang/bg.js
new file mode 100644
index 000000000..423bd02d7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/bg.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Bulgarian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Скрий панела с инструментите",
+ToolbarExpand : "Покажи панела с инструментите",
+
+// Toolbar Items and Context Menu
+Save : "Запази",
+NewPage : "Нова страница",
+Preview : "Предварителен изглед",
+Cut : "Изрежи",
+Copy : "Запамети",
+Paste : "Вмъкни",
+PasteText : "Вмъкни само текст",
+PasteWord : "Вмъкни от MS Word",
+Print : "Печат",
+SelectAll : "Селектирай всичко",
+RemoveFormat : "Изтрий форматирането",
+InsertLinkLbl : "Връзка",
+InsertLink : "Добави/Редактирай връзка",
+RemoveLink : "Изтрий връзка",
+Anchor : "Добави/Редактирай котва",
+InsertImageLbl : "Изображение",
+InsertImage : "Добави/Редактирай изображение",
+InsertFlashLbl : "Flash",
+InsertFlash : "Добави/Редактиай Flash обект",
+InsertTableLbl : "Таблица",
+InsertTable : "Добави/Редактирай таблица",
+InsertLineLbl : "Линия",
+InsertLine : "Вмъкни хоризонтална линия",
+InsertSpecialCharLbl: "Специален символ",
+InsertSpecialChar : "Вмъкни специален символ",
+InsertSmileyLbl : "Усмивка",
+InsertSmiley : "Добави усмивка",
+About : "За FCKeditor",
+Bold : "Удебелен",
+Italic : "Курсив",
+Underline : "Подчертан",
+StrikeThrough : "Зачертан",
+Subscript : "Индекс за база",
+Superscript : "Индекс за степен",
+LeftJustify : "Подравняване в ляво",
+CenterJustify : "Подравнявне в средата",
+RightJustify : "Подравняване в дясно",
+BlockJustify : "Двустранно подравняване",
+DecreaseIndent : "Намали отстъпа",
+IncreaseIndent : "Увеличи отстъпа",
+Undo : "Отмени",
+Redo : "Повтори",
+NumberedListLbl : "Нумериран списък",
+NumberedList : "Добави/Изтрий нумериран списък",
+BulletedListLbl : "Ненумериран списък",
+BulletedList : "Добави/Изтрий ненумериран списък",
+ShowTableBorders : "Покажи рамките на таблицата",
+ShowDetails : "Покажи подробности",
+Style : "Стил",
+FontFormat : "Формат",
+Font : "Шрифт",
+FontSize : "Размер",
+TextColor : "Цвят на текста",
+BGColor : "Цвят на фона",
+Source : "Код",
+Find : "Търси",
+Replace : "Замести",
+SpellCheck : "Провери правописа",
+UniversalKeyboard : "Универсална клавиатура",
+PageBreakLbl : "Нов ред",
+PageBreak : "Вмъкни нов ред",
+
+Form : "Формуляр",
+Checkbox : "Поле за отметка",
+RadioButton : "Поле за опция",
+TextField : "Текстово поле",
+Textarea : "Текстова област",
+HiddenField : "Скрито поле",
+Button : "Бутон",
+SelectionField : "Падащо меню с опции",
+ImageButton : "Бутон-изображение",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Редактирай връзка",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Добави ред",
+DeleteRows : "Изтрий редовете",
+InsertColumn : "Добави колона",
+DeleteColumns : "Изтрий колоните",
+InsertCell : "Добави клетка",
+DeleteCells : "Изтрий клетките",
+MergeCells : "Обедини клетките",
+SplitCell : "Раздели клетката",
+TableDelete : "Изтрий таблицата",
+CellProperties : "Параметри на клетката",
+TableProperties : "Параметри на таблицата",
+ImageProperties : "Параметри на изображението",
+FlashProperties : "Параметри на Flash обекта",
+
+AnchorProp : "Параметри на котвата",
+ButtonProp : "Параметри на бутона",
+CheckboxProp : "Параметри на полето за отметка",
+HiddenFieldProp : "Параметри на скритото поле",
+RadioButtonProp : "Параметри на полето за опция",
+ImageButtonProp : "Параметри на бутона-изображение",
+TextFieldProp : "Параметри на текстовото-поле",
+SelectionFieldProp : "Параметри на падащото меню с опции",
+TextareaProp : "Параметри на текстовата област",
+FormProp : "Параметри на формуляра",
+
+FontFormats : "Нормален;Форматиран;Адрес;Заглавие 1;Заглавие 2;Заглавие 3;Заглавие 4;Заглавие 5;Заглавие 6;Параграф (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Обработка на XHTML. Моля изчакайте...",
+Done : "Готово",
+PasteWordConfirm : "Текстът, който искате да вмъкнете е копиран от MS Word. Желаете ли да бъде изчистен преди вмъкването?",
+NotCompatiblePaste : "Тази операция изисква MS Internet Explorer версия 5.5 или по-висока. Желаете ли да вмъкнете запаметеното без изчистване?",
+UnknownToolbarItem : "Непознат инструмент \"%1\"",
+UnknownCommand : "Непозната команда \"%1\"",
+NotImplemented : "Командата не е имплементирана",
+UnknownToolbarSet : "Панелът \"%1\" не съществува",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "ОК",
+DlgBtnCancel : "Отказ",
+DlgBtnClose : "Затвори",
+DlgBtnBrowseServer : "Разгледай сървъра",
+DlgAdvancedTag : "Подробности...",
+DlgOpOther : "<Друго>",
+DlgInfoTab : "Информация",
+DlgAlertUrl : "Моля, въведете пълния път (URL)",
+
+// General Dialogs Labels
+DlgGenNotSet : "<не е настроен>",
+DlgGenId : "Идентификатор",
+DlgGenLangDir : "посока на речта",
+DlgGenLangDirLtr : "От ляво на дясно",
+DlgGenLangDirRtl : "От дясно на ляво",
+DlgGenLangCode : "Код на езика",
+DlgGenAccessKey : "Бърз клавиш",
+DlgGenName : "Име",
+DlgGenTabIndex : "Ред на достъп",
+DlgGenLongDescr : "Описание на връзката",
+DlgGenClass : "Клас от стиловите таблици",
+DlgGenTitle : "Препоръчително заглавие",
+DlgGenContType : "Препоръчителен тип на съдържанието",
+DlgGenLinkCharset : "Тип на свързания ресурс",
+DlgGenStyle : "Стил",
+
+// Image Dialog
+DlgImgTitle : "Параметри на изображението",
+DlgImgInfoTab : "Информация за изображението",
+DlgImgBtnUpload : "Прати към сървъра",
+DlgImgURL : "Пълен път (URL)",
+DlgImgUpload : "Качи",
+DlgImgAlt : "Алтернативен текст",
+DlgImgWidth : "Ширина",
+DlgImgHeight : "Височина",
+DlgImgLockRatio : "Запази пропорцията",
+DlgBtnResetSize : "Възстанови размера",
+DlgImgBorder : "Рамка",
+DlgImgHSpace : "Хоризонтален отстъп",
+DlgImgVSpace : "Вертикален отстъп",
+DlgImgAlign : "Подравняване",
+DlgImgAlignLeft : "Ляво",
+DlgImgAlignAbsBottom: "Най-долу",
+DlgImgAlignAbsMiddle: "Точно по средата",
+DlgImgAlignBaseline : "По базовата линия",
+DlgImgAlignBottom : "Долу",
+DlgImgAlignMiddle : "По средата",
+DlgImgAlignRight : "Дясно",
+DlgImgAlignTextTop : "Върху текста",
+DlgImgAlignTop : "Отгоре",
+DlgImgPreview : "Изглед",
+DlgImgAlertUrl : "Моля, въведете пълния път до изображението",
+DlgImgLinkTab : "Връзка",
+
+// Flash Dialog
+DlgFlashTitle : "Параметри на Flash обекта",
+DlgFlashChkPlay : "Автоматично стартиране",
+DlgFlashChkLoop : "Ново стартиране след завършването",
+DlgFlashChkMenu : "Разрешено Flash меню",
+DlgFlashScale : "Оразмеряване",
+DlgFlashScaleAll : "Покажи целия обект",
+DlgFlashScaleNoBorder : "Без рамка",
+DlgFlashScaleFit : "Според мястото",
+
+// Link Dialog
+DlgLnkWindowTitle : "Връзка",
+DlgLnkInfoTab : "Информация за връзката",
+DlgLnkTargetTab : "Цел",
+
+DlgLnkType : "Вид на връзката",
+DlgLnkTypeURL : "Пълен път (URL)",
+DlgLnkTypeAnchor : "Котва в текущата страница",
+DlgLnkTypeEMail : "Е-поща",
+DlgLnkProto : "Протокол",
+DlgLnkProtoOther : "<друго>",
+DlgLnkURL : "Пълен път (URL)",
+DlgLnkAnchorSel : "Изберете котва",
+DlgLnkAnchorByName : "По име на котвата",
+DlgLnkAnchorById : "По идентификатор на елемент",
+DlgLnkNoAnchors : "<Няма котви в текущия документ>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Адрес за е-поща",
+DlgLnkEMailSubject : "Тема на писмото",
+DlgLnkEMailBody : "Текст на писмото",
+DlgLnkUpload : "Качи",
+DlgLnkBtnUpload : "Прати на сървъра",
+
+DlgLnkTarget : "Цел",
+DlgLnkTargetFrame : "<рамка>",
+DlgLnkTargetPopup : "<дъщерен прозорец>",
+DlgLnkTargetBlank : "Нов прозорец (_blank)",
+DlgLnkTargetParent : "Родителски прозорец (_parent)",
+DlgLnkTargetSelf : "Активния прозорец (_self)",
+DlgLnkTargetTop : "Целия прозорец (_top)",
+DlgLnkTargetFrameName : "Име на целевия прозорец",
+DlgLnkPopWinName : "Име на дъщерния прозорец",
+DlgLnkPopWinFeat : "Параметри на дъщерния прозорец",
+DlgLnkPopResize : "С променливи размери",
+DlgLnkPopLocation : "Поле за адрес",
+DlgLnkPopMenu : "Меню",
+DlgLnkPopScroll : "Плъзгач",
+DlgLnkPopStatus : "Поле за статус",
+DlgLnkPopToolbar : "Панел с бутони",
+DlgLnkPopFullScrn : "Голям екран (MS IE)",
+DlgLnkPopDependent : "Зависим (Netscape)",
+DlgLnkPopWidth : "Ширина",
+DlgLnkPopHeight : "Височина",
+DlgLnkPopLeft : "Координати - X",
+DlgLnkPopTop : "Координати - Y",
+
+DlnLnkMsgNoUrl : "Моля, напишете пълния път (URL)",
+DlnLnkMsgNoEMail : "Моля, напишете адреса за е-поща",
+DlnLnkMsgNoAnchor : "Моля, изберете котва",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Изберете цвят",
+DlgColorBtnClear : "Изчисти",
+DlgColorHighlight : "Текущ",
+DlgColorSelected : "Избран",
+
+// Smiley Dialog
+DlgSmileyTitle : "Добави усмивка",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Изберете специален символ",
+
+// Table Dialog
+DlgTableTitle : "Параметри на таблицата",
+DlgTableRows : "Редове",
+DlgTableColumns : "Колони",
+DlgTableBorder : "Размер на рамката",
+DlgTableAlign : "Подравняване",
+DlgTableAlignNotSet : "<Не е избрано>",
+DlgTableAlignLeft : "Ляво",
+DlgTableAlignCenter : "Център",
+DlgTableAlignRight : "Дясно",
+DlgTableWidth : "Ширина",
+DlgTableWidthPx : "пиксели",
+DlgTableWidthPc : "проценти",
+DlgTableHeight : "Височина",
+DlgTableCellSpace : "Разстояние между клетките",
+DlgTableCellPad : "Отстъп на съдържанието в клетките",
+DlgTableCaption : "Заглавие",
+DlgTableSummary : "Резюме",
+
+// Table Cell Dialog
+DlgCellTitle : "Параметри на клетката",
+DlgCellWidth : "Ширина",
+DlgCellWidthPx : "пиксели",
+DlgCellWidthPc : "проценти",
+DlgCellHeight : "Височина",
+DlgCellWordWrap : "пренасяне на нов ред",
+DlgCellWordWrapNotSet : "<Не е настроено>",
+DlgCellWordWrapYes : "Да",
+DlgCellWordWrapNo : "не",
+DlgCellHorAlign : "Хоризонтално подравняване",
+DlgCellHorAlignNotSet : "<Не е настроено>",
+DlgCellHorAlignLeft : "Ляво",
+DlgCellHorAlignCenter : "Център",
+DlgCellHorAlignRight: "Дясно",
+DlgCellVerAlign : "Вертикално подравняване",
+DlgCellVerAlignNotSet : "<Не е настроено>",
+DlgCellVerAlignTop : "Горе",
+DlgCellVerAlignMiddle : "По средата",
+DlgCellVerAlignBottom : "Долу",
+DlgCellVerAlignBaseline : "По базовата линия",
+DlgCellRowSpan : "повече от един ред",
+DlgCellCollSpan : "повече от една колона",
+DlgCellBackColor : "фонов цвят",
+DlgCellBorderColor : "цвят на рамката",
+DlgCellBtnSelect : "Изберете...",
+
+// Find Dialog
+DlgFindTitle : "Търси",
+DlgFindFindBtn : "Търси",
+DlgFindNotFoundMsg : "Указания текст не беше намерен.",
+
+// Replace Dialog
+DlgReplaceTitle : "Замести",
+DlgReplaceFindLbl : "Търси:",
+DlgReplaceReplaceLbl : "Замести с:",
+DlgReplaceCaseChk : "Със същия регистър",
+DlgReplaceReplaceBtn : "Замести",
+DlgReplaceReplAllBtn : "Замести всички",
+DlgReplaceWordChk : "Търси същата дума",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Настройките за сигурност на вашия бразуър не разрешават на редактора да изпълни изрязването. За целта използвайте клавиатурата (Ctrl+X).",
+PasteErrorCopy : "Настройките за сигурност на вашия бразуър не разрешават на редактора да изпълни запаметяването. За целта използвайте клавиатурата (Ctrl+C).",
+
+PasteAsText : "Вмъкни като чист текст",
+PasteFromWord : "Вмъкни от MS Word",
+
+DlgPasteMsg2 : "Вмъкнете тук съдъжанието с клавиатуарата (<STRONG>Ctrl+V</STRONG>) и натиснете <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Игнорирай шрифтовите дефиниции",
+DlgPasteRemoveStyles : "Изтрий стиловите дефиниции",
+DlgPasteCleanBox : "Изчисти",
+
+// Color Picker
+ColorAutomatic : "По подразбиране",
+ColorMoreColors : "Други цветове...",
+
+// Document Properties
+DocProps : "Параметри на документа",
+
+// Anchor Dialog
+DlgAnchorTitle : "Параметри на котвата",
+DlgAnchorName : "Име на котвата",
+DlgAnchorErrorName : "Моля, въведете име на котвата",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Липсва в речника",
+DlgSpellChangeTo : "Промени на",
+DlgSpellBtnIgnore : "Игнорирай",
+DlgSpellBtnIgnoreAll : "Игнорирай всички",
+DlgSpellBtnReplace : "Замести",
+DlgSpellBtnReplaceAll : "Замести всички",
+DlgSpellBtnUndo : "Отмени",
+DlgSpellNoSuggestions : "- Няма предложения -",
+DlgSpellProgress : "Извършване на проверката за правопис...",
+DlgSpellNoMispell : "Проверката за правопис завършена: не са открити правописни грешки",
+DlgSpellNoChanges : "Проверката за правопис завършена: няма променени думи",
+DlgSpellOneChange : "Проверката за правопис завършена: една дума е променена",
+DlgSpellManyChanges : "Проверката за правопис завършена: %1 думи са променени",
+
+IeSpellDownload : "Инструментът за проверка на правопис не е инсталиран. Желаете ли да го инсталирате ?",
+
+// Button Dialog
+DlgButtonText : "Текст (Стойност)",
+DlgButtonType : "Тип",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Име",
+DlgCheckboxValue : "Стойност",
+DlgCheckboxSelected : "Отметнато",
+
+// Form Dialog
+DlgFormName : "Име",
+DlgFormAction : "Действие",
+DlgFormMethod : "Метод",
+
+// Select Field Dialog
+DlgSelectName : "Име",
+DlgSelectValue : "Стойност",
+DlgSelectSize : "Размер",
+DlgSelectLines : "линии",
+DlgSelectChkMulti : "Разрешено множествено селектиране",
+DlgSelectOpAvail : "Възможни опции",
+DlgSelectOpText : "Текст",
+DlgSelectOpValue : "Стойност",
+DlgSelectBtnAdd : "Добави",
+DlgSelectBtnModify : "Промени",
+DlgSelectBtnUp : "Нагоре",
+DlgSelectBtnDown : "Надолу",
+DlgSelectBtnSetValue : "Настрой като избрана стойност",
+DlgSelectBtnDelete : "Изтрий",
+
+// Textarea Dialog
+DlgTextareaName : "Име",
+DlgTextareaCols : "Колони",
+DlgTextareaRows : "Редове",
+
+// Text Field Dialog
+DlgTextName : "Име",
+DlgTextValue : "Стойност",
+DlgTextCharWidth : "Ширина на символите",
+DlgTextMaxChars : "Максимум символи",
+DlgTextType : "Тип",
+DlgTextTypeText : "Текст",
+DlgTextTypePass : "Парола",
+
+// Hidden Field Dialog
+DlgHiddenName : "Име",
+DlgHiddenValue : "Стойност",
+
+// Bulleted List Dialog
+BulletedListProp : "Параметри на ненумерирания списък",
+NumberedListProp : "Параметри на нумерирания списък",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Тип",
+DlgLstTypeCircle : "Окръжност",
+DlgLstTypeDisc : "Кръг",
+DlgLstTypeSquare : "Квадрат",
+DlgLstTypeNumbers : "Числа (1, 2, 3)",
+DlgLstTypeLCase : "Малки букви (a, b, c)",
+DlgLstTypeUCase : "Големи букви (A, B, C)",
+DlgLstTypeSRoman : "Малки римски числа (i, ii, iii)",
+DlgLstTypeLRoman : "Големи римски числа (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Общи",
+DlgDocBackTab : "Фон",
+DlgDocColorsTab : "Цветове и отстъпи",
+DlgDocMetaTab : "Мета данни",
+
+DlgDocPageTitle : "Заглавие на страницата",
+DlgDocLangDir : "Посока на речта",
+DlgDocLangDirLTR : "От ляво на дясно",
+DlgDocLangDirRTL : "От дясно на ляво",
+DlgDocLangCode : "Код на езика",
+DlgDocCharSet : "Кодиране на символите",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Друго кодиране на символите",
+
+DlgDocDocType : "Тип на документа",
+DlgDocDocTypeOther : "Друг тип на документа",
+DlgDocIncXHTML : "Включи XHTML декларация",
+DlgDocBgColor : "Цвят на фона",
+DlgDocBgImage : "Пълен път до фоновото изображение",
+DlgDocBgNoScroll : "Не-повтарящо се фоново изображение",
+DlgDocCText : "Текст",
+DlgDocCLink : "Връзка",
+DlgDocCVisited : "Посетена връзка",
+DlgDocCActive : "Активна връзка",
+DlgDocMargins : "Отстъпи на страницата",
+DlgDocMaTop : "Горе",
+DlgDocMaLeft : "Ляво",
+DlgDocMaRight : "Дясно",
+DlgDocMaBottom : "Долу",
+DlgDocMeIndex : "Ключови думи за документа (разделени със запетаи)",
+DlgDocMeDescr : "Описание на документа",
+DlgDocMeAuthor : "Автор",
+DlgDocMeCopy : "Авторски права",
+DlgDocPreview : "Изглед",
+
+// Templates Dialog
+Templates : "Шаблони",
+DlgTemplatesTitle : "Шаблони",
+DlgTemplatesSelMsg : "Изберете шаблон <br>(текущото съдържание на редактора ще бъде загубено):",
+DlgTemplatesLoading : "Зареждане на списъка с шаблоните. Моля изчакайте...",
+DlgTemplatesNoTpl : "(Няма дефинирани шаблони)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "За",
+DlgAboutBrowserInfoTab : "Информация за браузъра",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "версия",
+DlgAboutInfo : "За повече информация посетете"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/bn.js b/httemplate/elements/fckeditor/editor/lang/bn.js
new file mode 100644
index 000000000..8f76754ae
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/bn.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Bengali/Bangla language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "টূলবার গুটিয়ে দাও",
+ToolbarExpand : "টূলবার ছড়িয়ে দাও",
+
+// Toolbar Items and Context Menu
+Save : "সংরক্ষন কর",
+NewPage : "নতুন পেজ",
+Preview : "প্রিভিউ",
+Cut : "কাট",
+Copy : "কপি",
+Paste : "পেস্ট",
+PasteText : "পেস্ট (সাদা টেক্সট)",
+PasteWord : "পেস্ট (শব্দ)",
+Print : "প্রিন্ট",
+SelectAll : "সব সিলেক্ট কর",
+RemoveFormat : "ফরমেট সরাও",
+InsertLinkLbl : "লিংকের যুক্ত করার লেবেল",
+InsertLink : "লিংক যুক্ত কর",
+RemoveLink : "লিংক সরাও",
+Anchor : "নোঙ্গর",
+InsertImageLbl : "ছবির লেবেল যুক্ত কর",
+InsertImage : "ছবি যুক্ত কর",
+InsertFlashLbl : "ফ্লাশ লেবেল যুক্ত কর",
+InsertFlash : "ফ্লাশ যুক্ত কর",
+InsertTableLbl : "টেবিলের লেবেল যুক্ত কর",
+InsertTable : "টেবিল যুক্ত কর",
+InsertLineLbl : "রেখা যুক্ত কর",
+InsertLine : "রেখা যুক্ত কর",
+InsertSpecialCharLbl: "বিশেষ অক্ষরের লেবেল যুক্ত কর",
+InsertSpecialChar : "বিশেষ অক্ষর যুক্ত কর",
+InsertSmileyLbl : "স্মাইলী",
+InsertSmiley : "স্মাইলী যুক্ত কর",
+About : "FCKeditor কে বানিয়েছে",
+Bold : "বোল্ড",
+Italic : "ইটালিক",
+Underline : "আন্ডারলাইন",
+StrikeThrough : "স্ট্রাইক থ্রু",
+Subscript : "অধোলেখ",
+Superscript : "অভিলেখ",
+LeftJustify : "বা দিকে ঘেঁষা",
+CenterJustify : "মাঝ বরাবর ঘেষা",
+RightJustify : "ডান দিকে ঘেঁষা",
+BlockJustify : "ব্লক জাস্টিফাই",
+DecreaseIndent : "ইনডেন্ট কমাও",
+IncreaseIndent : "ইনডেন্ট বাড়াও",
+Undo : "আনডু",
+Redo : "রি-ডু",
+NumberedListLbl : "সাংখ্যিক লিস্টের লেবেল",
+NumberedList : "সাংখ্যিক লিস্ট",
+BulletedListLbl : "বুলেট লিস্ট লেবেল",
+BulletedList : "বুলেটেড লিস্ট",
+ShowTableBorders : "টেবিল বর্ডার",
+ShowDetails : "সবটুকু দেখাও",
+Style : "স্টাইল",
+FontFormat : "ফন্ট ফরমেট",
+Font : "ফন্ট",
+FontSize : "সাইজ",
+TextColor : "টেক্স্ট রং",
+BGColor : "বেকগ্রাউন্ড রং",
+Source : "সোর্স",
+Find : "খোজো",
+Replace : "রিপ্লেস",
+SpellCheck : "বানান চেক",
+UniversalKeyboard : "সার্বজনীন কিবোর্ড",
+PageBreakLbl : "পেজ ব্রেক লেবেল",
+PageBreak : "পেজ ব্রেক",
+
+Form : "ফর্ম",
+Checkbox : "চেক বাক্স",
+RadioButton : "রেডিও বাটন",
+TextField : "টেক্সট ফীল্ড",
+Textarea : "টেক্সট এরিয়া",
+HiddenField : "গুপ্ত ফীল্ড",
+Button : "বাটন",
+SelectionField : "বাছাই ফীল্ড",
+ImageButton : "ছবির বাটন",
+
+FitWindow : "উইন্ডো ফিট কর",
+
+// Context Menu
+EditLink : "লিংক সম্পাদন",
+CellCM : "সেল",
+RowCM : "রো",
+ColumnCM : "কলাম",
+InsertRow : "রো যুক্ত কর",
+DeleteRows : "রো মুছে দাও",
+InsertColumn : "কলাম যুক্ত কর",
+DeleteColumns : "কলাম মুছে দাও",
+InsertCell : "সেল যুক্ত কর",
+DeleteCells : "সেল মুছে দাও",
+MergeCells : "সেল জোড়া দাও",
+SplitCell : "সেল আলাদা কর",
+TableDelete : "টেবিল ডিলীট কর",
+CellProperties : "সেলের প্রোপার্টিজ",
+TableProperties : "টেবিল প্রোপার্টি",
+ImageProperties : "ছবি প্রোপার্টি",
+FlashProperties : "ফ্লাশ প্রোপার্টি",
+
+AnchorProp : "নোঙর প্রোপার্টি",
+ButtonProp : "বাটন প্রোপার্টি",
+CheckboxProp : "চেক বক্স প্রোপার্টি",
+HiddenFieldProp : "গুপ্ত ফীল্ড প্রোপার্টি",
+RadioButtonProp : "রেডিও বাটন প্রোপার্টি",
+ImageButtonProp : "ছবি বাটন প্রোপার্টি",
+TextFieldProp : "টেক্সট ফীল্ড প্রোপার্টি",
+SelectionFieldProp : "বাছাই ফীল্ড প্রোপার্টি",
+TextareaProp : "টেক্সট এরিয়া প্রোপার্টি",
+FormProp : "ফর্ম প্রোপার্টি",
+
+FontFormats : "সাধারণ;ফর্মেটেড;ঠিকানা;শীর্ষক ১;শীর্ষক ২;শীর্ষক ৩;শীর্ষক ৪;শীর্ষক ৫;শীর্ষক ৬;শীর্ষক (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML প্রসেস করা হচ্ছে",
+Done : "শেষ হয়েছে",
+PasteWordConfirm : "যে টেকস্টটি আপনি পেস্ট করতে চাচ্ছেন মনে হচ্ছে সেটি ওয়ার্ড থেকে কপি করা। আপনি কি পেস্ট করার আগে একে পরিষ্কার করতে চান?",
+NotCompatiblePaste : "এই কমান্ডটি শুধুমাত্র ইন্টারনেট এক্সপ্লোরার ৫.০ বা তার পরের ভার্সনে পাওয়া সম্ভব। আপনি কি পরিষ্কার না করেই পেস্ট করতে চান?",
+UnknownToolbarItem : "অজানা টুলবার আইটেম \"%1\"",
+UnknownCommand : "অজানা কমান্ড \"%1\"",
+NotImplemented : "কমান্ড ইমপ্লিমেন্ট করা হয়নি",
+UnknownToolbarSet : "টুলবার সেট \"%1\" এর অস্তিত্ব নেই",
+NoActiveX : "আপনার ব্রাউজারের সুরক্ষা সেটিংস কারনে এডিটরের কিছু ফিচার পাওয়া নাও যেতে পারে। আপনাকে অবশ্যই \"Run ActiveX controls and plug-ins\" এনাবেল করে নিতে হবে। আপনি ভুলভ্রান্তি কিছু কিছু ফিচারের অনুপস্থিতি উপলব্ধি করতে পারেন।",
+BrowseServerBlocked : "রিসোর্স ব্রাউজার খোলা গেল না। নিশ্চিত করুন যে সব পপআপ ব্লকার বন্ধ করা আছে।",
+DialogBlocked : "ডায়ালগ ইউন্ডো খোলা গেল না। নিশ্চিত করুন যে সব পপআপ ব্লকার বন্ধ করা আছে।",
+
+// Dialogs
+DlgBtnOK : "ওকে",
+DlgBtnCancel : "বাতিল",
+DlgBtnClose : "বন্ধ কর",
+DlgBtnBrowseServer : "ব্রাউজ সার্ভার",
+DlgAdvancedTag : "এডভান্সড",
+DlgOpOther : "<অন্য>",
+DlgInfoTab : "তথ্য",
+DlgAlertUrl : "দয়া করে URL যুক্ত করুন",
+
+// General Dialogs Labels
+DlgGenNotSet : "<সেট নেই>",
+DlgGenId : "আইডি",
+DlgGenLangDir : "ভাষা লেখার দিক",
+DlgGenLangDirLtr : "বাম থেকে ডান (LTR)",
+DlgGenLangDirRtl : "ডান থেকে বাম (RTL)",
+DlgGenLangCode : "ভাষা কোড",
+DlgGenAccessKey : "এক্সেস কী",
+DlgGenName : "নাম",
+DlgGenTabIndex : "ট্যাব ইন্ডেক্স",
+DlgGenLongDescr : "URL এর লম্বা বর্ণনা",
+DlgGenClass : "স্টাইল-শীট ক্লাস",
+DlgGenTitle : "পরামর্শ শীর্ষক",
+DlgGenContType : "পরামর্শ কন্টেন্টের প্রকার",
+DlgGenLinkCharset : "লিংক রিসোর্স ক্যারেক্টর সেট",
+DlgGenStyle : "স্টাইল",
+
+// Image Dialog
+DlgImgTitle : "ছবির প্রোপার্টি",
+DlgImgInfoTab : "ছবির তথ্য",
+DlgImgBtnUpload : "ইহাকে সার্ভারে প্রেরন কর",
+DlgImgURL : "URL",
+DlgImgUpload : "আপলোড",
+DlgImgAlt : "বিকল্প টেক্সট",
+DlgImgWidth : "প্রস্থ",
+DlgImgHeight : "দৈর্ঘ্য",
+DlgImgLockRatio : "অনুপাত লক কর",
+DlgBtnResetSize : "সাইজ পূর্বাবস্থায় ফিরিয়ে দাও",
+DlgImgBorder : "বর্ডার",
+DlgImgHSpace : "হরাইজন্টাল স্পেস",
+DlgImgVSpace : "ভার্টিকেল স্পেস",
+DlgImgAlign : "এলাইন",
+DlgImgAlignLeft : "বামে",
+DlgImgAlignAbsBottom: "Abs নীচে",
+DlgImgAlignAbsMiddle: "Abs উপর",
+DlgImgAlignBaseline : "মূল রেখা",
+DlgImgAlignBottom : "নীচে",
+DlgImgAlignMiddle : "মধ্য",
+DlgImgAlignRight : "ডানে",
+DlgImgAlignTextTop : "টেক্সট উপর",
+DlgImgAlignTop : "উপর",
+DlgImgPreview : "প্রীভিউ",
+DlgImgAlertUrl : "অনুগ্রহক করে ছবির URL টাইপ করুন",
+DlgImgLinkTab : "লিংক",
+
+// Flash Dialog
+DlgFlashTitle : "ফ্ল্যাশ প্রোপার্টি",
+DlgFlashChkPlay : "অটো প্লে",
+DlgFlashChkLoop : "লূপ",
+DlgFlashChkMenu : "ফ্ল্যাশ মেনু এনাবল কর",
+DlgFlashScale : "স্কেল",
+DlgFlashScaleAll : "সব দেখাও",
+DlgFlashScaleNoBorder : "কোনো বর্ডার নেই",
+DlgFlashScaleFit : "নিখুঁত ফিট",
+
+// Link Dialog
+DlgLnkWindowTitle : "লিংক",
+DlgLnkInfoTab : "লিংক তথ্য",
+DlgLnkTargetTab : "টার্গেট",
+
+DlgLnkType : "লিংক প্রকার",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "এই পেজে নোঙর কর",
+DlgLnkTypeEMail : "ইমেইল",
+DlgLnkProto : "প্রোটোকল",
+DlgLnkProtoOther : "<অন্য>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "নোঙর বাছাই",
+DlgLnkAnchorByName : "নোঙরের নাম দিয়ে",
+DlgLnkAnchorById : "নোঙরের আইডি দিয়ে",
+DlgLnkNoAnchors : "<ডকুমেন্টে আর কোন নোঙর নেই>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "ইমেইল ঠিকানা",
+DlgLnkEMailSubject : "মেসেজের বিষয়",
+DlgLnkEMailBody : "মেসেজের দেহ",
+DlgLnkUpload : "আপলোড",
+DlgLnkBtnUpload : "একে সার্ভারে পাঠাও",
+
+DlgLnkTarget : "টার্গেট",
+DlgLnkTargetFrame : "<ফ্রেম>",
+DlgLnkTargetPopup : "<পপআপ উইন্ডো>",
+DlgLnkTargetBlank : "নতুন উইন্ডো (_blank)",
+DlgLnkTargetParent : "মূল উইন্ডো (_parent)",
+DlgLnkTargetSelf : "এই উইন্ডো (_self)",
+DlgLnkTargetTop : "শীর্ষ উইন্ডো (_top)",
+DlgLnkTargetFrameName : "টার্গেট ফ্রেমের নাম",
+DlgLnkPopWinName : "পপআপ উইন্ডোর নাম",
+DlgLnkPopWinFeat : "পপআপ উইন্ডো ফীচার সমূহ",
+DlgLnkPopResize : "রিসাইজ করা সম্ভব",
+DlgLnkPopLocation : "লোকেশন বার",
+DlgLnkPopMenu : "মেন্যু বার",
+DlgLnkPopScroll : "স্ক্রল বার",
+DlgLnkPopStatus : "স্ট্যাটাস বার",
+DlgLnkPopToolbar : "টুল বার",
+DlgLnkPopFullScrn : "পূর্ণ পর্দা জুড়ে (IE)",
+DlgLnkPopDependent : "ডিপেন্ডেন্ট (Netscape)",
+DlgLnkPopWidth : "প্রস্থ",
+DlgLnkPopHeight : "দৈর্ঘ্য",
+DlgLnkPopLeft : "বামের পজিশন",
+DlgLnkPopTop : "ডানের পজিশন",
+
+DlnLnkMsgNoUrl : "অনুগ্রহ করে URL লিংক টাইপ করুন",
+DlnLnkMsgNoEMail : "অনুগ্রহ করে ইমেইল এড্রেস টাইপ করুন",
+DlnLnkMsgNoAnchor : "অনুগ্রহ করে নোঙর বাছাই করুন",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "রং বাছাই কর",
+DlgColorBtnClear : "পরিষ্কার কর",
+DlgColorHighlight : "হাইলাইট",
+DlgColorSelected : "সিলেক্টেড",
+
+// Smiley Dialog
+DlgSmileyTitle : "স্মাইলী যুক্ত কর",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "বিশেষ ক্যারেক্টার বাছাই কর",
+
+// Table Dialog
+DlgTableTitle : "টেবিল প্রোপার্টি",
+DlgTableRows : "রো",
+DlgTableColumns : "কলাম",
+DlgTableBorder : "বর্ডার সাইজ",
+DlgTableAlign : "এলাইনমেন্ট",
+DlgTableAlignNotSet : "<সেট নেই>",
+DlgTableAlignLeft : "বামে",
+DlgTableAlignCenter : "মাঝখানে",
+DlgTableAlignRight : "ডানে",
+DlgTableWidth : "প্রস্থ",
+DlgTableWidthPx : "পিক্সেল",
+DlgTableWidthPc : "শতকরা",
+DlgTableHeight : "দৈর্ঘ্য",
+DlgTableCellSpace : "সেল স্পেস",
+DlgTableCellPad : "সেল প্যাডিং",
+DlgTableCaption : "শীর্ষক",
+DlgTableSummary : "সারাংশ",
+
+// Table Cell Dialog
+DlgCellTitle : "সেল প্রোপার্টি",
+DlgCellWidth : "প্রস্থ",
+DlgCellWidthPx : "পিক্সেল",
+DlgCellWidthPc : "শতকরা",
+DlgCellHeight : "দৈর্ঘ্য",
+DlgCellWordWrap : "ওয়ার্ড রেপ",
+DlgCellWordWrapNotSet : "<সেট নেই>",
+DlgCellWordWrapYes : "হাঁ",
+DlgCellWordWrapNo : "না",
+DlgCellHorAlign : "হরাইজন্টাল এলাইনমেন্ট",
+DlgCellHorAlignNotSet : "<সেট নেই>",
+DlgCellHorAlignLeft : "বামে",
+DlgCellHorAlignCenter : "মাঝখানে",
+DlgCellHorAlignRight: "ডানে",
+DlgCellVerAlign : "ভার্টিক্যাল এলাইনমেন্ট",
+DlgCellVerAlignNotSet : "<সেট নেই>",
+DlgCellVerAlignTop : "উপর",
+DlgCellVerAlignMiddle : "মধ্য",
+DlgCellVerAlignBottom : "নীচে",
+DlgCellVerAlignBaseline : "মূলরেখা",
+DlgCellRowSpan : "রো স্প্যান",
+DlgCellCollSpan : "কলাম স্প্যান",
+DlgCellBackColor : "ব্যাকগ্রাউন্ড রং",
+DlgCellBorderColor : "বর্ডারের রং",
+DlgCellBtnSelect : "বাছাই কর",
+
+// Find Dialog
+DlgFindTitle : "খোঁজো",
+DlgFindFindBtn : "খোঁজো",
+DlgFindNotFoundMsg : "আপনার উল্লেখিত টেকস্ট পাওয়া যায়নি",
+
+// Replace Dialog
+DlgReplaceTitle : "বদলে দাও",
+DlgReplaceFindLbl : "যা খুঁজতে হবে:",
+DlgReplaceReplaceLbl : "যার সাথে বদলাতে হবে:",
+DlgReplaceCaseChk : "কেস মিলাও",
+DlgReplaceReplaceBtn : "বদলে দাও",
+DlgReplaceReplAllBtn : "সব বদলে দাও",
+DlgReplaceWordChk : "পুরা শব্দ মেলাও",
+
+// Paste Operations / Dialog
+PasteErrorCut : "আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কাট করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl+X)।",
+PasteErrorCopy : "আপনার ব্রাউজারের সুরক্ষা সেটিংস এডিটরকে অটোমেটিক কপি করার অনুমতি দেয়নি। দয়া করে এই কাজের জন্য কিবোর্ড ব্যবহার করুন (Ctrl+C)।",
+
+PasteAsText : "সাদা টেক্সট হিসেবে পেস্ট কর",
+PasteFromWord : "ওয়ার্ড থেকে পেস্ট কর",
+
+DlgPasteMsg2 : "অনুগ্রহ করে নীচের বাক্সে কিবোর্ড ব্যবহার করে (<STRONG>Ctrl+V</STRONG>) পেস্ট করুন এবং <STRONG>OK</STRONG> চাপ দিন",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "ফন্ট ফেস ডেফিনেশন ইগনোর করুন",
+DlgPasteRemoveStyles : "স্টাইল ডেফিনেশন সরিয়ে দিন",
+DlgPasteCleanBox : "বাক্স পরিষ্কার করুন",
+
+// Color Picker
+ColorAutomatic : "অটোমেটিক",
+ColorMoreColors : "আরও রং...",
+
+// Document Properties
+DocProps : "ডক্যুমেন্ট প্রোপার্টি",
+
+// Anchor Dialog
+DlgAnchorTitle : "নোঙরের প্রোপার্টি",
+DlgAnchorName : "নোঙরের নাম",
+DlgAnchorErrorName : "নোঙরের নাম টাইপ করুন",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "শব্দকোষে নেই",
+DlgSpellChangeTo : "এতে বদলাও",
+DlgSpellBtnIgnore : "ইগনোর কর",
+DlgSpellBtnIgnoreAll : "সব ইগনোর কর",
+DlgSpellBtnReplace : "বদলে দাও",
+DlgSpellBtnReplaceAll : "সব বদলে দাও",
+DlgSpellBtnUndo : "আন্ডু",
+DlgSpellNoSuggestions : "- কোন সাজেশন নেই -",
+DlgSpellProgress : "বানান পরীক্ষা চলছে...",
+DlgSpellNoMispell : "বানান পরীক্ষা শেষ: কোন ভুল বানান পাওয়া যায়নি",
+DlgSpellNoChanges : "বানান পরীক্ষা শেষ: কোন শব্দ পরিবর্তন করা হয়নি",
+DlgSpellOneChange : "বানান পরীক্ষা শেষ: একটি মাত্র শব্দ পরিবর্তন করা হয়েছে",
+DlgSpellManyChanges : "বানান পরীক্ষা শেষ: %1 গুলো শব্দ বদলে গ্যাছে",
+
+IeSpellDownload : "বানান পরীক্ষক ইনস্টল করা নেই। আপনি কি এখনই এটা ডাউনলোড করতে চান?",
+
+// Button Dialog
+DlgButtonText : "টেক্সট (ভ্যালু)",
+DlgButtonType : "প্রকার",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "নাম",
+DlgCheckboxValue : "ভ্যালু",
+DlgCheckboxSelected : "সিলেক্টেড",
+
+// Form Dialog
+DlgFormName : "নাম",
+DlgFormAction : "একশ্যন",
+DlgFormMethod : "পদ্ধতি",
+
+// Select Field Dialog
+DlgSelectName : "নাম",
+DlgSelectValue : "ভ্যালু",
+DlgSelectSize : "সাইজ",
+DlgSelectLines : "লাইন সমূহ",
+DlgSelectChkMulti : "একাধিক সিলেকশন এলাউ কর",
+DlgSelectOpAvail : "অন্যান্য বিকল্প",
+DlgSelectOpText : "টেক্সট",
+DlgSelectOpValue : "ভ্যালু",
+DlgSelectBtnAdd : "যুক্ত",
+DlgSelectBtnModify : "বদলে দাও",
+DlgSelectBtnUp : "উপর",
+DlgSelectBtnDown : "নীচে",
+DlgSelectBtnSetValue : "বাছাই করা ভ্যালু হিসেবে সেট কর",
+DlgSelectBtnDelete : "ডিলীট",
+
+// Textarea Dialog
+DlgTextareaName : "নাম",
+DlgTextareaCols : "কলাম",
+DlgTextareaRows : "রো",
+
+// Text Field Dialog
+DlgTextName : "নাম",
+DlgTextValue : "ভ্যালু",
+DlgTextCharWidth : "ক্যারেক্টার প্রশস্ততা",
+DlgTextMaxChars : "সর্বাধিক ক্যারেক্টার",
+DlgTextType : "টাইপ",
+DlgTextTypeText : "টেক্সট",
+DlgTextTypePass : "পাসওয়ার্ড",
+
+// Hidden Field Dialog
+DlgHiddenName : "নাম",
+DlgHiddenValue : "ভ্যালু",
+
+// Bulleted List Dialog
+BulletedListProp : "বুলেটেড সূচী প্রোপার্টি",
+NumberedListProp : "সাংখ্যিক সূচী প্রোপার্টি",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "প্রকার",
+DlgLstTypeCircle : "গোল",
+DlgLstTypeDisc : "ডিস্ক",
+DlgLstTypeSquare : "চৌকোণা",
+DlgLstTypeNumbers : "সংখ্যা (1, 2, 3)",
+DlgLstTypeLCase : "ছোট অক্ষর (a, b, c)",
+DlgLstTypeUCase : "বড় অক্ষর (A, B, C)",
+DlgLstTypeSRoman : "ছোট রোমান সংখ্যা (i, ii, iii)",
+DlgLstTypeLRoman : "বড় রোমান সংখ্যা (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "সাধারন",
+DlgDocBackTab : "ব্যাকগ্রাউন্ড",
+DlgDocColorsTab : "রং এবং মার্জিন",
+DlgDocMetaTab : "মেটাডেটা",
+
+DlgDocPageTitle : "পেজ শীর্ষক",
+DlgDocLangDir : "ভাষা লিখার দিক",
+DlgDocLangDirLTR : "বাম থেকে ডানে (LTR)",
+DlgDocLangDirRTL : "ডান থেকে বামে (RTL)",
+DlgDocLangCode : "ভাষা কোড",
+DlgDocCharSet : "ক্যারেক্টার সেট এনকোডিং",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "অন্য ক্যারেক্টার সেট এনকোডিং",
+
+DlgDocDocType : "ডক্যুমেন্ট টাইপ হেডিং",
+DlgDocDocTypeOther : "অন্য ডক্যুমেন্ট টাইপ হেডিং",
+DlgDocIncXHTML : "XHTML ডেক্লারেশন যুক্ত কর",
+DlgDocBgColor : "ব্যাকগ্রাউন্ড রং",
+DlgDocBgImage : "ব্যাকগ্রাউন্ড ছবির URL",
+DlgDocBgNoScroll : "স্ক্রলহীন ব্যাকগ্রাউন্ড",
+DlgDocCText : "টেক্সট",
+DlgDocCLink : "লিংক",
+DlgDocCVisited : "ভিজিট করা লিংক",
+DlgDocCActive : "সক্রিয় লিংক",
+DlgDocMargins : "পেজ মার্জিন",
+DlgDocMaTop : "উপর",
+DlgDocMaLeft : "বামে",
+DlgDocMaRight : "ডানে",
+DlgDocMaBottom : "নীচে",
+DlgDocMeIndex : "ডক্যুমেন্ট ইন্ডেক্স কিওয়ার্ড (কমা দ্বারা বিচ্ছিন্ন)",
+DlgDocMeDescr : "ডক্যূমেন্ট বর্ণনা",
+DlgDocMeAuthor : "লেখক",
+DlgDocMeCopy : "কপীরাইট",
+DlgDocPreview : "প্রীভিউ",
+
+// Templates Dialog
+Templates : "টেমপ্লেট",
+DlgTemplatesTitle : "কনটেন্ট টেমপ্লেট",
+DlgTemplatesSelMsg : "অনুগ্রহ করে এডিটরে ওপেন করার জন্য টেমপ্লেট বাছাই করুন<br>(আসল কনটেন্ট হারিয়ে যাবে):",
+DlgTemplatesLoading : "টেমপ্লেট লিস্ট হারিয়ে যাবে। অনুগ্রহ করে অপেক্ষা করুন...",
+DlgTemplatesNoTpl : "(কোন টেমপ্লেট ডিফাইন করা নেই)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "কে বানিয়েছে",
+DlgAboutBrowserInfoTab : "ব্রাউজারের ব্যাপারে তথ্য",
+DlgAboutLicenseTab : "লাইসেন্স",
+DlgAboutVersion : "ভার্সন",
+DlgAboutInfo : "আরও তথ্যের জন্য যান"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/bs.js b/httemplate/elements/fckeditor/editor/lang/bs.js
new file mode 100644
index 000000000..fbaa45191
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/bs.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Bosnian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skupi trake sa alatima",
+ToolbarExpand : "Otvori trake sa alatima",
+
+// Toolbar Items and Context Menu
+Save : "Snimi",
+NewPage : "Novi dokument",
+Preview : "Prikaži",
+Cut : "Izreži",
+Copy : "Kopiraj",
+Paste : "Zalijepi",
+PasteText : "Zalijepi kao obièan tekst",
+PasteWord : "Zalijepi iz Word-a",
+Print : "Štampaj",
+SelectAll : "Selektuj sve",
+RemoveFormat : "Poništi format",
+InsertLinkLbl : "Link",
+InsertLink : "Ubaci/Izmjeni link",
+RemoveLink : "Izbriši link",
+Anchor : "Insert/Edit Anchor", //MISSING
+InsertImageLbl : "Slika",
+InsertImage : "Ubaci/Izmjeni sliku",
+InsertFlashLbl : "Flash", //MISSING
+InsertFlash : "Insert/Edit Flash", //MISSING
+InsertTableLbl : "Tabela",
+InsertTable : "Ubaci/Izmjeni tabelu",
+InsertLineLbl : "Linija",
+InsertLine : "Ubaci horizontalnu liniju",
+InsertSpecialCharLbl: "Specijalni karakter",
+InsertSpecialChar : "Ubaci specijalni karater",
+InsertSmileyLbl : "Smješko",
+InsertSmiley : "Ubaci smješka",
+About : "O FCKeditor-u",
+Bold : "Boldiraj",
+Italic : "Ukosi",
+Underline : "Podvuci",
+StrikeThrough : "Precrtaj",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Lijevo poravnanje",
+CenterJustify : "Centralno poravnanje",
+RightJustify : "Desno poravnanje",
+BlockJustify : "Puno poravnanje",
+DecreaseIndent : "Smanji uvod",
+IncreaseIndent : "Poveæaj uvod",
+Undo : "Vrati",
+Redo : "Ponovi",
+NumberedListLbl : "Numerisana lista",
+NumberedList : "Ubaci/Izmjeni numerisanu listu",
+BulletedListLbl : "Lista",
+BulletedList : "Ubaci/Izmjeni listu",
+ShowTableBorders : "Pokaži okvire tabela",
+ShowDetails : "Pokaži detalje",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Velièina",
+TextColor : "Boja teksta",
+BGColor : "Boja pozadine",
+Source : "HTML kôd",
+Find : "Naði",
+Replace : "Zamjeni",
+SpellCheck : "Check Spelling", //MISSING
+UniversalKeyboard : "Universal Keyboard", //MISSING
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Form", //MISSING
+Checkbox : "Checkbox", //MISSING
+RadioButton : "Radio Button", //MISSING
+TextField : "Text Field", //MISSING
+Textarea : "Textarea", //MISSING
+HiddenField : "Hidden Field", //MISSING
+Button : "Button", //MISSING
+SelectionField : "Selection Field", //MISSING
+ImageButton : "Image Button", //MISSING
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Izmjeni link",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Ubaci red",
+DeleteRows : "Briši redove",
+InsertColumn : "Ubaci kolonu",
+DeleteColumns : "Briši kolone",
+InsertCell : "Ubaci æeliju",
+DeleteCells : "Briši æelije",
+MergeCells : "Spoji æelije",
+SplitCell : "Razdvoji æeliju",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Svojstva æelije",
+TableProperties : "Svojstva tabele",
+ImageProperties : "Svojstva slike",
+FlashProperties : "Flash Properties", //MISSING
+
+AnchorProp : "Anchor Properties", //MISSING
+ButtonProp : "Button Properties", //MISSING
+CheckboxProp : "Checkbox Properties", //MISSING
+HiddenFieldProp : "Hidden Field Properties", //MISSING
+RadioButtonProp : "Radio Button Properties", //MISSING
+ImageButtonProp : "Image Button Properties", //MISSING
+TextFieldProp : "Text Field Properties", //MISSING
+SelectionFieldProp : "Selection Field Properties", //MISSING
+TextareaProp : "Textarea Properties", //MISSING
+FormProp : "Form Properties", //MISSING
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Procesiram XHTML. Molim saèekajte...",
+Done : "Gotovo",
+PasteWordConfirm : "Tekst koji želite zalijepiti èini se da je kopiran iz Worda. Da li želite da se prvo oèisti?",
+NotCompatiblePaste : "Ova komanda je podržana u Internet Explorer-u verzijama 5.5 ili novijim. Da li želite da izvršite lijepljenje teksta bez èišæenja?",
+UnknownToolbarItem : "Nepoznata stavka sa trake sa alatima \"%1\"",
+UnknownCommand : "Nepoznata komanda \"%1\"",
+NotImplemented : "Komanda nije implementirana",
+UnknownToolbarSet : "Traka sa alatima \"%1\" ne postoji",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Odustani",
+DlgBtnClose : "Zatvori",
+DlgBtnBrowseServer : "Browse Server", //MISSING
+DlgAdvancedTag : "Naprednije",
+DlgOpOther : "<Other>", //MISSING
+DlgInfoTab : "Info", //MISSING
+DlgAlertUrl : "Please insert the URL", //MISSING
+
+// General Dialogs Labels
+DlgGenNotSet : "<nije podešeno>",
+DlgGenId : "Id",
+DlgGenLangDir : "Smjer pisanja",
+DlgGenLangDirLtr : "S lijeva na desno (LTR)",
+DlgGenLangDirRtl : "S desna na lijevo (RTL)",
+DlgGenLangCode : "Jezièni kôd",
+DlgGenAccessKey : "Pristupna tipka",
+DlgGenName : "Naziv",
+DlgGenTabIndex : "Tab indeks",
+DlgGenLongDescr : "Dugaèki opis URL-a",
+DlgGenClass : "Klase CSS stilova",
+DlgGenTitle : "Advisory title",
+DlgGenContType : "Advisory vrsta sadržaja",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Svojstva slike",
+DlgImgInfoTab : "Info slike",
+DlgImgBtnUpload : "Šalji na server",
+DlgImgURL : "URL",
+DlgImgUpload : "Šalji",
+DlgImgAlt : "Tekst na slici",
+DlgImgWidth : "Širina",
+DlgImgHeight : "Visina",
+DlgImgLockRatio : "Zakljuèaj odnos",
+DlgBtnResetSize : "Resetuj dimenzije",
+DlgImgBorder : "Okvir",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Poravnanje",
+DlgImgAlignLeft : "Lijevo",
+DlgImgAlignAbsBottom: "Abs dole",
+DlgImgAlignAbsMiddle: "Abs sredina",
+DlgImgAlignBaseline : "Bazno",
+DlgImgAlignBottom : "Dno",
+DlgImgAlignMiddle : "Sredina",
+DlgImgAlignRight : "Desno",
+DlgImgAlignTextTop : "Vrh teksta",
+DlgImgAlignTop : "Vrh",
+DlgImgPreview : "Prikaz",
+DlgImgAlertUrl : "Molimo ukucajte URL od slike.",
+DlgImgLinkTab : "Link", //MISSING
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties", //MISSING
+DlgFlashChkPlay : "Auto Play", //MISSING
+DlgFlashChkLoop : "Loop", //MISSING
+DlgFlashChkMenu : "Enable Flash Menu", //MISSING
+DlgFlashScale : "Scale", //MISSING
+DlgFlashScaleAll : "Show all", //MISSING
+DlgFlashScaleNoBorder : "No Border", //MISSING
+DlgFlashScaleFit : "Exact Fit", //MISSING
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link info",
+DlgLnkTargetTab : "Prozor",
+
+DlgLnkType : "Tip linka",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Sidro na ovoj stranici",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<drugi>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Izaberi sidro",
+DlgLnkAnchorByName : "Po nazivu sidra",
+DlgLnkAnchorById : "Po Id-u elementa",
+DlgLnkNoAnchors : "<Nema dostupnih sidra na stranici>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Adresa",
+DlgLnkEMailSubject : "Subjekt poruke",
+DlgLnkEMailBody : "Poruka",
+DlgLnkUpload : "Šalji",
+DlgLnkBtnUpload : "Šalji na server",
+
+DlgLnkTarget : "Prozor",
+DlgLnkTargetFrame : "<frejm>",
+DlgLnkTargetPopup : "<popup prozor>",
+DlgLnkTargetBlank : "Novi prozor (_blank)",
+DlgLnkTargetParent : "Glavni prozor (_parent)",
+DlgLnkTargetSelf : "Isti prozor (_self)",
+DlgLnkTargetTop : "Najgornji prozor (_top)",
+DlgLnkTargetFrameName : "Target Frame Name", //MISSING
+DlgLnkPopWinName : "Naziv popup prozora",
+DlgLnkPopWinFeat : "Moguænosti popup prozora",
+DlgLnkPopResize : "Promjenljive velièine",
+DlgLnkPopLocation : "Traka za lokaciju",
+DlgLnkPopMenu : "Izborna traka",
+DlgLnkPopScroll : "Scroll traka",
+DlgLnkPopStatus : "Statusna traka",
+DlgLnkPopToolbar : "Traka sa alatima",
+DlgLnkPopFullScrn : "Cijeli ekran (IE)",
+DlgLnkPopDependent : "Ovisno (Netscape)",
+DlgLnkPopWidth : "Širina",
+DlgLnkPopHeight : "Visina",
+DlgLnkPopLeft : "Lijeva pozicija",
+DlgLnkPopTop : "Gornja pozicija",
+
+DlnLnkMsgNoUrl : "Molimo ukucajte URL link",
+DlnLnkMsgNoEMail : "Molimo ukucajte e-mail adresu",
+DlnLnkMsgNoAnchor : "Molimo izaberite sidro",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Izaberi boju",
+DlgColorBtnClear : "Oèisti",
+DlgColorHighlight : "Igled",
+DlgColorSelected : "Selektovana",
+
+// Smiley Dialog
+DlgSmileyTitle : "Ubaci smješka",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Izaberi specijalni karakter",
+
+// Table Dialog
+DlgTableTitle : "Svojstva tabele",
+DlgTableRows : "Redova",
+DlgTableColumns : "Kolona",
+DlgTableBorder : "Okvir",
+DlgTableAlign : "Poravnanje",
+DlgTableAlignNotSet : "<Nije podešeno>",
+DlgTableAlignLeft : "Lijevo",
+DlgTableAlignCenter : "Centar",
+DlgTableAlignRight : "Desno",
+DlgTableWidth : "Širina",
+DlgTableWidthPx : "piksela",
+DlgTableWidthPc : "posto",
+DlgTableHeight : "Visina",
+DlgTableCellSpace : "Razmak æelija",
+DlgTableCellPad : "Uvod æelija",
+DlgTableCaption : "Naslov",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Svojstva æelije",
+DlgCellWidth : "Širina",
+DlgCellWidthPx : "piksela",
+DlgCellWidthPc : "posto",
+DlgCellHeight : "Visina",
+DlgCellWordWrap : "Vrapuj tekst",
+DlgCellWordWrapNotSet : "<Nije podešeno>",
+DlgCellWordWrapYes : "Da",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Horizontalno poravnanje",
+DlgCellHorAlignNotSet : "<Nije podešeno>",
+DlgCellHorAlignLeft : "Lijevo",
+DlgCellHorAlignCenter : "Centar",
+DlgCellHorAlignRight: "Desno",
+DlgCellVerAlign : "Vertikalno poravnanje",
+DlgCellVerAlignNotSet : "<Nije podešeno>",
+DlgCellVerAlignTop : "Gore",
+DlgCellVerAlignMiddle : "Sredina",
+DlgCellVerAlignBottom : "Dno",
+DlgCellVerAlignBaseline : "Bazno",
+DlgCellRowSpan : "Spajanje æelija",
+DlgCellCollSpan : "Spajanje kolona",
+DlgCellBackColor : "Boja pozadine",
+DlgCellBorderColor : "Boja okvira",
+DlgCellBtnSelect : "Selektuj...",
+
+// Find Dialog
+DlgFindTitle : "Naði",
+DlgFindFindBtn : "Naði",
+DlgFindNotFoundMsg : "Traženi tekst nije pronaðen.",
+
+// Replace Dialog
+DlgReplaceTitle : "Zamjeni",
+DlgReplaceFindLbl : "Naði šta:",
+DlgReplaceReplaceLbl : "Zamjeni sa:",
+DlgReplaceCaseChk : "Uporeðuj velika/mala slova",
+DlgReplaceReplaceBtn : "Zamjeni",
+DlgReplaceReplAllBtn : "Zamjeni sve",
+DlgReplaceWordChk : "Uporeðuj samo cijelu rijeè",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Sigurnosne postavke vašeg pretraživaèa ne dozvoljavaju operacije automatskog rezanja. Molimo koristite kraticu na tastaturi (Ctrl+X).",
+PasteErrorCopy : "Sigurnosne postavke Vašeg pretraživaèa ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tastaturi (Ctrl+C).",
+
+PasteAsText : "Zalijepi kao obièan tekst",
+PasteFromWord : "Zalijepi iz Word-a",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.", //MISSING
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING
+DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING
+DlgPasteCleanBox : "Clean Up Box", //MISSING
+
+// Color Picker
+ColorAutomatic : "Automatska",
+ColorMoreColors : "Više boja...",
+
+// Document Properties
+DocProps : "Document Properties", //MISSING
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties", //MISSING
+DlgAnchorName : "Anchor Name", //MISSING
+DlgAnchorErrorName : "Please type the anchor name", //MISSING
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary", //MISSING
+DlgSpellChangeTo : "Change to", //MISSING
+DlgSpellBtnIgnore : "Ignore", //MISSING
+DlgSpellBtnIgnoreAll : "Ignore All", //MISSING
+DlgSpellBtnReplace : "Replace", //MISSING
+DlgSpellBtnReplaceAll : "Replace All", //MISSING
+DlgSpellBtnUndo : "Undo", //MISSING
+DlgSpellNoSuggestions : "- No suggestions -", //MISSING
+DlgSpellProgress : "Spell check in progress...", //MISSING
+DlgSpellNoMispell : "Spell check complete: No misspellings found", //MISSING
+DlgSpellNoChanges : "Spell check complete: No words changed", //MISSING
+DlgSpellOneChange : "Spell check complete: One word changed", //MISSING
+DlgSpellManyChanges : "Spell check complete: %1 words changed", //MISSING
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?", //MISSING
+
+// Button Dialog
+DlgButtonText : "Text (Value)", //MISSING
+DlgButtonType : "Type", //MISSING
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name", //MISSING
+DlgCheckboxValue : "Value", //MISSING
+DlgCheckboxSelected : "Selected", //MISSING
+
+// Form Dialog
+DlgFormName : "Name", //MISSING
+DlgFormAction : "Action", //MISSING
+DlgFormMethod : "Method", //MISSING
+
+// Select Field Dialog
+DlgSelectName : "Name", //MISSING
+DlgSelectValue : "Value", //MISSING
+DlgSelectSize : "Size", //MISSING
+DlgSelectLines : "lines", //MISSING
+DlgSelectChkMulti : "Allow multiple selections", //MISSING
+DlgSelectOpAvail : "Available Options", //MISSING
+DlgSelectOpText : "Text", //MISSING
+DlgSelectOpValue : "Value", //MISSING
+DlgSelectBtnAdd : "Add", //MISSING
+DlgSelectBtnModify : "Modify", //MISSING
+DlgSelectBtnUp : "Up", //MISSING
+DlgSelectBtnDown : "Down", //MISSING
+DlgSelectBtnSetValue : "Set as selected value", //MISSING
+DlgSelectBtnDelete : "Delete", //MISSING
+
+// Textarea Dialog
+DlgTextareaName : "Name", //MISSING
+DlgTextareaCols : "Columns", //MISSING
+DlgTextareaRows : "Rows", //MISSING
+
+// Text Field Dialog
+DlgTextName : "Name", //MISSING
+DlgTextValue : "Value", //MISSING
+DlgTextCharWidth : "Character Width", //MISSING
+DlgTextMaxChars : "Maximum Characters", //MISSING
+DlgTextType : "Type", //MISSING
+DlgTextTypeText : "Text", //MISSING
+DlgTextTypePass : "Password", //MISSING
+
+// Hidden Field Dialog
+DlgHiddenName : "Name", //MISSING
+DlgHiddenValue : "Value", //MISSING
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties", //MISSING
+NumberedListProp : "Numbered List Properties", //MISSING
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Type", //MISSING
+DlgLstTypeCircle : "Circle", //MISSING
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Square", //MISSING
+DlgLstTypeNumbers : "Numbers (1, 2, 3)", //MISSING
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)", //MISSING
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)", //MISSING
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", //MISSING
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", //MISSING
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General", //MISSING
+DlgDocBackTab : "Background", //MISSING
+DlgDocColorsTab : "Colors and Margins", //MISSING
+DlgDocMetaTab : "Meta Data", //MISSING
+
+DlgDocPageTitle : "Page Title", //MISSING
+DlgDocLangDir : "Language Direction", //MISSING
+DlgDocLangDirLTR : "Left to Right (LTR)", //MISSING
+DlgDocLangDirRTL : "Right to Left (RTL)", //MISSING
+DlgDocLangCode : "Language Code", //MISSING
+DlgDocCharSet : "Character Set Encoding", //MISSING
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Other Character Set Encoding", //MISSING
+
+DlgDocDocType : "Document Type Heading", //MISSING
+DlgDocDocTypeOther : "Other Document Type Heading", //MISSING
+DlgDocIncXHTML : "Include XHTML Declarations", //MISSING
+DlgDocBgColor : "Background Color", //MISSING
+DlgDocBgImage : "Background Image URL", //MISSING
+DlgDocBgNoScroll : "Nonscrolling Background", //MISSING
+DlgDocCText : "Text", //MISSING
+DlgDocCLink : "Link", //MISSING
+DlgDocCVisited : "Visited Link", //MISSING
+DlgDocCActive : "Active Link", //MISSING
+DlgDocMargins : "Page Margins", //MISSING
+DlgDocMaTop : "Top", //MISSING
+DlgDocMaLeft : "Left", //MISSING
+DlgDocMaRight : "Right", //MISSING
+DlgDocMaBottom : "Bottom", //MISSING
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)", //MISSING
+DlgDocMeDescr : "Document Description", //MISSING
+DlgDocMeAuthor : "Author", //MISSING
+DlgDocMeCopy : "Copyright", //MISSING
+DlgDocPreview : "Preview", //MISSING
+
+// Templates Dialog
+Templates : "Templates", //MISSING
+DlgTemplatesTitle : "Content Templates", //MISSING
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br />(the actual contents will be lost):", //MISSING
+DlgTemplatesLoading : "Loading templates list. Please wait...", //MISSING
+DlgTemplatesNoTpl : "(No templates defined)", //MISSING
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "About", //MISSING
+DlgAboutBrowserInfoTab : "Browser Info", //MISSING
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "verzija",
+DlgAboutInfo : "Za više informacija posjetite"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ca.js b/httemplate/elements/fckeditor/editor/lang/ca.js
new file mode 100644
index 000000000..c3859cd49
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ca.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Catalan language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Col·lapsa la barra",
+ToolbarExpand : "Amplia la barra",
+
+// Toolbar Items and Context Menu
+Save : "Desa",
+NewPage : "Nova Pàgina",
+Preview : "Vista Prèvia",
+Cut : "Retalla",
+Copy : "Copia",
+Paste : "Enganxa",
+PasteText : "Enganxa com a text no formatat",
+PasteWord : "Enganxa des del Word",
+Print : "Imprimeix",
+SelectAll : "Selecciona-ho tot",
+RemoveFormat : "Elimina Format",
+InsertLinkLbl : "Enllaç",
+InsertLink : "Insereix/Edita enllaç",
+RemoveLink : "Elimina enllaç",
+Anchor : "Insereix/Edita àncora",
+InsertImageLbl : "Imatge",
+InsertImage : "Insereix/Edita imatge",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insereix/Edita Flash",
+InsertTableLbl : "Taula",
+InsertTable : "Insereix/Edita taula",
+InsertLineLbl : "Línia",
+InsertLine : "Insereix línia horitzontal",
+InsertSpecialCharLbl: "Caràcter Especial",
+InsertSpecialChar : "Insereix caràcter especial",
+InsertSmileyLbl : "Icona",
+InsertSmiley : "Insereix icona",
+About : "Quant a FCKeditor",
+Bold : "Negreta",
+Italic : "Cursiva",
+Underline : "Subratllat",
+StrikeThrough : "Barrat",
+Subscript : "Subíndex",
+Superscript : "Superíndex",
+LeftJustify : "Aliniament esquerra",
+CenterJustify : "Aliniament centrat",
+RightJustify : "Aliniament dreta",
+BlockJustify : "Justifica",
+DecreaseIndent : "Sagna el text",
+IncreaseIndent : "Treu el sagnat del text",
+Undo : "Desfés",
+Redo : "Refés",
+NumberedListLbl : "Llista numerada",
+NumberedList : "Aplica o elimina la llista numerada",
+BulletedListLbl : "Llista de pics",
+BulletedList : "Aplica o elimina la llista de pics",
+ShowTableBorders : "Mostra les vores de les taules",
+ShowDetails : "Mostra detalls",
+Style : "Estil",
+FontFormat : "Format",
+Font : "Tipus de lletra",
+FontSize : "Mida",
+TextColor : "Color de Text",
+BGColor : "Color de Fons",
+Source : "Codi font",
+Find : "Cerca",
+Replace : "Reemplaça",
+SpellCheck : "Revisa l'ortografia",
+UniversalKeyboard : "Teclat universal",
+PageBreakLbl : "Salt de pàgina",
+PageBreak : "Insereix salt de pàgina",
+
+Form : "Formulari",
+Checkbox : "Casella de verificació",
+RadioButton : "Botó d'opció",
+TextField : "Camp de text",
+Textarea : "Àrea de text",
+HiddenField : "Camp ocult",
+Button : "Botó",
+SelectionField : "Camp de selecció",
+ImageButton : "Botó d'imatge",
+
+FitWindow : "Maximiza la mida de l'editor",
+
+// Context Menu
+EditLink : "Edita l'enllaç",
+CellCM : "Cel·la",
+RowCM : "Fila",
+ColumnCM : "Columna",
+InsertRow : "Insereix una fila",
+DeleteRows : "Suprimeix una fila",
+InsertColumn : "Afegeix una columna",
+DeleteColumns : "Suprimeix una columna",
+InsertCell : "Insereix una cel·la",
+DeleteCells : "Suprimeix les cel·les",
+MergeCells : "Fusiona les cel·les",
+SplitCell : "Separa les cel·les",
+TableDelete : "Suprimeix la taula",
+CellProperties : "Propietats de la cel·la",
+TableProperties : "Propietats de la taula",
+ImageProperties : "Propietats de la imatge",
+FlashProperties : "Propietats del Flash",
+
+AnchorProp : "Propietats de l'àncora",
+ButtonProp : "Propietats del botó",
+CheckboxProp : "Propietats de la casella de verificació",
+HiddenFieldProp : "Propietats del camp ocult",
+RadioButtonProp : "Propietats del botó d'opció",
+ImageButtonProp : "Propietats del botó d'imatge",
+TextFieldProp : "Propietats del camp de text",
+SelectionFieldProp : "Propietats del camp de selecció",
+TextareaProp : "Propietats de l'àrea de text",
+FormProp : "Propietats del formulari",
+
+FontFormats : "Normal;Formatejat;Adreça;Encapçalament 1;Encapçalament 2;Encapçalament 3;Encapçalament 4;Encapçalament 5;Encapçalament 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processant XHTML. Si us plau esperi...",
+Done : "Fet",
+PasteWordConfirm : "El text que voleu enganxar sembla provenir de Word. Voleu netejar aquest text abans que sigui enganxat?",
+NotCompatiblePaste : "Aquesta funció és disponible per a Internet Explorer versió 5.5 o superior. Voleu enganxar sense netejar?",
+UnknownToolbarItem : "Element de la barra d'eines desconegut \"%1\"",
+UnknownCommand : "Nom de comanda desconegut \"%1\"",
+NotImplemented : "Mètode no implementat",
+UnknownToolbarSet : "Conjunt de barra d'eines \"%1\" inexistent",
+NoActiveX : "Les preferències del navegador poden limitar algunes funcions d'aquest editor. Cal habilitar l'opció \"Executa controls ActiveX i plug-ins\". Poden sorgir errors i poden faltar algunes funcions.",
+BrowseServerBlocked : "El visualitzador de recursos no s'ha pogut obrir. Assegura't de que els bloquejos de finestres emergents estan desactivats.",
+DialogBlocked : "No ha estat possible obrir una finestra de diàleg. Assegura't de que els bloquejos de finestres emergents estan desactivats.",
+
+// Dialogs
+DlgBtnOK : "D'acord",
+DlgBtnCancel : "Cancel·la",
+DlgBtnClose : "Tanca",
+DlgBtnBrowseServer : "Veure servidor",
+DlgAdvancedTag : "Avançat",
+DlgOpOther : "Altres",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Si us plau, afegiu la URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<no definit>",
+DlgGenId : "Id",
+DlgGenLangDir : "Direcció de l'idioma",
+DlgGenLangDirLtr : "D'esquerra a dreta (LTR)",
+DlgGenLangDirRtl : "De dreta a esquerra (RTL)",
+DlgGenLangCode : "Codi d'idioma",
+DlgGenAccessKey : "Clau d'accés",
+DlgGenName : "Nom",
+DlgGenTabIndex : "Index de Tab",
+DlgGenLongDescr : "Descripció llarga de la URL",
+DlgGenClass : "Classes del full d'estil",
+DlgGenTitle : "Títol consultiu",
+DlgGenContType : "Tipus de contingut consultiu",
+DlgGenLinkCharset : "Conjunt de caràcters font enllaçat",
+DlgGenStyle : "Estil",
+
+// Image Dialog
+DlgImgTitle : "Propietats de la imatge",
+DlgImgInfoTab : "Informació de la imatge",
+DlgImgBtnUpload : "Envia-la al servidor",
+DlgImgURL : "URL",
+DlgImgUpload : "Puja",
+DlgImgAlt : "Text alternatiu",
+DlgImgWidth : "Amplada",
+DlgImgHeight : "Alçada",
+DlgImgLockRatio : "Bloqueja les proporcions",
+DlgBtnResetSize : "Restaura la mida",
+DlgImgBorder : "Vora",
+DlgImgHSpace : "Espaiat horit.",
+DlgImgVSpace : "Espaiat vert.",
+DlgImgAlign : "Alineació",
+DlgImgAlignLeft : "Ajusta a l'esquerra",
+DlgImgAlignAbsBottom: "Abs Bottom",
+DlgImgAlignAbsMiddle: "Abs Middle",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Bottom",
+DlgImgAlignMiddle : "Middle",
+DlgImgAlignRight : "Ajusta a la dreta",
+DlgImgAlignTextTop : "Text Top",
+DlgImgAlignTop : "Top",
+DlgImgPreview : "Vista prèvia",
+DlgImgAlertUrl : "Si us plau, escriviu la URL de la imatge",
+DlgImgLinkTab : "Enllaç",
+
+// Flash Dialog
+DlgFlashTitle : "Propietats del Flash",
+DlgFlashChkPlay : "Reprodució automàtica",
+DlgFlashChkLoop : "Bucle",
+DlgFlashChkMenu : "Habilita menú Flash",
+DlgFlashScale : "Escala",
+DlgFlashScaleAll : "Mostra-ho tot",
+DlgFlashScaleNoBorder : "Sense vores",
+DlgFlashScaleFit : "Mida exacta",
+
+// Link Dialog
+DlgLnkWindowTitle : "Enllaç",
+DlgLnkInfoTab : "Informació de l'enllaç",
+DlgLnkTargetTab : "Destí",
+
+DlgLnkType : "Tipus d'enllaç",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Àncora en aquesta pàgina",
+DlgLnkTypeEMail : "Correu electrònic",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<altra>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Selecciona una àncora",
+DlgLnkAnchorByName : "Per nom d'àncora",
+DlgLnkAnchorById : "Per Id d'element",
+DlgLnkNoAnchors : "(No hi ha àncores disponibles en aquest document)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Adreça de correu electrònic",
+DlgLnkEMailSubject : "Assumpte del missatge",
+DlgLnkEMailBody : "Cos del missatge",
+DlgLnkUpload : "Puja",
+DlgLnkBtnUpload : "Envia al servidor",
+
+DlgLnkTarget : "Destí",
+DlgLnkTargetFrame : "<marc>",
+DlgLnkTargetPopup : "<finestra emergent>",
+DlgLnkTargetBlank : "Nova finestra (_blank)",
+DlgLnkTargetParent : "Finestra pare (_parent)",
+DlgLnkTargetSelf : "Mateixa finestra (_self)",
+DlgLnkTargetTop : "Finestra Major (_top)",
+DlgLnkTargetFrameName : "Nom del marc de destí",
+DlgLnkPopWinName : "Nom finestra popup",
+DlgLnkPopWinFeat : "Característiques finestra popup",
+DlgLnkPopResize : "Redimensionable",
+DlgLnkPopLocation : "Barra d'adreça",
+DlgLnkPopMenu : "Barra de menú",
+DlgLnkPopScroll : "Barres d'scroll",
+DlgLnkPopStatus : "Barra d'estat",
+DlgLnkPopToolbar : "Barra d'eines",
+DlgLnkPopFullScrn : "Pantalla completa (IE)",
+DlgLnkPopDependent : "Depenent (Netscape)",
+DlgLnkPopWidth : "Amplada",
+DlgLnkPopHeight : "Alçada",
+DlgLnkPopLeft : "Posició esquerra",
+DlgLnkPopTop : "Posició dalt",
+
+DlnLnkMsgNoUrl : "Si us plau, escrigui l'enllaç URL",
+DlnLnkMsgNoEMail : "Si us plau, escrigui l'adreça correu electrònic",
+DlnLnkMsgNoAnchor : "Si us plau, escrigui l'àncora",
+DlnLnkMsgInvPopName : "El nom de la finestra emergent ha de començar amb una lletra i no pot tenir espais",
+
+// Color Dialog
+DlgColorTitle : "Selecciona el color",
+DlgColorBtnClear : "Neteja",
+DlgColorHighlight : "Realça",
+DlgColorSelected : "Selecciona",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insereix una icona",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Selecciona el caràcter especial",
+
+// Table Dialog
+DlgTableTitle : "Propietats de la taula",
+DlgTableRows : "Files",
+DlgTableColumns : "Columnes",
+DlgTableBorder : "Mida vora",
+DlgTableAlign : "Alineació",
+DlgTableAlignNotSet : "<No Definit>",
+DlgTableAlignLeft : "Esquerra",
+DlgTableAlignCenter : "Centre",
+DlgTableAlignRight : "Dreta",
+DlgTableWidth : "Amplada",
+DlgTableWidthPx : "píxels",
+DlgTableWidthPc : "percentatge",
+DlgTableHeight : "Alçada",
+DlgTableCellSpace : "Espaiat de cel·les",
+DlgTableCellPad : "Encoixinament de cel·les",
+DlgTableCaption : "Títol",
+DlgTableSummary : "Resum",
+
+// Table Cell Dialog
+DlgCellTitle : "Propietats de la cel·la",
+DlgCellWidth : "Amplada",
+DlgCellWidthPx : "píxels",
+DlgCellWidthPc : "percentatge",
+DlgCellHeight : "Alçada",
+DlgCellWordWrap : "Ajust de paraula",
+DlgCellWordWrapNotSet : "<No Definit>",
+DlgCellWordWrapYes : "Si",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Alineació horitzontal",
+DlgCellHorAlignNotSet : "<No Definit>",
+DlgCellHorAlignLeft : "Esquerra",
+DlgCellHorAlignCenter : "Centre",
+DlgCellHorAlignRight: "Dreta",
+DlgCellVerAlign : "Alineació vertical",
+DlgCellVerAlignNotSet : "<No definit>",
+DlgCellVerAlignTop : "Top",
+DlgCellVerAlignMiddle : "Middle",
+DlgCellVerAlignBottom : "Bottom",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rows Span",
+DlgCellCollSpan : "Columns Span",
+DlgCellBackColor : "Color de fons",
+DlgCellBorderColor : "Color de la vora",
+DlgCellBtnSelect : "Seleccioneu...",
+
+// Find Dialog
+DlgFindTitle : "Cerca",
+DlgFindFindBtn : "Cerca",
+DlgFindNotFoundMsg : "El text especificat no s'ha trobat.",
+
+// Replace Dialog
+DlgReplaceTitle : "Reemplaça",
+DlgReplaceFindLbl : "Cerca:",
+DlgReplaceReplaceLbl : "Remplaça amb:",
+DlgReplaceCaseChk : "Distingeix majúscules/minúscules",
+DlgReplaceReplaceBtn : "Reemplaça",
+DlgReplaceReplAllBtn : "Reemplaça-ho tot",
+DlgReplaceWordChk : "Només paraules completes",
+
+// Paste Operations / Dialog
+PasteErrorCut : "La seguretat del vostre navegador no permet executar automàticament les operacions de retallar. Si us plau, utilitzeu el teclat (Ctrl+X).",
+PasteErrorCopy : "La seguretat del vostre navegador no permet executar automàticament les operacions de copiar. Si us plau, utilitzeu el teclat (Ctrl+C).",
+
+PasteAsText : "Enganxa com a text no formatat",
+PasteFromWord : "Enganxa com a Word",
+
+DlgPasteMsg2 : "Si us plau, enganxeu dins del següent camp utilitzant el teclat (<STRONG>Ctrl+V</STRONG>) i premeu <STRONG>OK</STRONG>.",
+DlgPasteSec : "A causa de la configuració de seguretat del vostre navegador, l'editor no pot accedir al porta-retalls directament. Enganxeu-ho un altre cop en aquesta finestra.",
+DlgPasteIgnoreFont : "Ignora definicions de font",
+DlgPasteRemoveStyles : "Elimina definicions d'estil",
+DlgPasteCleanBox : "Neteja camp",
+
+// Color Picker
+ColorAutomatic : "Automàtic",
+ColorMoreColors : "Més colors...",
+
+// Document Properties
+DocProps : "Propietats del document",
+
+// Anchor Dialog
+DlgAnchorTitle : "Propietats de l'àncora",
+DlgAnchorName : "Nom de l'àncora",
+DlgAnchorErrorName : "Si us plau, escriviu el nom de l'ancora",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "No és al diccionari",
+DlgSpellChangeTo : "Canvia a",
+DlgSpellBtnIgnore : "Ignora",
+DlgSpellBtnIgnoreAll : "Ignora-les totes",
+DlgSpellBtnReplace : "Canvia",
+DlgSpellBtnReplaceAll : "Canvia-les totes",
+DlgSpellBtnUndo : "Desfés",
+DlgSpellNoSuggestions : "Cap sugerència",
+DlgSpellProgress : "Comprovació ortogràfica en progrés",
+DlgSpellNoMispell : "Comprovació ortogràfica completada",
+DlgSpellNoChanges : "Comprovació ortogràfica: cap paraulada canviada",
+DlgSpellOneChange : "Comprovació ortogràfica: una paraula canviada",
+DlgSpellManyChanges : "Comprovació ortogràfica %1 paraules canviades",
+
+IeSpellDownload : "Comprovació ortogràfica no instal·lada. Voleu descarregar-ho ara?",
+
+// Button Dialog
+DlgButtonText : "Text (Valor)",
+DlgButtonType : "Tipus",
+DlgButtonTypeBtn : "Botó",
+DlgButtonTypeSbm : "Transmet formulari",
+DlgButtonTypeRst : "Reinicia formulari",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nom",
+DlgCheckboxValue : "Valor",
+DlgCheckboxSelected : "Seleccionat",
+
+// Form Dialog
+DlgFormName : "Nom",
+DlgFormAction : "Acció",
+DlgFormMethod : "Mètode",
+
+// Select Field Dialog
+DlgSelectName : "Nom",
+DlgSelectValue : "Valor",
+DlgSelectSize : "Mida",
+DlgSelectLines : "Línies",
+DlgSelectChkMulti : "Permet múltiples seleccions",
+DlgSelectOpAvail : "Opcions disponibles",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Valor",
+DlgSelectBtnAdd : "Afegeix",
+DlgSelectBtnModify : "Modifica",
+DlgSelectBtnUp : "Amunt",
+DlgSelectBtnDown : "Avall",
+DlgSelectBtnSetValue : "Selecciona per defecte",
+DlgSelectBtnDelete : "Elimina",
+
+// Textarea Dialog
+DlgTextareaName : "Nom",
+DlgTextareaCols : "Columnes",
+DlgTextareaRows : "Files",
+
+// Text Field Dialog
+DlgTextName : "Nom",
+DlgTextValue : "Valor",
+DlgTextCharWidth : "Amplada de caràcter",
+DlgTextMaxChars : "Màxim de caràcters",
+DlgTextType : "Tipus",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Contrasenya",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nom",
+DlgHiddenValue : "Valor",
+
+// Bulleted List Dialog
+BulletedListProp : "Propietats de la llista de pics",
+NumberedListProp : "Propietats de llista numerada",
+DlgLstStart : "Inici",
+DlgLstType : "Tipus",
+DlgLstTypeCircle : "Cercle",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Quadrat",
+DlgLstTypeNumbers : "Números (1, 2, 3)",
+DlgLstTypeLCase : "Lletres minúscules (a, b, c)",
+DlgLstTypeUCase : "Lletres majúscules (A, B, C)",
+DlgLstTypeSRoman : "Números romans minúscules (i, ii, iii)",
+DlgLstTypeLRoman : "Números romans majúscules (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Fons",
+DlgDocColorsTab : "Colors i marges",
+DlgDocMetaTab : "Dades Meta",
+
+DlgDocPageTitle : "Títol de la pàgina",
+DlgDocLangDir : "Direcció idioma",
+DlgDocLangDirLTR : "Esquerra a dreta (LTR)",
+DlgDocLangDirRTL : "Dreta a esquerra (RTL)",
+DlgDocLangCode : "Codi d'idioma",
+DlgDocCharSet : "Codificació de conjunt de caràcters",
+DlgDocCharSetCE : "Centreeuropeu",
+DlgDocCharSetCT : "Xinès tradicional (Big5)",
+DlgDocCharSetCR : "Ciríl·lic",
+DlgDocCharSetGR : "Grec",
+DlgDocCharSetJP : "Japonès",
+DlgDocCharSetKR : "Coreà",
+DlgDocCharSetTR : "Turc",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Europeu occidental",
+DlgDocCharSetOther : "Una altra codificació de caràcters",
+
+DlgDocDocType : "Capçalera de tipus de document",
+DlgDocDocTypeOther : "Un altra capçalera de tipus de document",
+DlgDocIncXHTML : "Incloure declaracions XHTML",
+DlgDocBgColor : "Color de fons",
+DlgDocBgImage : "URL de la imatge de fons",
+DlgDocBgNoScroll : "Fons fixe",
+DlgDocCText : "Text",
+DlgDocCLink : "Enllaç",
+DlgDocCVisited : "Enllaç visitat",
+DlgDocCActive : "Enllaç actiu",
+DlgDocMargins : "Marges de pàgina",
+DlgDocMaTop : "Cap",
+DlgDocMaLeft : "Esquerra",
+DlgDocMaRight : "Dreta",
+DlgDocMaBottom : "Peu",
+DlgDocMeIndex : "Mots clau per a indexació (separats per coma)",
+DlgDocMeDescr : "Descripció del document",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Vista prèvia",
+
+// Templates Dialog
+Templates : "Plantilles",
+DlgTemplatesTitle : "Contingut plantilles",
+DlgTemplatesSelMsg : "Si us plau, seleccioneu la plantilla per obrir en l'editor<br>(el contingut actual no serà enregistrat):",
+DlgTemplatesLoading : "Carregant la llista de plantilles. Si us plau, espereu...",
+DlgTemplatesNoTpl : "(No hi ha plantilles definides)",
+DlgTemplatesReplace : "Reemplaça el contingut actual",
+
+// About Dialog
+DlgAboutAboutTab : "Quant a",
+DlgAboutBrowserInfoTab : "Informació del navegador",
+DlgAboutLicenseTab : "Llicència",
+DlgAboutVersion : "versió",
+DlgAboutInfo : "Per a més informació aneu a"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/cs.js b/httemplate/elements/fckeditor/editor/lang/cs.js
new file mode 100644
index 000000000..49b5f87c0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/cs.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Czech language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skrýt panel nástrojů",
+ToolbarExpand : "Zobrazit panel nástrojů",
+
+// Toolbar Items and Context Menu
+Save : "Uložit",
+NewPage : "Nová stránka",
+Preview : "Náhled",
+Cut : "Vyjmout",
+Copy : "Kopírovat",
+Paste : "Vložit",
+PasteText : "Vložit jako čistý text",
+PasteWord : "Vložit z Wordu",
+Print : "Tisk",
+SelectAll : "Vybrat vše",
+RemoveFormat : "Odstranit formátování",
+InsertLinkLbl : "Odkaz",
+InsertLink : "Vložit/změnit odkaz",
+RemoveLink : "Odstranit odkaz",
+Anchor : "Vložít/změnit záložku",
+InsertImageLbl : "Obrázek",
+InsertImage : "Vložit/změnit obrázek",
+InsertFlashLbl : "Flash",
+InsertFlash : "Vložit/Upravit Flash",
+InsertTableLbl : "Tabulka",
+InsertTable : "Vložit/změnit tabulku",
+InsertLineLbl : "Linka",
+InsertLine : "Vložit vodorovnou linku",
+InsertSpecialCharLbl: "Speciální znaky",
+InsertSpecialChar : "Vložit speciální znaky",
+InsertSmileyLbl : "Smajlíky",
+InsertSmiley : "Vložit smajlík",
+About : "O aplikaci FCKeditor",
+Bold : "Tučné",
+Italic : "Kurzíva",
+Underline : "Podtržené",
+StrikeThrough : "Přeškrtnuté",
+Subscript : "Dolní index",
+Superscript : "Horní index",
+LeftJustify : "Zarovnat vlevo",
+CenterJustify : "Zarovnat na střed",
+RightJustify : "Zarovnat vpravo",
+BlockJustify : "Zarovnat do bloku",
+DecreaseIndent : "Zmenšit odsazení",
+IncreaseIndent : "Zvětšit odsazení",
+Undo : "Zpět",
+Redo : "Znovu",
+NumberedListLbl : "Číslování",
+NumberedList : "Vložit/odstranit číslovaný seznam",
+BulletedListLbl : "Odrážky",
+BulletedList : "Vložit/odstranit odrážky",
+ShowTableBorders : "Zobrazit okraje tabulek",
+ShowDetails : "Zobrazit podrobnosti",
+Style : "Styl",
+FontFormat : "Formát",
+Font : "Písmo",
+FontSize : "Velikost",
+TextColor : "Barva textu",
+BGColor : "Barva pozadí",
+Source : "Zdroj",
+Find : "Hledat",
+Replace : "Nahradit",
+SpellCheck : "Zkontrolovat pravopis",
+UniversalKeyboard : "Univerzální klávesnice",
+PageBreakLbl : "Konec stránky",
+PageBreak : "Vložit konec stránky",
+
+Form : "Formulář",
+Checkbox : "Zaškrtávací políčko",
+RadioButton : "Přepínač",
+TextField : "Textové pole",
+Textarea : "Textová oblast",
+HiddenField : "Skryté pole",
+Button : "Tlačítko",
+SelectionField : "Seznam",
+ImageButton : "Obrázkové tlačítko",
+
+FitWindow : "Maximalizovat velikost editoru",
+
+// Context Menu
+EditLink : "Změnit odkaz",
+CellCM : "Buňka",
+RowCM : "Řádek",
+ColumnCM : "Sloupec",
+InsertRow : "Vložit řádek",
+DeleteRows : "Smazat řádek",
+InsertColumn : "Vložit sloupec",
+DeleteColumns : "Smazat sloupec",
+InsertCell : "Vložit buňku",
+DeleteCells : "Smazat buňky",
+MergeCells : "Sloučit buňky",
+SplitCell : "Rozdělit buňku",
+TableDelete : "Smazat tabulku",
+CellProperties : "Vlastnosti buňky",
+TableProperties : "Vlastnosti tabulky",
+ImageProperties : "Vlastnosti obrázku",
+FlashProperties : "Vlastnosti Flashe",
+
+AnchorProp : "Vlastnosti záložky",
+ButtonProp : "Vlastnosti tlačítka",
+CheckboxProp : "Vlastnosti zaškrtávacího políčka",
+HiddenFieldProp : "Vlastnosti skrytého pole",
+RadioButtonProp : "Vlastnosti přepínače",
+ImageButtonProp : "Vlastností obrázkového tlačítka",
+TextFieldProp : "Vlastnosti textového pole",
+SelectionFieldProp : "Vlastnosti seznamu",
+TextareaProp : "Vlastnosti textové oblasti",
+FormProp : "Vlastnosti formuláře",
+
+FontFormats : "Normální;Formátovaný;Adresa;Nadpis 1;Nadpis 2;Nadpis 3;Nadpis 4;Nadpis 5;Nadpis 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Probíhá zpracování XHTML. Prosím čekejte...",
+Done : "Hotovo",
+PasteWordConfirm : "Jak je vidět, vkládaný text je kopírován z Wordu. Chcete jej před vložením vyčistit?",
+NotCompatiblePaste : "Tento příkaz je dostupný pouze v Internet Exploreru verze 5.5 nebo vyšší. Chcete vložit text bez vyčištění?",
+UnknownToolbarItem : "Neznámá položka panelu nástrojů \"%1\"",
+UnknownCommand : "Neznámý příkaz \"%1\"",
+NotImplemented : "Příkaz není implementován",
+UnknownToolbarSet : "Panel nástrojů \"%1\" neexistuje",
+NoActiveX : "Nastavení bezpečnosti Vašeho prohlížeče omezuje funkčnost některých jeho možností. Je třeba zapnout volbu \"Spouštět ovládáací prvky ActiveX a moduly plug-in\", jinak nebude možné využívat všechny dosputné schopnosti editoru.",
+BrowseServerBlocked : "Průzkumník zdrojů nelze otevřít. Prověřte, zda nemáte aktivováno blokování popup oken.",
+DialogBlocked : "Nelze otevřít dialogové okno. Prověřte, zda nemáte aktivováno blokování popup oken.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Storno",
+DlgBtnClose : "Zavřít",
+DlgBtnBrowseServer : "Vybrat na serveru",
+DlgAdvancedTag : "Rozšířené",
+DlgOpOther : "<Ostatní>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Prosím vložte URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nenastaveno>",
+DlgGenId : "Id",
+DlgGenLangDir : "Orientace jazyka",
+DlgGenLangDirLtr : "Zleva do prava (LTR)",
+DlgGenLangDirRtl : "Zprava do leva (RTL)",
+DlgGenLangCode : "Kód jazyka",
+DlgGenAccessKey : "Přístupový klíč",
+DlgGenName : "Jméno",
+DlgGenTabIndex : "Pořadí prvku",
+DlgGenLongDescr : "Dlouhý popis URL",
+DlgGenClass : "Třída stylu",
+DlgGenTitle : "Pomocný titulek",
+DlgGenContType : "Pomocný typ obsahu",
+DlgGenLinkCharset : "Přiřazená znaková sada",
+DlgGenStyle : "Styl",
+
+// Image Dialog
+DlgImgTitle : "Vlastnosti obrázku",
+DlgImgInfoTab : "Informace o obrázku",
+DlgImgBtnUpload : "Odeslat na server",
+DlgImgURL : "URL",
+DlgImgUpload : "Odeslat",
+DlgImgAlt : "Alternativní text",
+DlgImgWidth : "Šířka",
+DlgImgHeight : "Výška",
+DlgImgLockRatio : "Zámek",
+DlgBtnResetSize : "Původní velikost",
+DlgImgBorder : "Okraje",
+DlgImgHSpace : "H-mezera",
+DlgImgVSpace : "V-mezera",
+DlgImgAlign : "Zarovnání",
+DlgImgAlignLeft : "Vlevo",
+DlgImgAlignAbsBottom: "Zcela dolů",
+DlgImgAlignAbsMiddle: "Doprostřed",
+DlgImgAlignBaseline : "Na účaří",
+DlgImgAlignBottom : "Dolů",
+DlgImgAlignMiddle : "Na střed",
+DlgImgAlignRight : "Vpravo",
+DlgImgAlignTextTop : "Na horní okraj textu",
+DlgImgAlignTop : "Nahoru",
+DlgImgPreview : "Náhled",
+DlgImgAlertUrl : "Zadejte prosím URL obrázku",
+DlgImgLinkTab : "Odkaz",
+
+// Flash Dialog
+DlgFlashTitle : "Vlastnosti Flashe",
+DlgFlashChkPlay : "Automatické spuštění",
+DlgFlashChkLoop : "Opakování",
+DlgFlashChkMenu : "Nabídka Flash",
+DlgFlashScale : "Zobrazit",
+DlgFlashScaleAll : "Zobrazit vše",
+DlgFlashScaleNoBorder : "Bez okraje",
+DlgFlashScaleFit : "Přizpůsobit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Odkaz",
+DlgLnkInfoTab : "Informace o odkazu",
+DlgLnkTargetTab : "Cíl",
+
+DlgLnkType : "Typ odkazu",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Kotva v této stránce",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<jiný>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Vybrat kotvu",
+DlgLnkAnchorByName : "Podle jména kotvy",
+DlgLnkAnchorById : "Podle Id objektu",
+DlgLnkNoAnchors : "<Ve stránce žádná kotva není definována>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mailová adresa",
+DlgLnkEMailSubject : "Předmět zprávy",
+DlgLnkEMailBody : "Tělo zprávy",
+DlgLnkUpload : "Odeslat",
+DlgLnkBtnUpload : "Odeslat na Server",
+
+DlgLnkTarget : "Cíl",
+DlgLnkTargetFrame : "<rámec>",
+DlgLnkTargetPopup : "<vyskakovací okno>",
+DlgLnkTargetBlank : "Nové okno (_blank)",
+DlgLnkTargetParent : "Rodičovské okno (_parent)",
+DlgLnkTargetSelf : "Stejné okno (_self)",
+DlgLnkTargetTop : "Hlavní okno (_top)",
+DlgLnkTargetFrameName : "Název cílového rámu",
+DlgLnkPopWinName : "Název vyskakovacího okna",
+DlgLnkPopWinFeat : "Vlastnosti vyskakovacího okna",
+DlgLnkPopResize : "Měnitelná velikost",
+DlgLnkPopLocation : "Panel umístění",
+DlgLnkPopMenu : "Panel nabídky",
+DlgLnkPopScroll : "Posuvníky",
+DlgLnkPopStatus : "Stavový řádek",
+DlgLnkPopToolbar : "Panel nástrojů",
+DlgLnkPopFullScrn : "Celá obrazovka (IE)",
+DlgLnkPopDependent : "Závislost (Netscape)",
+DlgLnkPopWidth : "Šířka",
+DlgLnkPopHeight : "Výška",
+DlgLnkPopLeft : "Levý okraj",
+DlgLnkPopTop : "Horní okraj",
+
+DlnLnkMsgNoUrl : "Zadejte prosím URL odkazu",
+DlnLnkMsgNoEMail : "Zadejte prosím e-mailovou adresu",
+DlnLnkMsgNoAnchor : "Vyberte prosím kotvu",
+DlnLnkMsgInvPopName : "Název vyskakovacího okna musí začínat písmenem a nesmí obsahovat mezery",
+
+// Color Dialog
+DlgColorTitle : "Výběr barvy",
+DlgColorBtnClear : "Vymazat",
+DlgColorHighlight : "Zvýrazněná",
+DlgColorSelected : "Vybraná",
+
+// Smiley Dialog
+DlgSmileyTitle : "Vkládání smajlíků",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Výběr speciálního znaku",
+
+// Table Dialog
+DlgTableTitle : "Vlastnosti tabulky",
+DlgTableRows : "Řádky",
+DlgTableColumns : "Sloupce",
+DlgTableBorder : "Ohraničení",
+DlgTableAlign : "Zarovnání",
+DlgTableAlignNotSet : "<nenastaveno>",
+DlgTableAlignLeft : "Vlevo",
+DlgTableAlignCenter : "Na střed",
+DlgTableAlignRight : "Vpravo",
+DlgTableWidth : "Šířka",
+DlgTableWidthPx : "bodů",
+DlgTableWidthPc : "procent",
+DlgTableHeight : "Výška",
+DlgTableCellSpace : "Vzdálenost buněk",
+DlgTableCellPad : "Odsazení obsahu",
+DlgTableCaption : "Popis",
+DlgTableSummary : "Souhrn",
+
+// Table Cell Dialog
+DlgCellTitle : "Vlastnosti buňky",
+DlgCellWidth : "Šířka",
+DlgCellWidthPx : "bodů",
+DlgCellWidthPc : "procent",
+DlgCellHeight : "Výška",
+DlgCellWordWrap : "Zalamování",
+DlgCellWordWrapNotSet : "<nenanstaveno>",
+DlgCellWordWrapYes : "Ano",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Vodorovné zarovnání",
+DlgCellHorAlignNotSet : "<nenastaveno>",
+DlgCellHorAlignLeft : "Vlevo",
+DlgCellHorAlignCenter : "Na střed",
+DlgCellHorAlignRight: "Vpravo",
+DlgCellVerAlign : "Svislé zarovnání",
+DlgCellVerAlignNotSet : "<nenastaveno>",
+DlgCellVerAlignTop : "Nahoru",
+DlgCellVerAlignMiddle : "Doprostřed",
+DlgCellVerAlignBottom : "Dolů",
+DlgCellVerAlignBaseline : "Na účaří",
+DlgCellRowSpan : "Sloučené řádky",
+DlgCellCollSpan : "Sloučené sloupce",
+DlgCellBackColor : "Barva pozadí",
+DlgCellBorderColor : "Barva ohraničení",
+DlgCellBtnSelect : "Výběr...",
+
+// Find Dialog
+DlgFindTitle : "Hledat",
+DlgFindFindBtn : "Hledat",
+DlgFindNotFoundMsg : "Hledaný text nebyl nalezen.",
+
+// Replace Dialog
+DlgReplaceTitle : "Nahradit",
+DlgReplaceFindLbl : "Co hledat:",
+DlgReplaceReplaceLbl : "Čím nahradit:",
+DlgReplaceCaseChk : "Rozlišovat velikost písma",
+DlgReplaceReplaceBtn : "Nahradit",
+DlgReplaceReplAllBtn : "Nahradit vše",
+DlgReplaceWordChk : "Pouze celá slova",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Bezpečnostní nastavení Vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl+X).",
+PasteErrorCopy : "Bezpečnostní nastavení Vašeho prohlížeče nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl+C).",
+
+PasteAsText : "Vložit jako čistý text",
+PasteFromWord : "Vložit text z Wordu",
+
+DlgPasteMsg2 : "Do následujícího pole vložte požadovaný obsah pomocí klávesnice (<STRONG>Ctrl+V</STRONG>) a stiskněte <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorovat písmo",
+DlgPasteRemoveStyles : "Odstranit styly",
+DlgPasteCleanBox : "Vyčistit",
+
+// Color Picker
+ColorAutomatic : "Automaticky",
+ColorMoreColors : "Více barev...",
+
+// Document Properties
+DocProps : "Vlastnosti dokumentu",
+
+// Anchor Dialog
+DlgAnchorTitle : "Vlastnosti záložky",
+DlgAnchorName : "Název záložky",
+DlgAnchorErrorName : "Zadejte prosím název záložky",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Není ve slovníku",
+DlgSpellChangeTo : "Změnit na",
+DlgSpellBtnIgnore : "Přeskočit",
+DlgSpellBtnIgnoreAll : "Přeskakovat vše",
+DlgSpellBtnReplace : "Zaměnit",
+DlgSpellBtnReplaceAll : "Zaměňovat vše",
+DlgSpellBtnUndo : "Zpět",
+DlgSpellNoSuggestions : "- žádné návrhy -",
+DlgSpellProgress : "Probíhá kontrola pravopisu...",
+DlgSpellNoMispell : "Kontrola pravopisu dokončena: Žádné pravopisné chyby nenalezeny",
+DlgSpellNoChanges : "Kontrola pravopisu dokončena: Beze změn",
+DlgSpellOneChange : "Kontrola pravopisu dokončena: Jedno slovo změněno",
+DlgSpellManyChanges : "Kontrola pravopisu dokončena: %1 slov změněno",
+
+IeSpellDownload : "Kontrola pravopisu není nainstalována. Chcete ji nyní stáhnout?",
+
+// Button Dialog
+DlgButtonText : "Popisek",
+DlgButtonType : "Typ",
+DlgButtonTypeBtn : "Tlačítko",
+DlgButtonTypeSbm : "Odeslat",
+DlgButtonTypeRst : "Obnovit",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Název",
+DlgCheckboxValue : "Hodnota",
+DlgCheckboxSelected : "Zaškrtnuto",
+
+// Form Dialog
+DlgFormName : "Název",
+DlgFormAction : "Akce",
+DlgFormMethod : "Metoda",
+
+// Select Field Dialog
+DlgSelectName : "Název",
+DlgSelectValue : "Hodnota",
+DlgSelectSize : "Velikost",
+DlgSelectLines : "Řádků",
+DlgSelectChkMulti : "Povolit mnohonásobné výběry",
+DlgSelectOpAvail : "Dostupná nastavení",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Hodnota",
+DlgSelectBtnAdd : "Přidat",
+DlgSelectBtnModify : "Změnit",
+DlgSelectBtnUp : "Nahoru",
+DlgSelectBtnDown : "Dolů",
+DlgSelectBtnSetValue : "Nastavit jako vybranou hodnotu",
+DlgSelectBtnDelete : "Smazat",
+
+// Textarea Dialog
+DlgTextareaName : "Název",
+DlgTextareaCols : "Sloupců",
+DlgTextareaRows : "Řádků",
+
+// Text Field Dialog
+DlgTextName : "Název",
+DlgTextValue : "Hodnota",
+DlgTextCharWidth : "Šířka ve znacích",
+DlgTextMaxChars : "Maximální počet znaků",
+DlgTextType : "Typ",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Heslo",
+
+// Hidden Field Dialog
+DlgHiddenName : "Název",
+DlgHiddenValue : "Hodnota",
+
+// Bulleted List Dialog
+BulletedListProp : "Vlastnosti odrážek",
+NumberedListProp : "Vlastnosti číslovaného seznamu",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Typ",
+DlgLstTypeCircle : "Kružnice",
+DlgLstTypeDisc : "Kruh",
+DlgLstTypeSquare : "Čtverec",
+DlgLstTypeNumbers : "Čísla (1, 2, 3)",
+DlgLstTypeLCase : "Malá písmena (a, b, c)",
+DlgLstTypeUCase : "Velká písmena (A, B, C)",
+DlgLstTypeSRoman : "Malé římská číslice (i, ii, iii)",
+DlgLstTypeLRoman : "Velké římské číslice (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Obecné",
+DlgDocBackTab : "Pozadí",
+DlgDocColorsTab : "Barvy a okraje",
+DlgDocMetaTab : "Metadata",
+
+DlgDocPageTitle : "Titulek stránky",
+DlgDocLangDir : "Směr jazyku",
+DlgDocLangDirLTR : "Zleva do prava ",
+DlgDocLangDirRTL : "Zprava doleva",
+DlgDocLangCode : "Kód jazyku",
+DlgDocCharSet : "Znaková sada",
+DlgDocCharSetCE : "Středoevropské jazyky",
+DlgDocCharSetCT : "Tradiční čínština (Big5)",
+DlgDocCharSetCR : "Cyrilice",
+DlgDocCharSetGR : "Řečtina",
+DlgDocCharSetJP : "Japonština",
+DlgDocCharSetKR : "Korejština",
+DlgDocCharSetTR : "Turečtina",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Západoevropské jazyky",
+DlgDocCharSetOther : "Další znaková sada",
+
+DlgDocDocType : "Typ dokumentu",
+DlgDocDocTypeOther : "Jiný typ dokumetu",
+DlgDocIncXHTML : "Zahrnou deklarace XHTML",
+DlgDocBgColor : "Barva pozadí",
+DlgDocBgImage : "URL obrázku na pozadí",
+DlgDocBgNoScroll : "Nerolovatelné pozadí",
+DlgDocCText : "Text",
+DlgDocCLink : "Odkaz",
+DlgDocCVisited : "Navštívený odkaz",
+DlgDocCActive : "Vybraný odkaz",
+DlgDocMargins : "Okraje stránky",
+DlgDocMaTop : "Horní",
+DlgDocMaLeft : "Levý",
+DlgDocMaRight : "Pravý",
+DlgDocMaBottom : "Dolní",
+DlgDocMeIndex : "Klíčová slova (oddělená čárkou)",
+DlgDocMeDescr : "Popis dokumentu",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Autorská práva",
+DlgDocPreview : "Náhled",
+
+// Templates Dialog
+Templates : "Šablony",
+DlgTemplatesTitle : "Šablony obsahu",
+DlgTemplatesSelMsg : "Prosím zvolte šablonu pro otevření v editoru<br>(aktuální obsah editoru bude ztracen):",
+DlgTemplatesLoading : "Nahrávám přeheld šablon. Prosím čekejte...",
+DlgTemplatesNoTpl : "(Není definována žádná šablona)",
+DlgTemplatesReplace : "Nahradit aktuální obsah",
+
+// About Dialog
+DlgAboutAboutTab : "O aplikaci",
+DlgAboutBrowserInfoTab : "Informace o prohlížeči",
+DlgAboutLicenseTab : "Licence",
+DlgAboutVersion : "verze",
+DlgAboutInfo : "Více informací získáte na"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/da.js b/httemplate/elements/fckeditor/editor/lang/da.js
new file mode 100644
index 000000000..814324116
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/da.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Danish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skjul værktøjslinier",
+ToolbarExpand : "Vis værktøjslinier",
+
+// Toolbar Items and Context Menu
+Save : "Gem",
+NewPage : "Ny side",
+Preview : "Vis eksempel",
+Cut : "Klip",
+Copy : "Kopier",
+Paste : "Indsæt",
+PasteText : "Indsæt som ikke-formateret tekst",
+PasteWord : "Indsæt fra Word",
+Print : "Udskriv",
+SelectAll : "Vælg alt",
+RemoveFormat : "Fjern formatering",
+InsertLinkLbl : "Hyperlink",
+InsertLink : "Indsæt/rediger hyperlink",
+RemoveLink : "Fjern hyperlink",
+Anchor : "Indsæt/rediger bogmærke",
+InsertImageLbl : "Indsæt billede",
+InsertImage : "Indsæt/rediger billede",
+InsertFlashLbl : "Flash",
+InsertFlash : "Indsæt/rediger Flash",
+InsertTableLbl : "Table",
+InsertTable : "Indsæt/rediger tabel",
+InsertLineLbl : "Linie",
+InsertLine : "Indsæt vandret linie",
+InsertSpecialCharLbl: "Symbol",
+InsertSpecialChar : "Indsæt symbol",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Indsæt smiley",
+About : "Om FCKeditor",
+Bold : "Fed",
+Italic : "Kursiv",
+Underline : "Understreget",
+StrikeThrough : "Overstreget",
+Subscript : "Sænket skrift",
+Superscript : "Hævet skrift",
+LeftJustify : "Venstrestillet",
+CenterJustify : "Centreret",
+RightJustify : "Højrestillet",
+BlockJustify : "Lige margener",
+DecreaseIndent : "Formindsk indrykning",
+IncreaseIndent : "Forøg indrykning",
+Undo : "Fortryd",
+Redo : "Annuller fortryd",
+NumberedListLbl : "Talopstilling",
+NumberedList : "Indsæt/fjern talopstilling",
+BulletedListLbl : "Punktopstilling",
+BulletedList : "Indsæt/fjern punktopstilling",
+ShowTableBorders : "Vis tabelkanter",
+ShowDetails : "Vis detaljer",
+Style : "Typografi",
+FontFormat : "Formatering",
+Font : "Skrifttype",
+FontSize : "Skriftstørrelse",
+TextColor : "Tekstfarve",
+BGColor : "Baggrundsfarve",
+Source : "Kilde",
+Find : "Søg",
+Replace : "Erstat",
+SpellCheck : "Stavekontrol",
+UniversalKeyboard : "Universaltastatur",
+PageBreakLbl : "Sidskift",
+PageBreak : "Indsæt sideskift",
+
+Form : "Indsæt formular",
+Checkbox : "Indsæt afkrydsningsfelt",
+RadioButton : "Indsæt alternativknap",
+TextField : "Indsæt tekstfelt",
+Textarea : "Indsæt tekstboks",
+HiddenField : "Indsæt skjult felt",
+Button : "Indsæt knap",
+SelectionField : "Indsæt liste",
+ImageButton : "Indsæt billedknap",
+
+FitWindow : "Maksimer editor vinduet",
+
+// Context Menu
+EditLink : "Rediger hyperlink",
+CellCM : "Celle",
+RowCM : "Række",
+ColumnCM : "Kolonne",
+InsertRow : "Indsæt række",
+DeleteRows : "Slet række",
+InsertColumn : "Indsæt kolonne",
+DeleteColumns : "Slet kolonne",
+InsertCell : "Indsæt celle",
+DeleteCells : "Slet celle",
+MergeCells : "Flet celler",
+SplitCell : "Opdel celle",
+TableDelete : "Slet tabel",
+CellProperties : "Egenskaber for celle",
+TableProperties : "Egenskaber for tabel",
+ImageProperties : "Egenskaber for billede",
+FlashProperties : "Egenskaber for Flash",
+
+AnchorProp : "Egenskaber for bogmærke",
+ButtonProp : "Egenskaber for knap",
+CheckboxProp : "Egenskaber for afkrydsningsfelt",
+HiddenFieldProp : "Egenskaber for skjult felt",
+RadioButtonProp : "Egenskaber for alternativknap",
+ImageButtonProp : "Egenskaber for billedknap",
+TextFieldProp : "Egenskaber for tekstfelt",
+SelectionFieldProp : "Egenskaber for liste",
+TextareaProp : "Egenskaber for tekstboks",
+FormProp : "Egenskaber for formular",
+
+FontFormats : "Normal;Formateret;Adresse;Overskrift 1;Overskrift 2;Overskrift 3;Overskrift 4;Overskrift 5;Overskrift 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Behandler XHTML...",
+Done : "Færdig",
+PasteWordConfirm : "Den tekst du forsøger at indsætte ser ud til at komme fra Word.<br>Vil du rense teksten før den indsættes?",
+NotCompatiblePaste : "Denne kommando er tilgændelig i Internet Explorer 5.5 eller senere.<br>Vil du indsætte teksten uden at rense den ?",
+UnknownToolbarItem : "Ukendt værktøjslinjeobjekt \"%1\"!",
+UnknownCommand : "Ukendt kommandonavn \"%1\"!",
+NotImplemented : "Kommandoen er ikke implementeret!",
+UnknownToolbarSet : "Værktøjslinjen \"%1\" eksisterer ikke!",
+NoActiveX : "Din browsers sikkerhedsindstillinger begrænser nogle af editorens muligheder.<br>Slå \"Kør ActiveX-objekter og plug-ins\" til, ellers vil du opleve fejl og manglende muligheder.",
+BrowseServerBlocked : "Browseren kunne ikke åbne de nødvendige ressourcer!<br>Slå pop-up blokering fra.",
+DialogBlocked : "Dialogvinduet kunne ikke åbnes!<br>Slå pop-up blokering fra.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Annuller",
+DlgBtnClose : "Luk",
+DlgBtnBrowseServer : "Gennemse...",
+DlgAdvancedTag : "Avanceret",
+DlgOpOther : "<Andet>",
+DlgInfoTab : "Generelt",
+DlgAlertUrl : "Indtast URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<intet valgt>",
+DlgGenId : "Id",
+DlgGenLangDir : "Tekstretning",
+DlgGenLangDirLtr : "Fra venstre mod højre (LTR)",
+DlgGenLangDirRtl : "Fra højre mod venstre (RTL)",
+DlgGenLangCode : "Sprogkode",
+DlgGenAccessKey : "Genvejstast",
+DlgGenName : "Navn",
+DlgGenTabIndex : "Tabulator indeks",
+DlgGenLongDescr : "Udvidet beskrivelse",
+DlgGenClass : "Typografiark",
+DlgGenTitle : "Titel",
+DlgGenContType : "Indholdstype",
+DlgGenLinkCharset : "Tegnsæt",
+DlgGenStyle : "Typografi",
+
+// Image Dialog
+DlgImgTitle : "Egenskaber for billede",
+DlgImgInfoTab : "Generelt",
+DlgImgBtnUpload : "Upload",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternativ tekst",
+DlgImgWidth : "Bredde",
+DlgImgHeight : "Højde",
+DlgImgLockRatio : "Lås størrelsesforhold",
+DlgBtnResetSize : "Nulstil størrelse",
+DlgImgBorder : "Ramme",
+DlgImgHSpace : "HMargen",
+DlgImgVSpace : "VMargen",
+DlgImgAlign : "Justering",
+DlgImgAlignLeft : "Venstre",
+DlgImgAlignAbsBottom: "Absolut nederst",
+DlgImgAlignAbsMiddle: "Absolut centreret",
+DlgImgAlignBaseline : "Grundlinje",
+DlgImgAlignBottom : "Nederst",
+DlgImgAlignMiddle : "Centreret",
+DlgImgAlignRight : "Højre",
+DlgImgAlignTextTop : "Toppen af teksten",
+DlgImgAlignTop : "Øverst",
+DlgImgPreview : "Vis eksempel",
+DlgImgAlertUrl : "Indtast stien til billedet",
+DlgImgLinkTab : "Hyperlink",
+
+// Flash Dialog
+DlgFlashTitle : "Egenskaber for Flash",
+DlgFlashChkPlay : "Automatisk afspilning",
+DlgFlashChkLoop : "Gentagelse",
+DlgFlashChkMenu : "Vis Flash menu",
+DlgFlashScale : "Skalér",
+DlgFlashScaleAll : "Vis alt",
+DlgFlashScaleNoBorder : "Ingen ramme",
+DlgFlashScaleFit : "Tilpas størrelse",
+
+// Link Dialog
+DlgLnkWindowTitle : "Egenskaber for hyperlink",
+DlgLnkInfoTab : "Generelt",
+DlgLnkTargetTab : "Mål",
+
+DlgLnkType : "Hyperlink type",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Bogmærke på denne side",
+DlgLnkTypeEMail : "E-mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<anden>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Vælg et anker",
+DlgLnkAnchorByName : "Efter anker navn",
+DlgLnkAnchorById : "Efter element Id",
+DlgLnkNoAnchors : "<Ingen bogmærker dokumentet>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-mailadresse",
+DlgLnkEMailSubject : "Emne",
+DlgLnkEMailBody : "Brødtekst",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Upload",
+
+DlgLnkTarget : "Mål",
+DlgLnkTargetFrame : "<ramme>",
+DlgLnkTargetPopup : "<popup vindue>",
+DlgLnkTargetBlank : "Nyt vindue (_blank)",
+DlgLnkTargetParent : "Overordnet ramme (_parent)",
+DlgLnkTargetSelf : "Samme vindue (_self)",
+DlgLnkTargetTop : "Hele vinduet (_top)",
+DlgLnkTargetFrameName : "Destinationsvinduets navn",
+DlgLnkPopWinName : "Pop-up vinduets navn",
+DlgLnkPopWinFeat : "Egenskaber for pop-up",
+DlgLnkPopResize : "Skalering",
+DlgLnkPopLocation : "Adresselinje",
+DlgLnkPopMenu : "Menulinje",
+DlgLnkPopScroll : "Scrollbars",
+DlgLnkPopStatus : "Statuslinje",
+DlgLnkPopToolbar : "Værktøjslinje",
+DlgLnkPopFullScrn : "Fuld skærm (IE)",
+DlgLnkPopDependent : "Koblet/dependent (Netscape)",
+DlgLnkPopWidth : "Bredde",
+DlgLnkPopHeight : "Højde",
+DlgLnkPopLeft : "Position fra venstre",
+DlgLnkPopTop : "Position fra toppen",
+
+DlnLnkMsgNoUrl : "Indtast hyperlink URL!",
+DlnLnkMsgNoEMail : "Indtast e-mailaddresse!",
+DlnLnkMsgNoAnchor : "Vælg bogmærke!",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Vælg farve",
+DlgColorBtnClear : "Nulstil",
+DlgColorHighlight : "Markeret",
+DlgColorSelected : "Valgt",
+
+// Smiley Dialog
+DlgSmileyTitle : "Vælg smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Vælg symbol",
+
+// Table Dialog
+DlgTableTitle : "Egenskaber for tabel",
+DlgTableRows : "Rækker",
+DlgTableColumns : "Kolonner",
+DlgTableBorder : "Rammebredde",
+DlgTableAlign : "Justering",
+DlgTableAlignNotSet : "<intet valgt>",
+DlgTableAlignLeft : "Venstrestillet",
+DlgTableAlignCenter : "Centreret",
+DlgTableAlignRight : "Højrestillet",
+DlgTableWidth : "Bredde",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "procent",
+DlgTableHeight : "Højde",
+DlgTableCellSpace : "Celleafstand",
+DlgTableCellPad : "Cellemargen",
+DlgTableCaption : "Titel",
+DlgTableSummary : "Resume",
+
+// Table Cell Dialog
+DlgCellTitle : "Egenskaber for celle",
+DlgCellWidth : "Bredde",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "procent",
+DlgCellHeight : "Højde",
+DlgCellWordWrap : "Orddeling",
+DlgCellWordWrapNotSet : "<intet valgt>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nej",
+DlgCellHorAlign : "Vandret justering",
+DlgCellHorAlignNotSet : "<intet valgt>",
+DlgCellHorAlignLeft : "Venstrestillet",
+DlgCellHorAlignCenter : "Centreret",
+DlgCellHorAlignRight: "Højrestillet",
+DlgCellVerAlign : "Lodret justering",
+DlgCellVerAlignNotSet : "<intet valgt>",
+DlgCellVerAlignTop : "Øverst",
+DlgCellVerAlignMiddle : "Centreret",
+DlgCellVerAlignBottom : "Nederst",
+DlgCellVerAlignBaseline : "Grundlinje",
+DlgCellRowSpan : "Højde i antal rækker",
+DlgCellCollSpan : "Bredde i antal kolonner",
+DlgCellBackColor : "Baggrundsfarve",
+DlgCellBorderColor : "Rammefarve",
+DlgCellBtnSelect : "Vælg...",
+
+// Find Dialog
+DlgFindTitle : "Find",
+DlgFindFindBtn : "Find",
+DlgFindNotFoundMsg : "Søgeteksten blev ikke fundet!",
+
+// Replace Dialog
+DlgReplaceTitle : "Erstat",
+DlgReplaceFindLbl : "Søg efter:",
+DlgReplaceReplaceLbl : "Erstat med:",
+DlgReplaceCaseChk : "Forskel på store og små bogstaver",
+DlgReplaceReplaceBtn : "Erstat",
+DlgReplaceReplAllBtn : "Erstat alle",
+DlgReplaceWordChk : "Kun hele ord",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Din browsers sikkerhedsindstillinger tillader ikke editoren at klippe tekst automatisk!<br>Brug i stedet tastaturet til at klippe teksten (Ctrl+X).",
+PasteErrorCopy : "Din browsers sikkerhedsindstillinger tillader ikke editoren at kopiere tekst automatisk!<br>Brug i stedet tastaturet til at kopiere teksten (Ctrl+C).",
+
+PasteAsText : "Indsæt som ikke-formateret tekst",
+PasteFromWord : "Indsæt fra Word",
+
+DlgPasteMsg2 : "Indsæt i feltet herunder (<STRONG>Ctrl+V</STRONG>) og klik <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorer font definitioner",
+DlgPasteRemoveStyles : "Ignorer typografi",
+DlgPasteCleanBox : "Slet indhold",
+
+// Color Picker
+ColorAutomatic : "Automatisk",
+ColorMoreColors : "Flere farver...",
+
+// Document Properties
+DocProps : "Egenskaber for dokument",
+
+// Anchor Dialog
+DlgAnchorTitle : "Egenskaber for bogmærke",
+DlgAnchorName : "Bogmærke navn",
+DlgAnchorErrorName : "Indtast bogmærke navn!",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ikke i ordbogen",
+DlgSpellChangeTo : "Forslag",
+DlgSpellBtnIgnore : "Ignorer",
+DlgSpellBtnIgnoreAll : "Ignorer alle",
+DlgSpellBtnReplace : "Erstat",
+DlgSpellBtnReplaceAll : "Erstat alle",
+DlgSpellBtnUndo : "Tilbage",
+DlgSpellNoSuggestions : "- ingen forslag -",
+DlgSpellProgress : "Stavekontrolen arbejder...",
+DlgSpellNoMispell : "Stavekontrol færdig: Ingen fejl fundet",
+DlgSpellNoChanges : "Stavekontrol færdig: Ingen ord ændret",
+DlgSpellOneChange : "Stavekontrol færdig: Et ord ændret",
+DlgSpellManyChanges : "Stavekontrol færdig: %1 ord ændret",
+
+IeSpellDownload : "Stavekontrol ikke installeret.<br>Vil du hente den nu?",
+
+// Button Dialog
+DlgButtonText : "Tekst",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Navn",
+DlgCheckboxValue : "Værdi",
+DlgCheckboxSelected : "Valgt",
+
+// Form Dialog
+DlgFormName : "Navn",
+DlgFormAction : "Handling",
+DlgFormMethod : "Metod",
+
+// Select Field Dialog
+DlgSelectName : "Navn",
+DlgSelectValue : "Værdi",
+DlgSelectSize : "Størrelse",
+DlgSelectLines : "linier",
+DlgSelectChkMulti : "Tillad flere valg",
+DlgSelectOpAvail : "Valgmuligheder",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Værdi",
+DlgSelectBtnAdd : "Tilføj",
+DlgSelectBtnModify : "Rediger",
+DlgSelectBtnUp : "Op",
+DlgSelectBtnDown : "Ned",
+DlgSelectBtnSetValue : "Sæt som valgt",
+DlgSelectBtnDelete : "Slet",
+
+// Textarea Dialog
+DlgTextareaName : "Navn",
+DlgTextareaCols : "Kolonner",
+DlgTextareaRows : "Rækker",
+
+// Text Field Dialog
+DlgTextName : "Navn",
+DlgTextValue : "Værdi",
+DlgTextCharWidth : "Bredde (tegn)",
+DlgTextMaxChars : "Max antal tegn",
+DlgTextType : "Type",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Adgangskode",
+
+// Hidden Field Dialog
+DlgHiddenName : "Navn",
+DlgHiddenValue : "Værdi",
+
+// Bulleted List Dialog
+BulletedListProp : "Egenskaber for punktopstilling",
+NumberedListProp : "Egenskaber for talopstilling",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Type",
+DlgLstTypeCircle : "Cirkel",
+DlgLstTypeDisc : "Udfyldt cirkel",
+DlgLstTypeSquare : "Firkant",
+DlgLstTypeNumbers : "Nummereret (1, 2, 3)",
+DlgLstTypeLCase : "Små bogstaver (a, b, c)",
+DlgLstTypeUCase : "Store bogstaver (A, B, C)",
+DlgLstTypeSRoman : "Små romertal (i, ii, iii)",
+DlgLstTypeLRoman : "Store romertal (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Generelt",
+DlgDocBackTab : "Baggrund",
+DlgDocColorsTab : "Farver og margen",
+DlgDocMetaTab : "Metadata",
+
+DlgDocPageTitle : "Sidetitel",
+DlgDocLangDir : "Sprog",
+DlgDocLangDirLTR : "Fra venstre mod højre (LTR)",
+DlgDocLangDirRTL : "Fra højre mod venstre (RTL)",
+DlgDocLangCode : "Landekode",
+DlgDocCharSet : "Tegnsæt kode",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Anden tegnsæt kode",
+
+DlgDocDocType : "Dokumenttype kategori",
+DlgDocDocTypeOther : "Anden dokumenttype kategori",
+DlgDocIncXHTML : "Inkludere XHTML deklartion",
+DlgDocBgColor : "Baggrundsfarve",
+DlgDocBgImage : "Baggrundsbillede URL",
+DlgDocBgNoScroll : "Fastlåst baggrund",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Hyperlink",
+DlgDocCVisited : "Besøgt hyperlink",
+DlgDocCActive : "Aktivt hyperlink",
+DlgDocMargins : "Sidemargen",
+DlgDocMaTop : "Øverst",
+DlgDocMaLeft : "Venstre",
+DlgDocMaRight : "Højre",
+DlgDocMaBottom : "Nederst",
+DlgDocMeIndex : "Dokument index nøgleord (kommasepareret)",
+DlgDocMeDescr : "Dokument beskrivelse",
+DlgDocMeAuthor : "Forfatter",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Vis",
+
+// Templates Dialog
+Templates : "Skabeloner",
+DlgTemplatesTitle : "Indholdsskabeloner",
+DlgTemplatesSelMsg : "Vælg den skabelon, som skal åbnes i editoren.<br>(Nuværende indhold vil blive overskrevet!):",
+DlgTemplatesLoading : "Henter liste over skabeloner...",
+DlgTemplatesNoTpl : "(Der er ikke defineret nogen skabelon!)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Om",
+DlgAboutBrowserInfoTab : "Generelt",
+DlgAboutLicenseTab : "Licens",
+DlgAboutVersion : "version",
+DlgAboutInfo : "For yderlig information gå til"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/de.js b/httemplate/elements/fckeditor/editor/lang/de.js
new file mode 100644
index 000000000..2848d3462
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/de.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * German language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Symbolleiste einklappen",
+ToolbarExpand : "Symbolleiste ausklappen",
+
+// Toolbar Items and Context Menu
+Save : "Speichern",
+NewPage : "Neue Seite",
+Preview : "Vorschau",
+Cut : "Ausschneiden",
+Copy : "Kopieren",
+Paste : "Einfügen",
+PasteText : "aus Textdatei einfügen",
+PasteWord : "aus MS-Word einfügen",
+Print : "Drucken",
+SelectAll : "Alles auswählen",
+RemoveFormat : "Formatierungen entfernen",
+InsertLinkLbl : "Link",
+InsertLink : "Link einfügen/editieren",
+RemoveLink : "Link entfernen",
+Anchor : "Anker einfügen/editieren",
+InsertImageLbl : "Bild",
+InsertImage : "Bild einfügen/editieren",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash einfügen/editieren",
+InsertTableLbl : "Tabelle",
+InsertTable : "Tabelle einfügen/editieren",
+InsertLineLbl : "Linie",
+InsertLine : "Horizontale Linie einfügen",
+InsertSpecialCharLbl: "Sonderzeichen",
+InsertSpecialChar : "Sonderzeichen einfügen/editieren",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Smiley einfügen",
+About : "Über FCKeditor",
+Bold : "Fett",
+Italic : "Kursiv",
+Underline : "Unterstrichen",
+StrikeThrough : "Durchgestrichen",
+Subscript : "Tiefgestellt",
+Superscript : "Hochgestellt",
+LeftJustify : "Linksbündig",
+CenterJustify : "Zentriert",
+RightJustify : "Rechtsbündig",
+BlockJustify : "Blocksatz",
+DecreaseIndent : "Einzug verringern",
+IncreaseIndent : "Einzug erhöhen",
+Undo : "Rückgängig",
+Redo : "Wiederherstellen",
+NumberedListLbl : "Nummerierte Liste",
+NumberedList : "Nummerierte Liste einfügen/entfernen",
+BulletedListLbl : "Liste",
+BulletedList : "Liste einfügen/entfernen",
+ShowTableBorders : "Zeige Tabellenrahmen",
+ShowDetails : "Zeige Details",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Schriftart",
+FontSize : "Größe",
+TextColor : "Textfarbe",
+BGColor : "Hintergrundfarbe",
+Source : "Quellcode",
+Find : "Finden",
+Replace : "Ersetzen",
+SpellCheck : "Rechtschreibprüfung",
+UniversalKeyboard : "Universal-Tastatur",
+PageBreakLbl : "Seitenumbruch",
+PageBreak : "Seitenumbruch einfügen",
+
+Form : "Formular",
+Checkbox : "Checkbox",
+RadioButton : "Radiobutton",
+TextField : "Textfeld einzeilig",
+Textarea : "Textfeld mehrzeilig",
+HiddenField : "verstecktes Feld",
+Button : "Klickbutton",
+SelectionField : "Auswahlfeld",
+ImageButton : "Bildbutton",
+
+FitWindow : "Editor maximieren",
+
+// Context Menu
+EditLink : "Link editieren",
+CellCM : "Zelle",
+RowCM : "Zeile",
+ColumnCM : "Spalte",
+InsertRow : "Zeile einfügen",
+DeleteRows : "Zeile entfernen",
+InsertColumn : "Spalte einfügen",
+DeleteColumns : "Spalte löschen",
+InsertCell : "Zelle einfügen",
+DeleteCells : "Zelle löschen",
+MergeCells : "Zellen vereinen",
+SplitCell : "Zelle teilen",
+TableDelete : "Tabelle löschen",
+CellProperties : "Zellen Eigenschaften",
+TableProperties : "Tabellen Eigenschaften",
+ImageProperties : "Bild Eigenschaften",
+FlashProperties : "Flash Eigenschaften",
+
+AnchorProp : "Anker Eigenschaften",
+ButtonProp : "Button Eigenschaften",
+CheckboxProp : "Checkbox Eigenschaften",
+HiddenFieldProp : "Verstecktes Feld Eigenschaften",
+RadioButtonProp : "Optionsfeld Eigenschaften",
+ImageButtonProp : "Bildbutton Eigenschaften",
+TextFieldProp : "Textfeld (einzeilig) Eigenschaften",
+SelectionFieldProp : "Auswahlfeld Eigenschaften",
+TextareaProp : "Textfeld (mehrzeilig) Eigenschaften",
+FormProp : "Formular Eigenschaften",
+
+FontFormats : "Normal;Formatiert;Addresse;Überschrift 1;Überschrift 2;Überschrift 3;Überschrift 4;Überschrift 5;Überschrift 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Bearbeite XHTML. Bitte warten...",
+Done : "Fertig",
+PasteWordConfirm : "Der Text, den Sie einfügen möchten, scheint aus MS-Word kopiert zu sein. Möchten Sie ihn zuvor bereinigen lassen?",
+NotCompatiblePaste : "Diese Funktion steht nur im Internet Explorer ab Version 5.5 zur Verfügung. Möchten Sie den Text unbereinigt einfügen?",
+UnknownToolbarItem : "Unbekanntes Menüleisten-Objekt \"%1\"",
+UnknownCommand : "Unbekannter Befehl \"%1\"",
+NotImplemented : "Befehl nicht implementiert",
+UnknownToolbarSet : "Menüleiste \"%1\" existiert nicht",
+NoActiveX : "Die Sicherheitseinstellungen Ihres Browsers beschränken evtl. einige Funktionen des Editors. Aktivieren Sie die Option \"ActiveX-Steuerelemente und Plugins ausführen\" in den Sicherheitseinstellungen, um diese Funktionen nutzen zu können",
+BrowseServerBlocked : "Ein Auswahlfenster konnte nicht geöffnet werden. Stellen Sie sicher, das alle Popup-Blocker ausgeschaltet sind.",
+DialogBlocked : "Das Dialog-Fenster konnte nicht geöffnet werden. Stellen Sie sicher, das alle Popup-Blocker ausgeschaltet sind.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Abbrechen",
+DlgBtnClose : "Schließen",
+DlgBtnBrowseServer : "Server durchsuchen",
+DlgAdvancedTag : "Erweitert",
+DlgOpOther : "<andere>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Bitte tragen Sie die URL ein",
+
+// General Dialogs Labels
+DlgGenNotSet : "< nichts >",
+DlgGenId : "ID",
+DlgGenLangDir : "Schreibrichtung",
+DlgGenLangDirLtr : "Links nach Rechts (LTR)",
+DlgGenLangDirRtl : "Rechts nach Links (RTL)",
+DlgGenLangCode : "Sprachenkürzel",
+DlgGenAccessKey : "Schlüssel",
+DlgGenName : "Name",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Langform URL",
+DlgGenClass : "Stylesheet Klasse",
+DlgGenTitle : "Titel Beschreibung",
+DlgGenContType : "Content Beschreibung",
+DlgGenLinkCharset : "Ziel-Zeichensatz",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Bild Eigenschaften",
+DlgImgInfoTab : "Bild-Info",
+DlgImgBtnUpload : "Zum Server senden",
+DlgImgURL : "Bildauswahl",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternativer Text",
+DlgImgWidth : "Breite",
+DlgImgHeight : "Höhe",
+DlgImgLockRatio : "Größenverhältniss beibehalten",
+DlgBtnResetSize : "Größe zurücksetzen",
+DlgImgBorder : "Rahmen",
+DlgImgHSpace : "H-Abstand",
+DlgImgVSpace : "V-Abstand",
+DlgImgAlign : "Ausrichtung",
+DlgImgAlignLeft : "Links",
+DlgImgAlignAbsBottom: "Abs Unten",
+DlgImgAlignAbsMiddle: "Abs Mitte",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Unten",
+DlgImgAlignMiddle : "Mitte",
+DlgImgAlignRight : "Rechts",
+DlgImgAlignTextTop : "Text Oben",
+DlgImgAlignTop : "Oben",
+DlgImgPreview : "Vorschau",
+DlgImgAlertUrl : "Bitte geben Sie die Bild-URL an",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Eigenschaften",
+DlgFlashChkPlay : "autom. Abspielen",
+DlgFlashChkLoop : "Endlosschleife",
+DlgFlashChkMenu : "Flash-Menü aktivieren",
+DlgFlashScale : "Skalierung",
+DlgFlashScaleAll : "Alles anzeigen",
+DlgFlashScaleNoBorder : "ohne Rand",
+DlgFlashScaleFit : "Passgenau",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Zielseite",
+
+DlgLnkType : "Link-Typ",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Anker in dieser Seite",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<anderes>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Anker auswählen",
+DlgLnkAnchorByName : "nach Anker Name",
+DlgLnkAnchorById : "nach Element Id",
+DlgLnkNoAnchors : "<keine Anker im Dokument vorhanden>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Addresse",
+DlgLnkEMailSubject : "Betreffzeile",
+DlgLnkEMailBody : "Nachrichtentext",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Zum Server senden",
+
+DlgLnkTarget : "Zielseite",
+DlgLnkTargetFrame : "<Frame>",
+DlgLnkTargetPopup : "<Pop-up Fenster>",
+DlgLnkTargetBlank : "Neues Fenster (_blank)",
+DlgLnkTargetParent : "Oberes Fenster (_parent)",
+DlgLnkTargetSelf : "Gleiches Fenster (_self)",
+DlgLnkTargetTop : "Oberstes Fenster (_top)",
+DlgLnkTargetFrameName : "Ziel-Fenster Name",
+DlgLnkPopWinName : "Pop-up Fenster Name",
+DlgLnkPopWinFeat : "Pop-up Fenster Eigenschaften",
+DlgLnkPopResize : "Vergrößerbar",
+DlgLnkPopLocation : "Adress-Leiste",
+DlgLnkPopMenu : "Menü-Leiste",
+DlgLnkPopScroll : "Rollbalken",
+DlgLnkPopStatus : "Statusleiste",
+DlgLnkPopToolbar : "Werkzeugleiste",
+DlgLnkPopFullScrn : "Vollbild (IE)",
+DlgLnkPopDependent : "Abhängig (Netscape)",
+DlgLnkPopWidth : "Breite",
+DlgLnkPopHeight : "Höhe",
+DlgLnkPopLeft : "Linke Position",
+DlgLnkPopTop : "Obere Position",
+
+DlnLnkMsgNoUrl : "Bitte geben Sie die Link-URL an",
+DlnLnkMsgNoEMail : "Bitte geben Sie e-Mail Adresse an",
+DlnLnkMsgNoAnchor : "Bitte wählen Sie einen Anker aus",
+DlnLnkMsgInvPopName : "Der Name des Popups muss mit einem Buchstaben beginnen und darf keine Leerzeichen enthalten",
+
+// Color Dialog
+DlgColorTitle : "Farbauswahl",
+DlgColorBtnClear : "Keine Farbe",
+DlgColorHighlight : "Vorschau",
+DlgColorSelected : "Ausgewählt",
+
+// Smiley Dialog
+DlgSmileyTitle : "Smiley auswählen",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Sonderzeichen auswählen",
+
+// Table Dialog
+DlgTableTitle : "Tabellen Eigenschaften",
+DlgTableRows : "Zeile",
+DlgTableColumns : "Spalte",
+DlgTableBorder : "Rahmen",
+DlgTableAlign : "Ausrichtung",
+DlgTableAlignNotSet : "<nichts>",
+DlgTableAlignLeft : "Links",
+DlgTableAlignCenter : "Zentriert",
+DlgTableAlignRight : "Rechts",
+DlgTableWidth : "Breite",
+DlgTableWidthPx : "Pixel",
+DlgTableWidthPc : "%",
+DlgTableHeight : "Höhe",
+DlgTableCellSpace : "Zellenabstand außen",
+DlgTableCellPad : "Zellenabstand innen",
+DlgTableCaption : "Überschrift",
+DlgTableSummary : "Inhaltsübersicht",
+
+// Table Cell Dialog
+DlgCellTitle : "Zellen-Eigenschaften",
+DlgCellWidth : "Breite",
+DlgCellWidthPx : "Pixel",
+DlgCellWidthPc : "%",
+DlgCellHeight : "Höhe",
+DlgCellWordWrap : "Umbruch",
+DlgCellWordWrapNotSet : "<nichts>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nein",
+DlgCellHorAlign : "Horizontale Ausrichtung",
+DlgCellHorAlignNotSet : "<nichts>",
+DlgCellHorAlignLeft : "Links",
+DlgCellHorAlignCenter : "Zentriert",
+DlgCellHorAlignRight: "Rechts",
+DlgCellVerAlign : "Vertikale Ausrichtung",
+DlgCellVerAlignNotSet : "<nichts>",
+DlgCellVerAlignTop : "Oben",
+DlgCellVerAlignMiddle : "Mitte",
+DlgCellVerAlignBottom : "Unten",
+DlgCellVerAlignBaseline : "Grundlinie",
+DlgCellRowSpan : "Zeilen zusammenfassen",
+DlgCellCollSpan : "Spalten zusammenfassen",
+DlgCellBackColor : "Hintergrundfarbe",
+DlgCellBorderColor : "Rahmenfarbe",
+DlgCellBtnSelect : "Auswahl...",
+
+// Find Dialog
+DlgFindTitle : "Finden",
+DlgFindFindBtn : "Finden",
+DlgFindNotFoundMsg : "Der gesuchte Text wurde nicht gefunden.",
+
+// Replace Dialog
+DlgReplaceTitle : "Ersetzen",
+DlgReplaceFindLbl : "Suche nach:",
+DlgReplaceReplaceLbl : "Ersetze mit:",
+DlgReplaceCaseChk : "Groß-Kleinschreibung beachten",
+DlgReplaceReplaceBtn : "Ersetzen",
+DlgReplaceReplAllBtn : "Alle Ersetzen",
+DlgReplaceWordChk : "Nur ganze Worte suchen",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).",
+PasteErrorCopy : "Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).",
+
+PasteAsText : "Als Text einfügen",
+PasteFromWord : "Aus Word einfügen",
+
+DlgPasteMsg2 : "Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit <STRONG>Ctrl+V</STRONG>) ein und bestätigen Sie mit <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoriere Schriftart-Definitionen",
+DlgPasteRemoveStyles : "Entferne Style-Definitionen",
+DlgPasteCleanBox : "Inhalt aufräumen",
+
+// Color Picker
+ColorAutomatic : "Automatisch",
+ColorMoreColors : "Weitere Farben...",
+
+// Document Properties
+DocProps : "Dokument Eigenschaften",
+
+// Anchor Dialog
+DlgAnchorTitle : "Anker Eigenschaften",
+DlgAnchorName : "Anker Name",
+DlgAnchorErrorName : "Bitte geben Sie den Namen des Ankers ein",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nicht im Wörterbuch",
+DlgSpellChangeTo : "Ändern in",
+DlgSpellBtnIgnore : "Ignorieren",
+DlgSpellBtnIgnoreAll : "Alle Ignorieren",
+DlgSpellBtnReplace : "Ersetzen",
+DlgSpellBtnReplaceAll : "Alle Ersetzen",
+DlgSpellBtnUndo : "Rückgängig",
+DlgSpellNoSuggestions : " - keine Vorschläge - ",
+DlgSpellProgress : "Rechtschreibprüfung läuft...",
+DlgSpellNoMispell : "Rechtschreibprüfung abgeschlossen - keine Fehler gefunden",
+DlgSpellNoChanges : "Rechtschreibprüfung abgeschlossen - keine Worte geändert",
+DlgSpellOneChange : "Rechtschreibprüfung abgeschlossen - ein Wort geändert",
+DlgSpellManyChanges : "Rechtschreibprüfung abgeschlossen - %1 Wörter geändert",
+
+IeSpellDownload : "Rechtschreibprüfung nicht installiert. Möchten Sie sie jetzt herunterladen?",
+
+// Button Dialog
+DlgButtonText : "Text (Wert)",
+DlgButtonType : "Typ",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Absenden",
+DlgButtonTypeRst : "Zurücksetzen",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name",
+DlgCheckboxValue : "Wert",
+DlgCheckboxSelected : "ausgewählt",
+
+// Form Dialog
+DlgFormName : "Name",
+DlgFormAction : "Action",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Name",
+DlgSelectValue : "Wert",
+DlgSelectSize : "Größe",
+DlgSelectLines : "Linien",
+DlgSelectChkMulti : "Erlaube Mehrfachauswahl",
+DlgSelectOpAvail : "Mögliche Optionen",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Wert",
+DlgSelectBtnAdd : "Hinzufügen",
+DlgSelectBtnModify : "Ändern",
+DlgSelectBtnUp : "Hoch",
+DlgSelectBtnDown : "Runter",
+DlgSelectBtnSetValue : "Setze als Standardwert",
+DlgSelectBtnDelete : "Entfernen",
+
+// Textarea Dialog
+DlgTextareaName : "Name",
+DlgTextareaCols : "Spalten",
+DlgTextareaRows : "Reihen",
+
+// Text Field Dialog
+DlgTextName : "Name",
+DlgTextValue : "Wert",
+DlgTextCharWidth : "Zeichenbreite",
+DlgTextMaxChars : "Max. Zeichen",
+DlgTextType : "Typ",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Passwort",
+
+// Hidden Field Dialog
+DlgHiddenName : "Name",
+DlgHiddenValue : "Wert",
+
+// Bulleted List Dialog
+BulletedListProp : "Listen-Eigenschaften",
+NumberedListProp : "Nummerierte Listen-Eigenschaften",
+DlgLstStart : "Start",
+DlgLstType : "Typ",
+DlgLstTypeCircle : "Ring",
+DlgLstTypeDisc : "Kreis",
+DlgLstTypeSquare : "Quadrat",
+DlgLstTypeNumbers : "Nummern (1, 2, 3)",
+DlgLstTypeLCase : "Kleinbuchstaben (a, b, c)",
+DlgLstTypeUCase : "Großbuchstaben (A, B, C)",
+DlgLstTypeSRoman : "Kleine römische Zahlen (i, ii, iii)",
+DlgLstTypeLRoman : "Große römische Zahlen (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Allgemein",
+DlgDocBackTab : "Hintergrund",
+DlgDocColorsTab : "Farben und Abstände",
+DlgDocMetaTab : "Metadaten",
+
+DlgDocPageTitle : "Seitentitel",
+DlgDocLangDir : "Schriftrichtung",
+DlgDocLangDirLTR : "Links nach Rechts",
+DlgDocLangDirRTL : "Rechts nach Links",
+DlgDocLangCode : "Sprachkürzel",
+DlgDocCharSet : "Zeichenkodierung",
+DlgDocCharSetCE : "Zentraleuropäisch",
+DlgDocCharSetCT : "traditionell Chinesisch (Big5)",
+DlgDocCharSetCR : "Kyrillisch",
+DlgDocCharSetGR : "Griechisch",
+DlgDocCharSetJP : "Japanisch",
+DlgDocCharSetKR : "Koreanisch",
+DlgDocCharSetTR : "Türkisch",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Westeuropäisch",
+DlgDocCharSetOther : "Andere Zeichenkodierung",
+
+DlgDocDocType : "Dokumententyp",
+DlgDocDocTypeOther : "Anderer Dokumententyp",
+DlgDocIncXHTML : "Beziehe XHTML Deklarationen ein",
+DlgDocBgColor : "Hintergrundfarbe",
+DlgDocBgImage : "Hintergrundbild URL",
+DlgDocBgNoScroll : "feststehender Hintergrund",
+DlgDocCText : "Text",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Besuchter Link",
+DlgDocCActive : "Aktiver Link",
+DlgDocMargins : "Seitenränder",
+DlgDocMaTop : "Oben",
+DlgDocMaLeft : "Links",
+DlgDocMaRight : "Rechts",
+DlgDocMaBottom : "Unten",
+DlgDocMeIndex : "Schlüsselwörter (durch Komma getrennt)",
+DlgDocMeDescr : "Dokument-Beschreibung",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Vorschau",
+
+// Templates Dialog
+Templates : "Vorlagen",
+DlgTemplatesTitle : "Vorlagen",
+DlgTemplatesSelMsg : "Klicken Sie auf eine Vorlage, um sie im Editor zu öffnen (der aktuelle Inhalt wird dabei gelöscht!):",
+DlgTemplatesLoading : "Liste der Vorlagen wird geladen. Bitte warten...",
+DlgTemplatesNoTpl : "(keine Vorlagen definiert)",
+DlgTemplatesReplace : "Aktuellen Inhalt ersetzen",
+
+// About Dialog
+DlgAboutAboutTab : "Über",
+DlgAboutBrowserInfoTab : "Browser-Info",
+DlgAboutLicenseTab : "Lizenz",
+DlgAboutVersion : "Version",
+DlgAboutInfo : "Für weitere Informationen siehe"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/el.js b/httemplate/elements/fckeditor/editor/lang/el.js
new file mode 100644
index 000000000..90fefc48f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/el.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Greek language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Απόκρυψη Μπάρας Εργαλείων",
+ToolbarExpand : "Εμφάνιση Μπάρας Εργαλείων",
+
+// Toolbar Items and Context Menu
+Save : "Αποθήκευση",
+NewPage : "Νέα Σελίδα",
+Preview : "Προεπισκόπιση",
+Cut : "Αποκοπή",
+Copy : "Αντιγραφή",
+Paste : "Επικόλληση",
+PasteText : "Επικόλληση (απλό κείμενο)",
+PasteWord : "Επικόλληση από το Word",
+Print : "Εκτύπωση",
+SelectAll : "Επιλογή όλων",
+RemoveFormat : "Αφαίρεση Μορφοποίησης",
+InsertLinkLbl : "Σύνδεσμος (Link)",
+InsertLink : "Εισαγωγή/Μεταβολή Συνδέσμου (Link)",
+RemoveLink : "Αφαίρεση Συνδέσμου (Link)",
+Anchor : "Εισαγωγή/επεξεργασία Anchor",
+InsertImageLbl : "Εικόνα",
+InsertImage : "Εισαγωγή/Μεταβολή Εικόνας",
+InsertFlashLbl : "Εισαγωγή Flash",
+InsertFlash : "Εισαγωγή/επεξεργασία Flash",
+InsertTableLbl : "Πίνακας",
+InsertTable : "Εισαγωγή/Μεταβολή Πίνακα",
+InsertLineLbl : "Γραμμή",
+InsertLine : "Εισαγωγή Οριζόντιας Γραμμής",
+InsertSpecialCharLbl: "Ειδικό Σύμβολο",
+InsertSpecialChar : "Εισαγωγή Ειδικού Συμβόλου",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Εισαγωγή Smiley",
+About : "Περί του FCKeditor",
+Bold : "Έντονα",
+Italic : "Πλάγια",
+Underline : "Υπογράμμιση",
+StrikeThrough : "Διαγράμμιση",
+Subscript : "Δείκτης",
+Superscript : "Εκθέτης",
+LeftJustify : "Στοίχιση Αριστερά",
+CenterJustify : "Στοίχιση στο Κέντρο",
+RightJustify : "Στοίχιση Δεξιά",
+BlockJustify : "Πλήρης Στοίχιση (Block)",
+DecreaseIndent : "Μείωση Εσοχής",
+IncreaseIndent : "Αύξηση Εσοχής",
+Undo : "Αναίρεση",
+Redo : "Επαναφορά",
+NumberedListLbl : "Λίστα με Αριθμούς",
+NumberedList : "Εισαγωγή/Διαγραφή Λίστας με Αριθμούς",
+BulletedListLbl : "Λίστα με Bullets",
+BulletedList : "Εισαγωγή/Διαγραφή Λίστας με Bullets",
+ShowTableBorders : "Προβολή Ορίων Πίνακα",
+ShowDetails : "Προβολή Λεπτομερειών",
+Style : "Στυλ",
+FontFormat : "Μορφή Γραμματοσειράς",
+Font : "Γραμματοσειρά",
+FontSize : "Μέγεθος",
+TextColor : "Χρώμα Γραμμάτων",
+BGColor : "Χρώμα Υποβάθρου",
+Source : "HTML κώδικας",
+Find : "Αναζήτηση",
+Replace : "Αντικατάσταση",
+SpellCheck : "Ορθογραφικός έλεγχος",
+UniversalKeyboard : "Διεθνής πληκτρολόγιο",
+PageBreakLbl : "Τέλος σελίδας",
+PageBreak : "Εισαγωγή τέλους σελίδας",
+
+Form : "Φόρμα",
+Checkbox : "Κουτί επιλογής",
+RadioButton : "Κουμπί Radio",
+TextField : "Πεδίο κειμένου",
+Textarea : "Περιοχή κειμένου",
+HiddenField : "Κρυφό πεδίο",
+Button : "Κουμπί",
+SelectionField : "Πεδίο επιλογής",
+ImageButton : "Κουμπί εικόνας",
+
+FitWindow : "Μεγιστοποίηση προγράμματος",
+
+// Context Menu
+EditLink : "Μεταβολή Συνδέσμου (Link)",
+CellCM : "Κελί",
+RowCM : "Σειρά",
+ColumnCM : "Στήλη",
+InsertRow : "Εισαγωγή Γραμμής",
+DeleteRows : "Διαγραφή Γραμμών",
+InsertColumn : "Εισαγωγή Κολώνας",
+DeleteColumns : "Διαγραφή Κολωνών",
+InsertCell : "Εισαγωγή Κελιού",
+DeleteCells : "Διαγραφή Κελιών",
+MergeCells : "Ενοποίηση Κελιών",
+SplitCell : "Διαχωρισμός Κελιού",
+TableDelete : "Διαγραφή πίνακα",
+CellProperties : "Ιδιότητες Κελιού",
+TableProperties : "Ιδιότητες Πίνακα",
+ImageProperties : "Ιδιότητες Εικόνας",
+FlashProperties : "Ιδιότητες Flash",
+
+AnchorProp : "Ιδιότητες άγκυρας",
+ButtonProp : "Ιδιότητες κουμπιού",
+CheckboxProp : "Ιδιότητες κουμπιού επιλογής",
+HiddenFieldProp : "Ιδιότητες κρυφού πεδίου",
+RadioButtonProp : "Ιδιότητες κουμπιού radio",
+ImageButtonProp : "Ιδιότητες κουμπιού εικόνας",
+TextFieldProp : "Ιδιότητες πεδίου κειμένου",
+SelectionFieldProp : "Ιδιότητες πεδίου επιλογής",
+TextareaProp : "Ιδιότητες περιοχής κειμένου",
+FormProp : "Ιδιότητες φόρμας",
+
+FontFormats : "Κανονικό;Μορφοποιημένο;Διεύθυνση;Επικεφαλίδα 1;Επικεφαλίδα 2;Επικεφαλίδα 3;Επικεφαλίδα 4;Επικεφαλίδα 5;Επικεφαλίδα 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Επεξεργασία XHTML. Παρακαλώ περιμένετε...",
+Done : "Έτοιμο",
+PasteWordConfirm : "Το κείμενο που θέλετε να επικολήσετε, φαίνεται πως προέρχεται από το Word. Θέλετε να καθαριστεί πριν επικοληθεί;",
+NotCompatiblePaste : "Αυτή η επιλογή είναι διαθέσιμη στον Internet Explorer έκδοση 5.5+. Θέλετε να γίνει η επικόλληση χωρίς καθαρισμό;",
+UnknownToolbarItem : "Άγνωστο αντικείμενο της μπάρας εργαλείων \"%1\"",
+UnknownCommand : "Άγνωστή εντολή \"%1\"",
+NotImplemented : "Η εντολή δεν έχει ενεργοποιηθεί",
+UnknownToolbarSet : "Η μπάρα εργαλείων \"%1\" δεν υπάρχει",
+NoActiveX : "Οι ρυθμίσεις ασφαλείας του browser σας μπορεί να περιορίσουν κάποιες ρυθμίσεις του προγράμματος. Χρειάζεται να ενεργοποιήσετε την επιλογή \"Run ActiveX controls and plug-ins\". Ίσως παρουσιαστούν λάθη και παρατηρήσετε ελειπείς λειτουργίες.",
+BrowseServerBlocked : "Οι πόροι του browser σας δεν είναι προσπελάσιμοι. Σιγουρευτείτε ότι δεν υπάρχουν ενεργοί popup blockers.",
+DialogBlocked : "Δεν ήταν δυνατό να ανοίξει το παράθυρο διαλόγου. Σιγουρευτείτε ότι δεν υπάρχουν ενεργοί popup blockers.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Ακύρωση",
+DlgBtnClose : "Κλείσιμο",
+DlgBtnBrowseServer : "Εξερεύνηση διακομιστή",
+DlgAdvancedTag : "Για προχωρημένους",
+DlgOpOther : "<Άλλα>",
+DlgInfoTab : "Πληροφορίες",
+DlgAlertUrl : "Παρακαλώ εισάγετε URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<χωρίς>",
+DlgGenId : "Id",
+DlgGenLangDir : "Κατεύθυνση κειμένου",
+DlgGenLangDirLtr : "Αριστερά προς Δεξιά (LTR)",
+DlgGenLangDirRtl : "Δεξιά προς Αριστερά (RTL)",
+DlgGenLangCode : "Κωδικός Γλώσσας",
+DlgGenAccessKey : "Συντόμευση (Access Key)",
+DlgGenName : "Όνομα",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Αναλυτική περιγραφή URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Συμβουλευτικός τίτλος",
+DlgGenContType : "Συμβουλευτικός τίτλος περιεχομένου",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Στύλ",
+
+// Image Dialog
+DlgImgTitle : "Ιδιότητες Εικόνας",
+DlgImgInfoTab : "Πληροφορίες Εικόνας",
+DlgImgBtnUpload : "Αποστολή στον Διακομιστή",
+DlgImgURL : "URL",
+DlgImgUpload : "Αποστολή",
+DlgImgAlt : "Εναλλακτικό Κείμενο (ALT)",
+DlgImgWidth : "Πλάτος",
+DlgImgHeight : "Ύψος",
+DlgImgLockRatio : "Κλείδωμα Αναλογίας",
+DlgBtnResetSize : "Επαναφορά Αρχικού Μεγέθους",
+DlgImgBorder : "Περιθώριο",
+DlgImgHSpace : "Οριζόντιος Χώρος (HSpace)",
+DlgImgVSpace : "Κάθετος Χώρος (VSpace)",
+DlgImgAlign : "Ευθυγράμμιση (Align)",
+DlgImgAlignLeft : "Αριστερά",
+DlgImgAlignAbsBottom: "Απόλυτα Κάτω (Abs Bottom)",
+DlgImgAlignAbsMiddle: "Απόλυτα στη Μέση (Abs Middle)",
+DlgImgAlignBaseline : "Γραμμή Βάσης (Baseline)",
+DlgImgAlignBottom : "Κάτω (Bottom)",
+DlgImgAlignMiddle : "Μέση (Middle)",
+DlgImgAlignRight : "Δεξιά (Right)",
+DlgImgAlignTextTop : "Κορυφή Κειμένου (Text Top)",
+DlgImgAlignTop : "Πάνω (Top)",
+DlgImgPreview : "Προεπισκόπιση",
+DlgImgAlertUrl : "Εισάγετε την τοποθεσία (URL) της εικόνας",
+DlgImgLinkTab : "Σύνδεσμος",
+
+// Flash Dialog
+DlgFlashTitle : "Ιδιότητες flash",
+DlgFlashChkPlay : "Αυτόματη έναρξη",
+DlgFlashChkLoop : "Επανάληψη",
+DlgFlashChkMenu : "Ενεργοποίηση Flash Menu",
+DlgFlashScale : "Κλίμακα",
+DlgFlashScaleAll : "Εμφάνιση όλων",
+DlgFlashScaleNoBorder : "Χωρίς όρια",
+DlgFlashScaleFit : "Ακριβής εφαρμογή",
+
+// Link Dialog
+DlgLnkWindowTitle : "Σύνδεσμος (Link)",
+DlgLnkInfoTab : "Link",
+DlgLnkTargetTab : "Παράθυρο Στόχος (Target)",
+
+DlgLnkType : "Τύπος συνδέσμου (Link)",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Άγκυρα σε αυτή τη σελίδα",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Προτόκολο",
+DlgLnkProtoOther : "<άλλο>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Επιλέξτε μια άγκυρα",
+DlgLnkAnchorByName : "Βάσει του Ονόματος (Name) της άγκυρας",
+DlgLnkAnchorById : "Βάσει του Element Id",
+DlgLnkNoAnchors : "<Δεν υπάρχουν άγκυρες στο κείμενο>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Διεύθυνση Ηλεκτρονικού Ταχυδρομείου",
+DlgLnkEMailSubject : "Θέμα Μηνύματος",
+DlgLnkEMailBody : "Κείμενο Μηνύματος",
+DlgLnkUpload : "Αποστολή",
+DlgLnkBtnUpload : "Αποστολή στον Διακομιστή",
+
+DlgLnkTarget : "Παράθυρο Στόχος (Target)",
+DlgLnkTargetFrame : "<πλαίσιο>",
+DlgLnkTargetPopup : "<παράθυρο popup>",
+DlgLnkTargetBlank : "Νέο Παράθυρο (_blank)",
+DlgLnkTargetParent : "Γονικό Παράθυρο (_parent)",
+DlgLnkTargetSelf : "Ίδιο Παράθυρο (_self)",
+DlgLnkTargetTop : "Ανώτατο Παράθυρο (_top)",
+DlgLnkTargetFrameName : "Όνομα πλαισίου στόχου",
+DlgLnkPopWinName : "Όνομα Popup Window",
+DlgLnkPopWinFeat : "Επιλογές Popup Window",
+DlgLnkPopResize : "Με αλλαγή Μεγέθους",
+DlgLnkPopLocation : "Μπάρα Τοποθεσίας",
+DlgLnkPopMenu : "Μπάρα Menu",
+DlgLnkPopScroll : "Μπάρες Κύλισης",
+DlgLnkPopStatus : "Μπάρα Status",
+DlgLnkPopToolbar : "Μπάρα Εργαλείων",
+DlgLnkPopFullScrn : "Ολόκληρη η Οθόνη (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Πλάτος",
+DlgLnkPopHeight : "Ύψος",
+DlgLnkPopLeft : "Τοποθεσία Αριστερής Άκρης",
+DlgLnkPopTop : "Τοποθεσία Πάνω Άκρης",
+
+DlnLnkMsgNoUrl : "Εισάγετε την τοποθεσία (URL) του υπερσυνδέσμου (Link)",
+DlnLnkMsgNoEMail : "Εισάγετε την διεύθυνση ηλεκτρονικού ταχυδρομείου",
+DlnLnkMsgNoAnchor : "Επιλέξτε ένα Anchor",
+DlnLnkMsgInvPopName : "Το όνομα του popup πρέπει να αρχίζει με χαρακτήρα της αλφαβήτου και να μην περιέχει κενά",
+
+// Color Dialog
+DlgColorTitle : "Επιλογή χρώματος",
+DlgColorBtnClear : "Καθαρισμός",
+DlgColorHighlight : "Προεπισκόπιση",
+DlgColorSelected : "Επιλεγμένο",
+
+// Smiley Dialog
+DlgSmileyTitle : "Επιλέξτε ένα Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Επιλέξτε ένα Ειδικό Σύμβολο",
+
+// Table Dialog
+DlgTableTitle : "Ιδιότητες Πίνακα",
+DlgTableRows : "Γραμμές",
+DlgTableColumns : "Κολώνες",
+DlgTableBorder : "Μέγεθος Περιθωρίου",
+DlgTableAlign : "Στοίχιση",
+DlgTableAlignNotSet : "<χωρίς>",
+DlgTableAlignLeft : "Αριστερά",
+DlgTableAlignCenter : "Κέντρο",
+DlgTableAlignRight : "Δεξιά",
+DlgTableWidth : "Πλάτος",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "\%",
+DlgTableHeight : "Ύψος",
+DlgTableCellSpace : "Απόσταση κελιών",
+DlgTableCellPad : "Γέμισμα κελιών",
+DlgTableCaption : "Υπέρτιτλος",
+DlgTableSummary : "Περίληψη",
+
+// Table Cell Dialog
+DlgCellTitle : "Ιδιότητες Κελιού",
+DlgCellWidth : "Πλάτος",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "\%",
+DlgCellHeight : "Ύψος",
+DlgCellWordWrap : "Με αλλαγή γραμμής",
+DlgCellWordWrapNotSet : "<χωρίς>",
+DlgCellWordWrapYes : "Ναι",
+DlgCellWordWrapNo : "Όχι",
+DlgCellHorAlign : "Οριζόντια Στοίχιση",
+DlgCellHorAlignNotSet : "<χωρίς>",
+DlgCellHorAlignLeft : "Αριστερά",
+DlgCellHorAlignCenter : "Κέντρο",
+DlgCellHorAlignRight: "Δεξιά",
+DlgCellVerAlign : "Κάθετη Στοίχιση",
+DlgCellVerAlignNotSet : "<χωρίς>",
+DlgCellVerAlignTop : "Πάνω (Top)",
+DlgCellVerAlignMiddle : "Μέση (Middle)",
+DlgCellVerAlignBottom : "Κάτω (Bottom)",
+DlgCellVerAlignBaseline : "Γραμμή Βάσης (Baseline)",
+DlgCellRowSpan : "Αριθμός Γραμμών (Rows Span)",
+DlgCellCollSpan : "Αριθμός Κολωνών (Columns Span)",
+DlgCellBackColor : "Χρώμα Υποβάθρου",
+DlgCellBorderColor : "Χρώμα Περιθωρίου",
+DlgCellBtnSelect : "Επιλογή...",
+
+// Find Dialog
+DlgFindTitle : "Αναζήτηση",
+DlgFindFindBtn : "Αναζήτηση",
+DlgFindNotFoundMsg : "Το κείμενο δεν βρέθηκε.",
+
+// Replace Dialog
+DlgReplaceTitle : "Αντικατάσταση",
+DlgReplaceFindLbl : "Αναζήτηση:",
+DlgReplaceReplaceLbl : "Αντικατάσταση με:",
+DlgReplaceCaseChk : "Έλεγχος πεζών/κεφαλαίων",
+DlgReplaceReplaceBtn : "Αντικατάσταση",
+DlgReplaceReplAllBtn : "Αντικατάσταση Όλων",
+DlgReplaceWordChk : "Εύρεση πλήρους λέξης",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Οι ρυθμίσεις ασφαλείας του φυλλομετρητή σας δεν επιτρέπουν την επιλεγμένη εργασία αποκοπής. Χρησιμοποιείστε το πληκτρολόγιο (Ctrl+X).",
+PasteErrorCopy : "Οι ρυθμίσεις ασφαλείας του φυλλομετρητή σας δεν επιτρέπουν την επιλεγμένη εργασία αντιγραφής. Χρησιμοποιείστε το πληκτρολόγιο (Ctrl+C).",
+
+PasteAsText : "Επικόλληση ως Απλό Κείμενο",
+PasteFromWord : "Επικόλληση από το Word",
+
+DlgPasteMsg2 : "Παρακαλώ επικολήστε στο ακόλουθο κουτί χρησιμοποιόντας το πληκτρολόγιο (<STRONG>Ctrl+V</STRONG>) και πατήστε <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Αγνόηση προδιαγραφών γραμματοσειράς",
+DlgPasteRemoveStyles : "Αφαίρεση προδιαγραφών στύλ",
+DlgPasteCleanBox : "Κουτί εκαθάρισης",
+
+// Color Picker
+ColorAutomatic : "Αυτόματο",
+ColorMoreColors : "Περισσότερα χρώματα...",
+
+// Document Properties
+DocProps : "Ιδιότητες εγγράφου",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ιδιότητες άγκυρας",
+DlgAnchorName : "Όνομα άγκυρας",
+DlgAnchorErrorName : "Παρακαλούμε εισάγετε όνομα άγκυρας",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Δεν υπάρχει στο λεξικό",
+DlgSpellChangeTo : "Αλλαγή σε",
+DlgSpellBtnIgnore : "Αγνόηση",
+DlgSpellBtnIgnoreAll : "Αγνόηση όλων",
+DlgSpellBtnReplace : "Αντικατάσταση",
+DlgSpellBtnReplaceAll : "Αντικατάσταση όλων",
+DlgSpellBtnUndo : "Αναίρεση",
+DlgSpellNoSuggestions : "- Δεν υπάρχουν προτάσεις -",
+DlgSpellProgress : "Ορθογραφικός έλεγχος σε εξέλιξη...",
+DlgSpellNoMispell : "Ο ορθογραφικός έλεγχος ολοκληρώθηκε: Δεν βρέθηκαν λάθη",
+DlgSpellNoChanges : "Ο ορθογραφικός έλεγχος ολοκληρώθηκε: Δεν άλλαξαν λέξεις",
+DlgSpellOneChange : "Ο ορθογραφικός έλεγχος ολοκληρώθηκε: Μια λέξη άλλαξε",
+DlgSpellManyChanges : "Ο ορθογραφικός έλεγχος ολοκληρώθηκε: %1 λέξεις άλλαξαν",
+
+IeSpellDownload : "Δεν υπάρχει εγκατεστημένος ορθογράφος. Θέλετε να τον κατεβάσετε τώρα;",
+
+// Button Dialog
+DlgButtonText : "Κείμενο (Τιμή)",
+DlgButtonType : "Τύπος",
+DlgButtonTypeBtn : "Κουμπί",
+DlgButtonTypeSbm : "Καταχώρηση",
+DlgButtonTypeRst : "Επαναφορά",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Όνομα",
+DlgCheckboxValue : "Τιμή",
+DlgCheckboxSelected : "Επιλεγμένο",
+
+// Form Dialog
+DlgFormName : "Όνομα",
+DlgFormAction : "Δράση",
+DlgFormMethod : "Μάθοδος",
+
+// Select Field Dialog
+DlgSelectName : "Όνομα",
+DlgSelectValue : "Τιμή",
+DlgSelectSize : "Μέγεθος",
+DlgSelectLines : "γραμμές",
+DlgSelectChkMulti : "Πολλαπλές επιλογές",
+DlgSelectOpAvail : "Διαθέσιμες επιλογές",
+DlgSelectOpText : "Κείμενο",
+DlgSelectOpValue : "Τιμή",
+DlgSelectBtnAdd : "Προσθήκη",
+DlgSelectBtnModify : "Αλλαγή",
+DlgSelectBtnUp : "Πάνω",
+DlgSelectBtnDown : "Κάτω",
+DlgSelectBtnSetValue : "Προεπιλεγμένη επιλογή",
+DlgSelectBtnDelete : "Διαγραφή",
+
+// Textarea Dialog
+DlgTextareaName : "Όνομα",
+DlgTextareaCols : "Στήλες",
+DlgTextareaRows : "Σειρές",
+
+// Text Field Dialog
+DlgTextName : "Όνομα",
+DlgTextValue : "Τιμή",
+DlgTextCharWidth : "Μήκος χαρακτήρων",
+DlgTextMaxChars : "Μέγιστοι χαρακτήρες",
+DlgTextType : "Τύπος",
+DlgTextTypeText : "Κείμενο",
+DlgTextTypePass : "Κωδικός",
+
+// Hidden Field Dialog
+DlgHiddenName : "Όνομα",
+DlgHiddenValue : "Τιμή",
+
+// Bulleted List Dialog
+BulletedListProp : "Ιδιότητες λίστας Bulleted",
+NumberedListProp : "Ιδιότητες αριθμημένης λίστας ",
+DlgLstStart : "Αρχή",
+DlgLstType : "Τύπος",
+DlgLstTypeCircle : "Κύκλος",
+DlgLstTypeDisc : "Δίσκος",
+DlgLstTypeSquare : "Τετράγωνο",
+DlgLstTypeNumbers : "Αριθμοί (1, 2, 3)",
+DlgLstTypeLCase : "Πεζά γράμματα (a, b, c)",
+DlgLstTypeUCase : "Κεφαλαία γράμματα (A, B, C)",
+DlgLstTypeSRoman : "Μικρά λατινικά αριθμητικά (i, ii, iii)",
+DlgLstTypeLRoman : "Μεγάλα λατινικά αριθμητικά (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Γενικά",
+DlgDocBackTab : "Φόντο",
+DlgDocColorsTab : "Χρώματα και περιθώρια",
+DlgDocMetaTab : "Δεδομένα Meta",
+
+DlgDocPageTitle : "Τίτλος σελίδας",
+DlgDocLangDir : "Κατεύθυνση γραφής",
+DlgDocLangDirLTR : "αριστερά προς δεξιά (LTR)",
+DlgDocLangDirRTL : "δεξιά προς αριστερά (RTL)",
+DlgDocLangCode : "Κωδικός γλώσσας",
+DlgDocCharSet : "Κωδικοποίηση χαρακτήρων",
+DlgDocCharSetCE : "Κεντρικής Ευρώπης",
+DlgDocCharSetCT : "Παραδοσιακά κινέζικα (Big5)",
+DlgDocCharSetCR : "Κυριλλική",
+DlgDocCharSetGR : "Ελληνική",
+DlgDocCharSetJP : "Ιαπωνική",
+DlgDocCharSetKR : "Κορεάτικη",
+DlgDocCharSetTR : "Τουρκική",
+DlgDocCharSetUN : "Διεθνής (UTF-8)",
+DlgDocCharSetWE : "Δυτικής Ευρώπης",
+DlgDocCharSetOther : "Άλλη κωδικοποίηση χαρακτήρων",
+
+DlgDocDocType : "Επικεφαλίδα τύπου εγγράφου",
+DlgDocDocTypeOther : "Άλλη επικεφαλίδα τύπου εγγράφου",
+DlgDocIncXHTML : "Να συμπεριληφθούν οι δηλώσεις XHTML",
+DlgDocBgColor : "Χρώμα φόντου",
+DlgDocBgImage : "Διεύθυνση εικόνας φόντου",
+DlgDocBgNoScroll : "Φόντο χωρίς κύλιση",
+DlgDocCText : "Κείμενο",
+DlgDocCLink : "Σύνδεσμος",
+DlgDocCVisited : "Σύνδεσμος που έχει επισκευθεί",
+DlgDocCActive : "Ενεργός σύνδεσμος",
+DlgDocMargins : "Περιθώρια σελίδας",
+DlgDocMaTop : "Κορυφή",
+DlgDocMaLeft : "Αριστερά",
+DlgDocMaRight : "Δεξιά",
+DlgDocMaBottom : "Κάτω",
+DlgDocMeIndex : "Λέξεις κλειδιά δείκτες εγγράφου (διαχωρισμός με κόμμα)",
+DlgDocMeDescr : "Περιγραφή εγγράφου",
+DlgDocMeAuthor : "Συγγραφέας",
+DlgDocMeCopy : "Πνευματικά δικαιώματα",
+DlgDocPreview : "Προεπισκόπηση",
+
+// Templates Dialog
+Templates : "Πρότυπα",
+DlgTemplatesTitle : "Πρότυπα περιεχομένου",
+DlgTemplatesSelMsg : "Παρακαλώ επιλέξτε πρότυπο για εισαγωγή στο πρόγραμμα<br>(τα υπάρχοντα περιεχόμενα θα χαθούν):",
+DlgTemplatesLoading : "Φόρτωση καταλόγου προτύπων. Παρακαλώ περιμένετε...",
+DlgTemplatesNoTpl : "(Δεν έχουν καθοριστεί πρότυπα)",
+DlgTemplatesReplace : "Αντικατάσταση υπάρχοντων περιεχομένων",
+
+// About Dialog
+DlgAboutAboutTab : "Σχετικά",
+DlgAboutBrowserInfoTab : "Πληροφορίες Browser",
+DlgAboutLicenseTab : "Άδεια",
+DlgAboutVersion : "έκδοση",
+DlgAboutInfo : "Για περισσότερες πληροφορίες"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/en-au.js b/httemplate/elements/fckeditor/editor/lang/en-au.js
new file mode 100644
index 000000000..b6960b6b3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/en-au.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * English (Australia) language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Collapse Toolbar",
+ToolbarExpand : "Expand Toolbar",
+
+// Toolbar Items and Context Menu
+Save : "Save",
+NewPage : "New Page",
+Preview : "Preview",
+Cut : "Cut",
+Copy : "Copy",
+Paste : "Paste",
+PasteText : "Paste as plain text",
+PasteWord : "Paste from Word",
+Print : "Print",
+SelectAll : "Select All",
+RemoveFormat : "Remove Format",
+InsertLinkLbl : "Link",
+InsertLink : "Insert/Edit Link",
+RemoveLink : "Remove Link",
+Anchor : "Insert/Edit Anchor",
+InsertImageLbl : "Image",
+InsertImage : "Insert/Edit Image",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insert/Edit Flash",
+InsertTableLbl : "Table",
+InsertTable : "Insert/Edit Table",
+InsertLineLbl : "Line",
+InsertLine : "Insert Horizontal Line",
+InsertSpecialCharLbl: "Special Character",
+InsertSpecialChar : "Insert Special Character",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Insert Smiley",
+About : "About FCKeditor",
+Bold : "Bold",
+Italic : "Italic",
+Underline : "Underline",
+StrikeThrough : "Strike Through",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Left Justify",
+CenterJustify : "Centre Justify",
+RightJustify : "Right Justify",
+BlockJustify : "Block Justify",
+DecreaseIndent : "Decrease Indent",
+IncreaseIndent : "Increase Indent",
+Undo : "Undo",
+Redo : "Redo",
+NumberedListLbl : "Numbered List",
+NumberedList : "Insert/Remove Numbered List",
+BulletedListLbl : "Bulleted List",
+BulletedList : "Insert/Remove Bulleted List",
+ShowTableBorders : "Show Table Borders",
+ShowDetails : "Show Details",
+Style : "Style",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Size",
+TextColor : "Text Colour",
+BGColor : "Background Colour",
+Source : "Source",
+Find : "Find",
+Replace : "Replace",
+SpellCheck : "Check Spelling",
+UniversalKeyboard : "Universal Keyboard",
+PageBreakLbl : "Page Break",
+PageBreak : "Insert Page Break",
+
+Form : "Form",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Hidden Field",
+Button : "Button",
+SelectionField : "Selection Field",
+ImageButton : "Image Button",
+
+FitWindow : "Maximize the editor size",
+
+// Context Menu
+EditLink : "Edit Link",
+CellCM : "Cell",
+RowCM : "Row",
+ColumnCM : "Column",
+InsertRow : "Insert Row",
+DeleteRows : "Delete Rows",
+InsertColumn : "Insert Column",
+DeleteColumns : "Delete Columns",
+InsertCell : "Insert Cell",
+DeleteCells : "Delete Cells",
+MergeCells : "Merge Cells",
+SplitCell : "Split Cell",
+TableDelete : "Delete Table",
+CellProperties : "Cell Properties",
+TableProperties : "Table Properties",
+ImageProperties : "Image Properties",
+FlashProperties : "Flash Properties",
+
+AnchorProp : "Anchor Properties",
+ButtonProp : "Button Properties",
+CheckboxProp : "Checkbox Properties",
+HiddenFieldProp : "Hidden Field Properties",
+RadioButtonProp : "Radio Button Properties",
+ImageButtonProp : "Image Button Properties",
+TextFieldProp : "Text Field Properties",
+SelectionFieldProp : "Selection Field Properties",
+TextareaProp : "Textarea Properties",
+FormProp : "Form Properties",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processing XHTML. Please wait...",
+Done : "Done",
+PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?",
+NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?",
+UnknownToolbarItem : "Unknown toolbar item \"%1\"",
+UnknownCommand : "Unknown command name \"%1\"",
+NotImplemented : "Command not implemented",
+UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.",
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.",
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancel",
+DlgBtnClose : "Close",
+DlgBtnBrowseServer : "Browse Server",
+DlgAdvancedTag : "Advanced",
+DlgOpOther : "<Other>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Please insert the URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<not set>",
+DlgGenId : "Id",
+DlgGenLangDir : "Language Direction",
+DlgGenLangDirLtr : "Left to Right (LTR)",
+DlgGenLangDirRtl : "Right to Left (RTL)",
+DlgGenLangCode : "Language Code",
+DlgGenAccessKey : "Access Key",
+DlgGenName : "Name",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Long Description URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Image Properties",
+DlgImgInfoTab : "Image Info",
+DlgImgBtnUpload : "Send it to the Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternative Text",
+DlgImgWidth : "Width",
+DlgImgHeight : "Height",
+DlgImgLockRatio : "Lock Ratio",
+DlgBtnResetSize : "Reset Size",
+DlgImgBorder : "Border",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Align",
+DlgImgAlignLeft : "Left",
+DlgImgAlignAbsBottom: "Abs Bottom",
+DlgImgAlignAbsMiddle: "Abs Middle",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Bottom",
+DlgImgAlignMiddle : "Middle",
+DlgImgAlignRight : "Right",
+DlgImgAlignTextTop : "Text Top",
+DlgImgAlignTop : "Top",
+DlgImgPreview : "Preview",
+DlgImgAlertUrl : "Please type the image URL",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties",
+DlgFlashChkPlay : "Auto Play",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Enable Flash Menu",
+DlgFlashScale : "Scale",
+DlgFlashScaleAll : "Show all",
+DlgFlashScaleNoBorder : "No Border",
+DlgFlashScaleFit : "Exact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Target",
+
+DlgLnkType : "Link Type",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Link to anchor in the text",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<other>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Select an Anchor",
+DlgLnkAnchorByName : "By Anchor Name",
+DlgLnkAnchorById : "By Element Id",
+DlgLnkNoAnchors : "(No anchors available in the document)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Address",
+DlgLnkEMailSubject : "Message Subject",
+DlgLnkEMailBody : "Message Body",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Send it to the Server",
+
+DlgLnkTarget : "Target",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<popup window>",
+DlgLnkTargetBlank : "New Window (_blank)",
+DlgLnkTargetParent : "Parent Window (_parent)",
+DlgLnkTargetSelf : "Same Window (_self)",
+DlgLnkTargetTop : "Topmost Window (_top)",
+DlgLnkTargetFrameName : "Target Frame Name",
+DlgLnkPopWinName : "Popup Window Name",
+DlgLnkPopWinFeat : "Popup Window Features",
+DlgLnkPopResize : "Resizable",
+DlgLnkPopLocation : "Location Bar",
+DlgLnkPopMenu : "Menu Bar",
+DlgLnkPopScroll : "Scroll Bars",
+DlgLnkPopStatus : "Status Bar",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Full Screen (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Width",
+DlgLnkPopHeight : "Height",
+DlgLnkPopLeft : "Left Position",
+DlgLnkPopTop : "Top Position",
+
+DlnLnkMsgNoUrl : "Please type the link URL",
+DlnLnkMsgNoEMail : "Please type the e-mail address",
+DlnLnkMsgNoAnchor : "Please select an anchor",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces",
+
+// Color Dialog
+DlgColorTitle : "Select Colour",
+DlgColorBtnClear : "Clear",
+DlgColorHighlight : "Highlight",
+DlgColorSelected : "Selected",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insert a Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Select Special Character",
+
+// Table Dialog
+DlgTableTitle : "Table Properties",
+DlgTableRows : "Rows",
+DlgTableColumns : "Columns",
+DlgTableBorder : "Border size",
+DlgTableAlign : "Alignment",
+DlgTableAlignNotSet : "<Not set>",
+DlgTableAlignLeft : "Left",
+DlgTableAlignCenter : "Centre",
+DlgTableAlignRight : "Right",
+DlgTableWidth : "Width",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Height",
+DlgTableCellSpace : "Cell spacing",
+DlgTableCellPad : "Cell padding",
+DlgTableCaption : "Caption",
+DlgTableSummary : "Summary",
+
+// Table Cell Dialog
+DlgCellTitle : "Cell Properties",
+DlgCellWidth : "Width",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Height",
+DlgCellWordWrap : "Word Wrap",
+DlgCellWordWrapNotSet : "<Not set>",
+DlgCellWordWrapYes : "Yes",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Horizontal Alignment",
+DlgCellHorAlignNotSet : "<Not set>",
+DlgCellHorAlignLeft : "Left",
+DlgCellHorAlignCenter : "Centre",
+DlgCellHorAlignRight: "Right",
+DlgCellVerAlign : "Vertical Alignment",
+DlgCellVerAlignNotSet : "<Not set>",
+DlgCellVerAlignTop : "Top",
+DlgCellVerAlignMiddle : "Middle",
+DlgCellVerAlignBottom : "Bottom",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rows Span",
+DlgCellCollSpan : "Columns Span",
+DlgCellBackColor : "Background Colour",
+DlgCellBorderColor : "Border Colour",
+DlgCellBtnSelect : "Select...",
+
+// Find Dialog
+DlgFindTitle : "Find",
+DlgFindFindBtn : "Find",
+DlgFindNotFoundMsg : "The specified text was not found.",
+
+// Replace Dialog
+DlgReplaceTitle : "Replace",
+DlgReplaceFindLbl : "Find what:",
+DlgReplaceReplaceLbl : "Replace with:",
+DlgReplaceCaseChk : "Match case",
+DlgReplaceReplaceBtn : "Replace",
+DlgReplaceReplAllBtn : "Replace All",
+DlgReplaceWordChk : "Match whole word",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).",
+PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).",
+
+PasteAsText : "Paste as Plain Text",
+PasteFromWord : "Paste from Word",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<STRONG>Ctrl+V</STRONG>) and hit <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.",
+DlgPasteIgnoreFont : "Ignore Font Face definitions",
+DlgPasteRemoveStyles : "Remove Styles definitions",
+DlgPasteCleanBox : "Clean Up Box",
+
+// Color Picker
+ColorAutomatic : "Automatic",
+ColorMoreColors : "More Colours...",
+
+// Document Properties
+DocProps : "Document Properties",
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties",
+DlgAnchorName : "Anchor Name",
+DlgAnchorErrorName : "Please type the anchor name",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary",
+DlgSpellChangeTo : "Change to",
+DlgSpellBtnIgnore : "Ignore",
+DlgSpellBtnIgnoreAll : "Ignore All",
+DlgSpellBtnReplace : "Replace",
+DlgSpellBtnReplaceAll : "Replace All",
+DlgSpellBtnUndo : "Undo",
+DlgSpellNoSuggestions : "- No suggestions -",
+DlgSpellProgress : "Spell check in progress...",
+DlgSpellNoMispell : "Spell check complete: No misspellings found",
+DlgSpellNoChanges : "Spell check complete: No words changed",
+DlgSpellOneChange : "Spell check complete: One word changed",
+DlgSpellManyChanges : "Spell check complete: %1 words changed",
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?",
+
+// Button Dialog
+DlgButtonText : "Text (Value)",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name",
+DlgCheckboxValue : "Value",
+DlgCheckboxSelected : "Selected",
+
+// Form Dialog
+DlgFormName : "Name",
+DlgFormAction : "Action",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Name",
+DlgSelectValue : "Value",
+DlgSelectSize : "Size",
+DlgSelectLines : "lines",
+DlgSelectChkMulti : "Allow multiple selections",
+DlgSelectOpAvail : "Available Options",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Value",
+DlgSelectBtnAdd : "Add",
+DlgSelectBtnModify : "Modify",
+DlgSelectBtnUp : "Up",
+DlgSelectBtnDown : "Down",
+DlgSelectBtnSetValue : "Set as selected value",
+DlgSelectBtnDelete : "Delete",
+
+// Textarea Dialog
+DlgTextareaName : "Name",
+DlgTextareaCols : "Columns",
+DlgTextareaRows : "Rows",
+
+// Text Field Dialog
+DlgTextName : "Name",
+DlgTextValue : "Value",
+DlgTextCharWidth : "Character Width",
+DlgTextMaxChars : "Maximum Characters",
+DlgTextType : "Type",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Password",
+
+// Hidden Field Dialog
+DlgHiddenName : "Name",
+DlgHiddenValue : "Value",
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties",
+NumberedListProp : "Numbered List Properties",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Circle",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Square",
+DlgLstTypeNumbers : "Numbers (1, 2, 3)",
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)",
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)",
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)",
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Background",
+DlgDocColorsTab : "Colours and Margins",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Page Title",
+DlgDocLangDir : "Language Direction",
+DlgDocLangDirLTR : "Left to Right (LTR)",
+DlgDocLangDirRTL : "Right to Left (RTL)",
+DlgDocLangCode : "Language Code",
+DlgDocCharSet : "Character Set Encoding",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "Other Character Set Encoding",
+
+DlgDocDocType : "Document Type Heading",
+DlgDocDocTypeOther : "Other Document Type Heading",
+DlgDocIncXHTML : "Include XHTML Declarations",
+DlgDocBgColor : "Background Colour",
+DlgDocBgImage : "Background Image URL",
+DlgDocBgNoScroll : "Nonscrolling Background",
+DlgDocCText : "Text",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Visited Link",
+DlgDocCActive : "Active Link",
+DlgDocMargins : "Page Margins",
+DlgDocMaTop : "Top",
+DlgDocMaLeft : "Left",
+DlgDocMaRight : "Right",
+DlgDocMaBottom : "Bottom",
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)",
+DlgDocMeDescr : "Document Description",
+DlgDocMeAuthor : "Author",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Preview",
+
+// Templates Dialog
+Templates : "Templates",
+DlgTemplatesTitle : "Content Templates",
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br>(the actual contents will be lost):",
+DlgTemplatesLoading : "Loading templates list. Please wait...",
+DlgTemplatesNoTpl : "(No templates defined)",
+DlgTemplatesReplace : "Replace actual contents",
+
+// About Dialog
+DlgAboutAboutTab : "About",
+DlgAboutBrowserInfoTab : "Browser Info",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "For further information go to"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/en-ca.js b/httemplate/elements/fckeditor/editor/lang/en-ca.js
new file mode 100644
index 000000000..2900a9d35
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/en-ca.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * English (Canadian) language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Collapse Toolbar",
+ToolbarExpand : "Expand Toolbar",
+
+// Toolbar Items and Context Menu
+Save : "Save",
+NewPage : "New Page",
+Preview : "Preview",
+Cut : "Cut",
+Copy : "Copy",
+Paste : "Paste",
+PasteText : "Paste as plain text",
+PasteWord : "Paste from Word",
+Print : "Print",
+SelectAll : "Select All",
+RemoveFormat : "Remove Format",
+InsertLinkLbl : "Link",
+InsertLink : "Insert/Edit Link",
+RemoveLink : "Remove Link",
+Anchor : "Insert/Edit Anchor",
+InsertImageLbl : "Image",
+InsertImage : "Insert/Edit Image",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insert/Edit Flash",
+InsertTableLbl : "Table",
+InsertTable : "Insert/Edit Table",
+InsertLineLbl : "Line",
+InsertLine : "Insert Horizontal Line",
+InsertSpecialCharLbl: "Special Character",
+InsertSpecialChar : "Insert Special Character",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Insert Smiley",
+About : "About FCKeditor",
+Bold : "Bold",
+Italic : "Italic",
+Underline : "Underline",
+StrikeThrough : "Strike Through",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Left Justify",
+CenterJustify : "Centre Justify",
+RightJustify : "Right Justify",
+BlockJustify : "Block Justify",
+DecreaseIndent : "Decrease Indent",
+IncreaseIndent : "Increase Indent",
+Undo : "Undo",
+Redo : "Redo",
+NumberedListLbl : "Numbered List",
+NumberedList : "Insert/Remove Numbered List",
+BulletedListLbl : "Bulleted List",
+BulletedList : "Insert/Remove Bulleted List",
+ShowTableBorders : "Show Table Borders",
+ShowDetails : "Show Details",
+Style : "Style",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Size",
+TextColor : "Text Colour",
+BGColor : "Background Colour",
+Source : "Source",
+Find : "Find",
+Replace : "Replace",
+SpellCheck : "Check Spelling",
+UniversalKeyboard : "Universal Keyboard",
+PageBreakLbl : "Page Break",
+PageBreak : "Insert Page Break",
+
+Form : "Form",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Hidden Field",
+Button : "Button",
+SelectionField : "Selection Field",
+ImageButton : "Image Button",
+
+FitWindow : "Maximize the editor size",
+
+// Context Menu
+EditLink : "Edit Link",
+CellCM : "Cell",
+RowCM : "Row",
+ColumnCM : "Column",
+InsertRow : "Insert Row",
+DeleteRows : "Delete Rows",
+InsertColumn : "Insert Column",
+DeleteColumns : "Delete Columns",
+InsertCell : "Insert Cell",
+DeleteCells : "Delete Cells",
+MergeCells : "Merge Cells",
+SplitCell : "Split Cell",
+TableDelete : "Delete Table",
+CellProperties : "Cell Properties",
+TableProperties : "Table Properties",
+ImageProperties : "Image Properties",
+FlashProperties : "Flash Properties",
+
+AnchorProp : "Anchor Properties",
+ButtonProp : "Button Properties",
+CheckboxProp : "Checkbox Properties",
+HiddenFieldProp : "Hidden Field Properties",
+RadioButtonProp : "Radio Button Properties",
+ImageButtonProp : "Image Button Properties",
+TextFieldProp : "Text Field Properties",
+SelectionFieldProp : "Selection Field Properties",
+TextareaProp : "Textarea Properties",
+FormProp : "Form Properties",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processing XHTML. Please wait...",
+Done : "Done",
+PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?",
+NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?",
+UnknownToolbarItem : "Unknown toolbar item \"%1\"",
+UnknownCommand : "Unknown command name \"%1\"",
+NotImplemented : "Command not implemented",
+UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.",
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.",
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancel",
+DlgBtnClose : "Close",
+DlgBtnBrowseServer : "Browse Server",
+DlgAdvancedTag : "Advanced",
+DlgOpOther : "<Other>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Please insert the URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<not set>",
+DlgGenId : "Id",
+DlgGenLangDir : "Language Direction",
+DlgGenLangDirLtr : "Left to Right (LTR)",
+DlgGenLangDirRtl : "Right to Left (RTL)",
+DlgGenLangCode : "Language Code",
+DlgGenAccessKey : "Access Key",
+DlgGenName : "Name",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Long Description URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Image Properties",
+DlgImgInfoTab : "Image Info",
+DlgImgBtnUpload : "Send it to the Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternative Text",
+DlgImgWidth : "Width",
+DlgImgHeight : "Height",
+DlgImgLockRatio : "Lock Ratio",
+DlgBtnResetSize : "Reset Size",
+DlgImgBorder : "Border",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Align",
+DlgImgAlignLeft : "Left",
+DlgImgAlignAbsBottom: "Abs Bottom",
+DlgImgAlignAbsMiddle: "Abs Middle",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Bottom",
+DlgImgAlignMiddle : "Middle",
+DlgImgAlignRight : "Right",
+DlgImgAlignTextTop : "Text Top",
+DlgImgAlignTop : "Top",
+DlgImgPreview : "Preview",
+DlgImgAlertUrl : "Please type the image URL",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties",
+DlgFlashChkPlay : "Auto Play",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Enable Flash Menu",
+DlgFlashScale : "Scale",
+DlgFlashScaleAll : "Show all",
+DlgFlashScaleNoBorder : "No Border",
+DlgFlashScaleFit : "Exact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Target",
+
+DlgLnkType : "Link Type",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Link to anchor in the text",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<other>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Select an Anchor",
+DlgLnkAnchorByName : "By Anchor Name",
+DlgLnkAnchorById : "By Element Id",
+DlgLnkNoAnchors : "(No anchors available in the document)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Address",
+DlgLnkEMailSubject : "Message Subject",
+DlgLnkEMailBody : "Message Body",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Send it to the Server",
+
+DlgLnkTarget : "Target",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<popup window>",
+DlgLnkTargetBlank : "New Window (_blank)",
+DlgLnkTargetParent : "Parent Window (_parent)",
+DlgLnkTargetSelf : "Same Window (_self)",
+DlgLnkTargetTop : "Topmost Window (_top)",
+DlgLnkTargetFrameName : "Target Frame Name",
+DlgLnkPopWinName : "Popup Window Name",
+DlgLnkPopWinFeat : "Popup Window Features",
+DlgLnkPopResize : "Resizable",
+DlgLnkPopLocation : "Location Bar",
+DlgLnkPopMenu : "Menu Bar",
+DlgLnkPopScroll : "Scroll Bars",
+DlgLnkPopStatus : "Status Bar",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Full Screen (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Width",
+DlgLnkPopHeight : "Height",
+DlgLnkPopLeft : "Left Position",
+DlgLnkPopTop : "Top Position",
+
+DlnLnkMsgNoUrl : "Please type the link URL",
+DlnLnkMsgNoEMail : "Please type the e-mail address",
+DlnLnkMsgNoAnchor : "Please select an anchor",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces",
+
+// Color Dialog
+DlgColorTitle : "Select Colour",
+DlgColorBtnClear : "Clear",
+DlgColorHighlight : "Highlight",
+DlgColorSelected : "Selected",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insert a Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Select Special Character",
+
+// Table Dialog
+DlgTableTitle : "Table Properties",
+DlgTableRows : "Rows",
+DlgTableColumns : "Columns",
+DlgTableBorder : "Border size",
+DlgTableAlign : "Alignment",
+DlgTableAlignNotSet : "<Not set>",
+DlgTableAlignLeft : "Left",
+DlgTableAlignCenter : "Centre",
+DlgTableAlignRight : "Right",
+DlgTableWidth : "Width",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Height",
+DlgTableCellSpace : "Cell spacing",
+DlgTableCellPad : "Cell padding",
+DlgTableCaption : "Caption",
+DlgTableSummary : "Summary",
+
+// Table Cell Dialog
+DlgCellTitle : "Cell Properties",
+DlgCellWidth : "Width",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Height",
+DlgCellWordWrap : "Word Wrap",
+DlgCellWordWrapNotSet : "<Not set>",
+DlgCellWordWrapYes : "Yes",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Horizontal Alignment",
+DlgCellHorAlignNotSet : "<Not set>",
+DlgCellHorAlignLeft : "Left",
+DlgCellHorAlignCenter : "Centre",
+DlgCellHorAlignRight: "Right",
+DlgCellVerAlign : "Vertical Alignment",
+DlgCellVerAlignNotSet : "<Not set>",
+DlgCellVerAlignTop : "Top",
+DlgCellVerAlignMiddle : "Middle",
+DlgCellVerAlignBottom : "Bottom",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rows Span",
+DlgCellCollSpan : "Columns Span",
+DlgCellBackColor : "Background Colour",
+DlgCellBorderColor : "Border Colour",
+DlgCellBtnSelect : "Select...",
+
+// Find Dialog
+DlgFindTitle : "Find",
+DlgFindFindBtn : "Find",
+DlgFindNotFoundMsg : "The specified text was not found.",
+
+// Replace Dialog
+DlgReplaceTitle : "Replace",
+DlgReplaceFindLbl : "Find what:",
+DlgReplaceReplaceLbl : "Replace with:",
+DlgReplaceCaseChk : "Match case",
+DlgReplaceReplaceBtn : "Replace",
+DlgReplaceReplAllBtn : "Replace All",
+DlgReplaceWordChk : "Match whole word",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).",
+PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).",
+
+PasteAsText : "Paste as Plain Text",
+PasteFromWord : "Paste from Word",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<STRONG>Ctrl+V</STRONG>) and hit <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.",
+DlgPasteIgnoreFont : "Ignore Font Face definitions",
+DlgPasteRemoveStyles : "Remove Styles definitions",
+DlgPasteCleanBox : "Clean Up Box",
+
+// Color Picker
+ColorAutomatic : "Automatic",
+ColorMoreColors : "More Colours...",
+
+// Document Properties
+DocProps : "Document Properties",
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties",
+DlgAnchorName : "Anchor Name",
+DlgAnchorErrorName : "Please type the anchor name",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary",
+DlgSpellChangeTo : "Change to",
+DlgSpellBtnIgnore : "Ignore",
+DlgSpellBtnIgnoreAll : "Ignore All",
+DlgSpellBtnReplace : "Replace",
+DlgSpellBtnReplaceAll : "Replace All",
+DlgSpellBtnUndo : "Undo",
+DlgSpellNoSuggestions : "- No suggestions -",
+DlgSpellProgress : "Spell check in progress...",
+DlgSpellNoMispell : "Spell check complete: No misspellings found",
+DlgSpellNoChanges : "Spell check complete: No words changed",
+DlgSpellOneChange : "Spell check complete: One word changed",
+DlgSpellManyChanges : "Spell check complete: %1 words changed",
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?",
+
+// Button Dialog
+DlgButtonText : "Text (Value)",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name",
+DlgCheckboxValue : "Value",
+DlgCheckboxSelected : "Selected",
+
+// Form Dialog
+DlgFormName : "Name",
+DlgFormAction : "Action",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Name",
+DlgSelectValue : "Value",
+DlgSelectSize : "Size",
+DlgSelectLines : "lines",
+DlgSelectChkMulti : "Allow multiple selections",
+DlgSelectOpAvail : "Available Options",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Value",
+DlgSelectBtnAdd : "Add",
+DlgSelectBtnModify : "Modify",
+DlgSelectBtnUp : "Up",
+DlgSelectBtnDown : "Down",
+DlgSelectBtnSetValue : "Set as selected value",
+DlgSelectBtnDelete : "Delete",
+
+// Textarea Dialog
+DlgTextareaName : "Name",
+DlgTextareaCols : "Columns",
+DlgTextareaRows : "Rows",
+
+// Text Field Dialog
+DlgTextName : "Name",
+DlgTextValue : "Value",
+DlgTextCharWidth : "Character Width",
+DlgTextMaxChars : "Maximum Characters",
+DlgTextType : "Type",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Password",
+
+// Hidden Field Dialog
+DlgHiddenName : "Name",
+DlgHiddenValue : "Value",
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties",
+NumberedListProp : "Numbered List Properties",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Circle",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Square",
+DlgLstTypeNumbers : "Numbers (1, 2, 3)",
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)",
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)",
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)",
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Background",
+DlgDocColorsTab : "Colours and Margins",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Page Title",
+DlgDocLangDir : "Language Direction",
+DlgDocLangDirLTR : "Left to Right (LTR)",
+DlgDocLangDirRTL : "Right to Left (RTL)",
+DlgDocLangCode : "Language Code",
+DlgDocCharSet : "Character Set Encoding",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "Other Character Set Encoding",
+
+DlgDocDocType : "Document Type Heading",
+DlgDocDocTypeOther : "Other Document Type Heading",
+DlgDocIncXHTML : "Include XHTML Declarations",
+DlgDocBgColor : "Background Colour",
+DlgDocBgImage : "Background Image URL",
+DlgDocBgNoScroll : "Nonscrolling Background",
+DlgDocCText : "Text",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Visited Link",
+DlgDocCActive : "Active Link",
+DlgDocMargins : "Page Margins",
+DlgDocMaTop : "Top",
+DlgDocMaLeft : "Left",
+DlgDocMaRight : "Right",
+DlgDocMaBottom : "Bottom",
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)",
+DlgDocMeDescr : "Document Description",
+DlgDocMeAuthor : "Author",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Preview",
+
+// Templates Dialog
+Templates : "Templates",
+DlgTemplatesTitle : "Content Templates",
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br>(the actual contents will be lost):",
+DlgTemplatesLoading : "Loading templates list. Please wait...",
+DlgTemplatesNoTpl : "(No templates defined)",
+DlgTemplatesReplace : "Replace actual contents",
+
+// About Dialog
+DlgAboutAboutTab : "About",
+DlgAboutBrowserInfoTab : "Browser Info",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "For further information go to"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/en-uk.js b/httemplate/elements/fckeditor/editor/lang/en-uk.js
new file mode 100644
index 000000000..eaaf3e4c1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/en-uk.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * English (United Kingdom) language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Collapse Toolbar",
+ToolbarExpand : "Expand Toolbar",
+
+// Toolbar Items and Context Menu
+Save : "Save",
+NewPage : "New Page",
+Preview : "Preview",
+Cut : "Cut",
+Copy : "Copy",
+Paste : "Paste",
+PasteText : "Paste as plain text",
+PasteWord : "Paste from Word",
+Print : "Print",
+SelectAll : "Select All",
+RemoveFormat : "Remove Format",
+InsertLinkLbl : "Link",
+InsertLink : "Insert/Edit Link",
+RemoveLink : "Remove Link",
+Anchor : "Insert/Edit Anchor",
+InsertImageLbl : "Image",
+InsertImage : "Insert/Edit Image",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insert/Edit Flash",
+InsertTableLbl : "Table",
+InsertTable : "Insert/Edit Table",
+InsertLineLbl : "Line",
+InsertLine : "Insert Horizontal Line",
+InsertSpecialCharLbl: "Special Character",
+InsertSpecialChar : "Insert Special Character",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Insert Smiley",
+About : "About FCKeditor",
+Bold : "Bold",
+Italic : "Italic",
+Underline : "Underline",
+StrikeThrough : "Strike Through",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Left Justify",
+CenterJustify : "Centre Justify",
+RightJustify : "Right Justify",
+BlockJustify : "Block Justify",
+DecreaseIndent : "Decrease Indent",
+IncreaseIndent : "Increase Indent",
+Undo : "Undo",
+Redo : "Redo",
+NumberedListLbl : "Numbered List",
+NumberedList : "Insert/Remove Numbered List",
+BulletedListLbl : "Bulleted List",
+BulletedList : "Insert/Remove Bulleted List",
+ShowTableBorders : "Show Table Borders",
+ShowDetails : "Show Details",
+Style : "Style",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Size",
+TextColor : "Text Colour",
+BGColor : "Background Colour",
+Source : "Source",
+Find : "Find",
+Replace : "Replace",
+SpellCheck : "Check Spelling",
+UniversalKeyboard : "Universal Keyboard",
+PageBreakLbl : "Page Break",
+PageBreak : "Insert Page Break",
+
+Form : "Form",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Hidden Field",
+Button : "Button",
+SelectionField : "Selection Field",
+ImageButton : "Image Button",
+
+FitWindow : "Maximize the editor size",
+
+// Context Menu
+EditLink : "Edit Link",
+CellCM : "Cell",
+RowCM : "Row",
+ColumnCM : "Column",
+InsertRow : "Insert Row",
+DeleteRows : "Delete Rows",
+InsertColumn : "Insert Column",
+DeleteColumns : "Delete Columns",
+InsertCell : "Insert Cell",
+DeleteCells : "Delete Cells",
+MergeCells : "Merge Cells",
+SplitCell : "Split Cell",
+TableDelete : "Delete Table",
+CellProperties : "Cell Properties",
+TableProperties : "Table Properties",
+ImageProperties : "Image Properties",
+FlashProperties : "Flash Properties",
+
+AnchorProp : "Anchor Properties",
+ButtonProp : "Button Properties",
+CheckboxProp : "Checkbox Properties",
+HiddenFieldProp : "Hidden Field Properties",
+RadioButtonProp : "Radio Button Properties",
+ImageButtonProp : "Image Button Properties",
+TextFieldProp : "Text Field Properties",
+SelectionFieldProp : "Selection Field Properties",
+TextareaProp : "Textarea Properties",
+FormProp : "Form Properties",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processing XHTML. Please wait...",
+Done : "Done",
+PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?",
+NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?",
+UnknownToolbarItem : "Unknown toolbar item \"%1\"",
+UnknownCommand : "Unknown command name \"%1\"",
+NotImplemented : "Command not implemented",
+UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.",
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.",
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancel",
+DlgBtnClose : "Close",
+DlgBtnBrowseServer : "Browse Server",
+DlgAdvancedTag : "Advanced",
+DlgOpOther : "<Other>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Please insert the URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<not set>",
+DlgGenId : "Id",
+DlgGenLangDir : "Language Direction",
+DlgGenLangDirLtr : "Left to Right (LTR)",
+DlgGenLangDirRtl : "Right to Left (RTL)",
+DlgGenLangCode : "Language Code",
+DlgGenAccessKey : "Access Key",
+DlgGenName : "Name",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Long Description URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Image Properties",
+DlgImgInfoTab : "Image Info",
+DlgImgBtnUpload : "Send it to the Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternative Text",
+DlgImgWidth : "Width",
+DlgImgHeight : "Height",
+DlgImgLockRatio : "Lock Ratio",
+DlgBtnResetSize : "Reset Size",
+DlgImgBorder : "Border",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Align",
+DlgImgAlignLeft : "Left",
+DlgImgAlignAbsBottom: "Abs Bottom",
+DlgImgAlignAbsMiddle: "Abs Middle",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Bottom",
+DlgImgAlignMiddle : "Middle",
+DlgImgAlignRight : "Right",
+DlgImgAlignTextTop : "Text Top",
+DlgImgAlignTop : "Top",
+DlgImgPreview : "Preview",
+DlgImgAlertUrl : "Please type the image URL",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties",
+DlgFlashChkPlay : "Auto Play",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Enable Flash Menu",
+DlgFlashScale : "Scale",
+DlgFlashScaleAll : "Show all",
+DlgFlashScaleNoBorder : "No Border",
+DlgFlashScaleFit : "Exact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Target",
+
+DlgLnkType : "Link Type",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Link to anchor in the text",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<other>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Select an Anchor",
+DlgLnkAnchorByName : "By Anchor Name",
+DlgLnkAnchorById : "By Element Id",
+DlgLnkNoAnchors : "(No anchors available in the document)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Address",
+DlgLnkEMailSubject : "Message Subject",
+DlgLnkEMailBody : "Message Body",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Send it to the Server",
+
+DlgLnkTarget : "Target",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<popup window>",
+DlgLnkTargetBlank : "New Window (_blank)",
+DlgLnkTargetParent : "Parent Window (_parent)",
+DlgLnkTargetSelf : "Same Window (_self)",
+DlgLnkTargetTop : "Topmost Window (_top)",
+DlgLnkTargetFrameName : "Target Frame Name",
+DlgLnkPopWinName : "Popup Window Name",
+DlgLnkPopWinFeat : "Popup Window Features",
+DlgLnkPopResize : "Resizable",
+DlgLnkPopLocation : "Location Bar",
+DlgLnkPopMenu : "Menu Bar",
+DlgLnkPopScroll : "Scroll Bars",
+DlgLnkPopStatus : "Status Bar",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Full Screen (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Width",
+DlgLnkPopHeight : "Height",
+DlgLnkPopLeft : "Left Position",
+DlgLnkPopTop : "Top Position",
+
+DlnLnkMsgNoUrl : "Please type the link URL",
+DlnLnkMsgNoEMail : "Please type the e-mail address",
+DlnLnkMsgNoAnchor : "Please select an anchor",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces",
+
+// Color Dialog
+DlgColorTitle : "Select Colour",
+DlgColorBtnClear : "Clear",
+DlgColorHighlight : "Highlight",
+DlgColorSelected : "Selected",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insert a Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Select Special Character",
+
+// Table Dialog
+DlgTableTitle : "Table Properties",
+DlgTableRows : "Rows",
+DlgTableColumns : "Columns",
+DlgTableBorder : "Border size",
+DlgTableAlign : "Alignment",
+DlgTableAlignNotSet : "<Not set>",
+DlgTableAlignLeft : "Left",
+DlgTableAlignCenter : "Centre",
+DlgTableAlignRight : "Right",
+DlgTableWidth : "Width",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Height",
+DlgTableCellSpace : "Cell spacing",
+DlgTableCellPad : "Cell padding",
+DlgTableCaption : "Caption",
+DlgTableSummary : "Summary",
+
+// Table Cell Dialog
+DlgCellTitle : "Cell Properties",
+DlgCellWidth : "Width",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Height",
+DlgCellWordWrap : "Word Wrap",
+DlgCellWordWrapNotSet : "<Not set>",
+DlgCellWordWrapYes : "Yes",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Horizontal Alignment",
+DlgCellHorAlignNotSet : "<Not set>",
+DlgCellHorAlignLeft : "Left",
+DlgCellHorAlignCenter : "Centre",
+DlgCellHorAlignRight: "Right",
+DlgCellVerAlign : "Vertical Alignment",
+DlgCellVerAlignNotSet : "<Not set>",
+DlgCellVerAlignTop : "Top",
+DlgCellVerAlignMiddle : "Middle",
+DlgCellVerAlignBottom : "Bottom",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rows Span",
+DlgCellCollSpan : "Columns Span",
+DlgCellBackColor : "Background Colour",
+DlgCellBorderColor : "Border Colour",
+DlgCellBtnSelect : "Select...",
+
+// Find Dialog
+DlgFindTitle : "Find",
+DlgFindFindBtn : "Find",
+DlgFindNotFoundMsg : "The specified text was not found.",
+
+// Replace Dialog
+DlgReplaceTitle : "Replace",
+DlgReplaceFindLbl : "Find what:",
+DlgReplaceReplaceLbl : "Replace with:",
+DlgReplaceCaseChk : "Match case",
+DlgReplaceReplaceBtn : "Replace",
+DlgReplaceReplAllBtn : "Replace All",
+DlgReplaceWordChk : "Match whole word",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).",
+PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).",
+
+PasteAsText : "Paste as Plain Text",
+PasteFromWord : "Paste from Word",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<STRONG>Ctrl+V</STRONG>) and hit <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.",
+DlgPasteIgnoreFont : "Ignore Font Face definitions",
+DlgPasteRemoveStyles : "Remove Styles definitions",
+DlgPasteCleanBox : "Clean Up Box",
+
+// Color Picker
+ColorAutomatic : "Automatic",
+ColorMoreColors : "More Colours...",
+
+// Document Properties
+DocProps : "Document Properties",
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties",
+DlgAnchorName : "Anchor Name",
+DlgAnchorErrorName : "Please type the anchor name",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary",
+DlgSpellChangeTo : "Change to",
+DlgSpellBtnIgnore : "Ignore",
+DlgSpellBtnIgnoreAll : "Ignore All",
+DlgSpellBtnReplace : "Replace",
+DlgSpellBtnReplaceAll : "Replace All",
+DlgSpellBtnUndo : "Undo",
+DlgSpellNoSuggestions : "- No suggestions -",
+DlgSpellProgress : "Spell check in progress...",
+DlgSpellNoMispell : "Spell check complete: No misspellings found",
+DlgSpellNoChanges : "Spell check complete: No words changed",
+DlgSpellOneChange : "Spell check complete: One word changed",
+DlgSpellManyChanges : "Spell check complete: %1 words changed",
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?",
+
+// Button Dialog
+DlgButtonText : "Text (Value)",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name",
+DlgCheckboxValue : "Value",
+DlgCheckboxSelected : "Selected",
+
+// Form Dialog
+DlgFormName : "Name",
+DlgFormAction : "Action",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Name",
+DlgSelectValue : "Value",
+DlgSelectSize : "Size",
+DlgSelectLines : "lines",
+DlgSelectChkMulti : "Allow multiple selections",
+DlgSelectOpAvail : "Available Options",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Value",
+DlgSelectBtnAdd : "Add",
+DlgSelectBtnModify : "Modify",
+DlgSelectBtnUp : "Up",
+DlgSelectBtnDown : "Down",
+DlgSelectBtnSetValue : "Set as selected value",
+DlgSelectBtnDelete : "Delete",
+
+// Textarea Dialog
+DlgTextareaName : "Name",
+DlgTextareaCols : "Columns",
+DlgTextareaRows : "Rows",
+
+// Text Field Dialog
+DlgTextName : "Name",
+DlgTextValue : "Value",
+DlgTextCharWidth : "Character Width",
+DlgTextMaxChars : "Maximum Characters",
+DlgTextType : "Type",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Password",
+
+// Hidden Field Dialog
+DlgHiddenName : "Name",
+DlgHiddenValue : "Value",
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties",
+NumberedListProp : "Numbered List Properties",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Circle",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Square",
+DlgLstTypeNumbers : "Numbers (1, 2, 3)",
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)",
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)",
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)",
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Background",
+DlgDocColorsTab : "Colours and Margins",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Page Title",
+DlgDocLangDir : "Language Direction",
+DlgDocLangDirLTR : "Left to Right (LTR)",
+DlgDocLangDirRTL : "Right to Left (RTL)",
+DlgDocLangCode : "Language Code",
+DlgDocCharSet : "Character Set Encoding",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "Other Character Set Encoding",
+
+DlgDocDocType : "Document Type Heading",
+DlgDocDocTypeOther : "Other Document Type Heading",
+DlgDocIncXHTML : "Include XHTML Declarations",
+DlgDocBgColor : "Background Colour",
+DlgDocBgImage : "Background Image URL",
+DlgDocBgNoScroll : "Nonscrolling Background",
+DlgDocCText : "Text",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Visited Link",
+DlgDocCActive : "Active Link",
+DlgDocMargins : "Page Margins",
+DlgDocMaTop : "Top",
+DlgDocMaLeft : "Left",
+DlgDocMaRight : "Right",
+DlgDocMaBottom : "Bottom",
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)",
+DlgDocMeDescr : "Document Description",
+DlgDocMeAuthor : "Author",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Preview",
+
+// Templates Dialog
+Templates : "Templates",
+DlgTemplatesTitle : "Content Templates",
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br>(the actual contents will be lost):",
+DlgTemplatesLoading : "Loading templates list. Please wait...",
+DlgTemplatesNoTpl : "(No templates defined)",
+DlgTemplatesReplace : "Replace actual contents",
+
+// About Dialog
+DlgAboutAboutTab : "About",
+DlgAboutBrowserInfoTab : "Browser Info",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "For further information go to"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/en.js b/httemplate/elements/fckeditor/editor/lang/en.js
new file mode 100644
index 000000000..c579fc9e3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/en.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * English language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Collapse Toolbar",
+ToolbarExpand : "Expand Toolbar",
+
+// Toolbar Items and Context Menu
+Save : "Save",
+NewPage : "New Page",
+Preview : "Preview",
+Cut : "Cut",
+Copy : "Copy",
+Paste : "Paste",
+PasteText : "Paste as plain text",
+PasteWord : "Paste from Word",
+Print : "Print",
+SelectAll : "Select All",
+RemoveFormat : "Remove Format",
+InsertLinkLbl : "Link",
+InsertLink : "Insert/Edit Link",
+RemoveLink : "Remove Link",
+Anchor : "Insert/Edit Anchor",
+InsertImageLbl : "Image",
+InsertImage : "Insert/Edit Image",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insert/Edit Flash",
+InsertTableLbl : "Table",
+InsertTable : "Insert/Edit Table",
+InsertLineLbl : "Line",
+InsertLine : "Insert Horizontal Line",
+InsertSpecialCharLbl: "Special Character",
+InsertSpecialChar : "Insert Special Character",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Insert Smiley",
+About : "About FCKeditor",
+Bold : "Bold",
+Italic : "Italic",
+Underline : "Underline",
+StrikeThrough : "Strike Through",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Left Justify",
+CenterJustify : "Center Justify",
+RightJustify : "Right Justify",
+BlockJustify : "Block Justify",
+DecreaseIndent : "Decrease Indent",
+IncreaseIndent : "Increase Indent",
+Undo : "Undo",
+Redo : "Redo",
+NumberedListLbl : "Numbered List",
+NumberedList : "Insert/Remove Numbered List",
+BulletedListLbl : "Bulleted List",
+BulletedList : "Insert/Remove Bulleted List",
+ShowTableBorders : "Show Table Borders",
+ShowDetails : "Show Details",
+Style : "Style",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Size",
+TextColor : "Text Color",
+BGColor : "Background Color",
+Source : "Source",
+Find : "Find",
+Replace : "Replace",
+SpellCheck : "Check Spelling",
+UniversalKeyboard : "Universal Keyboard",
+PageBreakLbl : "Page Break",
+PageBreak : "Insert Page Break",
+
+Form : "Form",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Hidden Field",
+Button : "Button",
+SelectionField : "Selection Field",
+ImageButton : "Image Button",
+
+FitWindow : "Maximize the editor size",
+
+// Context Menu
+EditLink : "Edit Link",
+CellCM : "Cell",
+RowCM : "Row",
+ColumnCM : "Column",
+InsertRow : "Insert Row",
+DeleteRows : "Delete Rows",
+InsertColumn : "Insert Column",
+DeleteColumns : "Delete Columns",
+InsertCell : "Insert Cell",
+DeleteCells : "Delete Cells",
+MergeCells : "Merge Cells",
+SplitCell : "Split Cell",
+TableDelete : "Delete Table",
+CellProperties : "Cell Properties",
+TableProperties : "Table Properties",
+ImageProperties : "Image Properties",
+FlashProperties : "Flash Properties",
+
+AnchorProp : "Anchor Properties",
+ButtonProp : "Button Properties",
+CheckboxProp : "Checkbox Properties",
+HiddenFieldProp : "Hidden Field Properties",
+RadioButtonProp : "Radio Button Properties",
+ImageButtonProp : "Image Button Properties",
+TextFieldProp : "Text Field Properties",
+SelectionFieldProp : "Selection Field Properties",
+TextareaProp : "Textarea Properties",
+FormProp : "Form Properties",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processing XHTML. Please wait...",
+Done : "Done",
+PasteWordConfirm : "The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?",
+NotCompatiblePaste : "This command is available for Internet Explorer version 5.5 or more. Do you want to paste without cleaning?",
+UnknownToolbarItem : "Unknown toolbar item \"%1\"",
+UnknownCommand : "Unknown command name \"%1\"",
+NotImplemented : "Command not implemented",
+UnknownToolbarSet : "Toolbar set \"%1\" doesn't exist",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.",
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.",
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancel",
+DlgBtnClose : "Close",
+DlgBtnBrowseServer : "Browse Server",
+DlgAdvancedTag : "Advanced",
+DlgOpOther : "<Other>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Please insert the URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<not set>",
+DlgGenId : "Id",
+DlgGenLangDir : "Language Direction",
+DlgGenLangDirLtr : "Left to Right (LTR)",
+DlgGenLangDirRtl : "Right to Left (RTL)",
+DlgGenLangCode : "Language Code",
+DlgGenAccessKey : "Access Key",
+DlgGenName : "Name",
+DlgGenTabIndex : "Tab Index",
+DlgGenLongDescr : "Long Description URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Image Properties",
+DlgImgInfoTab : "Image Info",
+DlgImgBtnUpload : "Send it to the Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternative Text",
+DlgImgWidth : "Width",
+DlgImgHeight : "Height",
+DlgImgLockRatio : "Lock Ratio",
+DlgBtnResetSize : "Reset Size",
+DlgImgBorder : "Border",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Align",
+DlgImgAlignLeft : "Left",
+DlgImgAlignAbsBottom: "Abs Bottom",
+DlgImgAlignAbsMiddle: "Abs Middle",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Bottom",
+DlgImgAlignMiddle : "Middle",
+DlgImgAlignRight : "Right",
+DlgImgAlignTextTop : "Text Top",
+DlgImgAlignTop : "Top",
+DlgImgPreview : "Preview",
+DlgImgAlertUrl : "Please type the image URL",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties",
+DlgFlashChkPlay : "Auto Play",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Enable Flash Menu",
+DlgFlashScale : "Scale",
+DlgFlashScaleAll : "Show all",
+DlgFlashScaleNoBorder : "No Border",
+DlgFlashScaleFit : "Exact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Target",
+
+DlgLnkType : "Link Type",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Link to anchor in the text",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<other>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Select an Anchor",
+DlgLnkAnchorByName : "By Anchor Name",
+DlgLnkAnchorById : "By Element Id",
+DlgLnkNoAnchors : "(No anchors available in the document)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Address",
+DlgLnkEMailSubject : "Message Subject",
+DlgLnkEMailBody : "Message Body",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Send it to the Server",
+
+DlgLnkTarget : "Target",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<popup window>",
+DlgLnkTargetBlank : "New Window (_blank)",
+DlgLnkTargetParent : "Parent Window (_parent)",
+DlgLnkTargetSelf : "Same Window (_self)",
+DlgLnkTargetTop : "Topmost Window (_top)",
+DlgLnkTargetFrameName : "Target Frame Name",
+DlgLnkPopWinName : "Popup Window Name",
+DlgLnkPopWinFeat : "Popup Window Features",
+DlgLnkPopResize : "Resizable",
+DlgLnkPopLocation : "Location Bar",
+DlgLnkPopMenu : "Menu Bar",
+DlgLnkPopScroll : "Scroll Bars",
+DlgLnkPopStatus : "Status Bar",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Full Screen (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Width",
+DlgLnkPopHeight : "Height",
+DlgLnkPopLeft : "Left Position",
+DlgLnkPopTop : "Top Position",
+
+DlnLnkMsgNoUrl : "Please type the link URL",
+DlnLnkMsgNoEMail : "Please type the e-mail address",
+DlnLnkMsgNoAnchor : "Please select an anchor",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces",
+
+// Color Dialog
+DlgColorTitle : "Select Color",
+DlgColorBtnClear : "Clear",
+DlgColorHighlight : "Highlight",
+DlgColorSelected : "Selected",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insert a Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Select Special Character",
+
+// Table Dialog
+DlgTableTitle : "Table Properties",
+DlgTableRows : "Rows",
+DlgTableColumns : "Columns",
+DlgTableBorder : "Border size",
+DlgTableAlign : "Alignment",
+DlgTableAlignNotSet : "<Not set>",
+DlgTableAlignLeft : "Left",
+DlgTableAlignCenter : "Center",
+DlgTableAlignRight : "Right",
+DlgTableWidth : "Width",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Height",
+DlgTableCellSpace : "Cell spacing",
+DlgTableCellPad : "Cell padding",
+DlgTableCaption : "Caption",
+DlgTableSummary : "Summary",
+
+// Table Cell Dialog
+DlgCellTitle : "Cell Properties",
+DlgCellWidth : "Width",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Height",
+DlgCellWordWrap : "Word Wrap",
+DlgCellWordWrapNotSet : "<Not set>",
+DlgCellWordWrapYes : "Yes",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Horizontal Alignment",
+DlgCellHorAlignNotSet : "<Not set>",
+DlgCellHorAlignLeft : "Left",
+DlgCellHorAlignCenter : "Center",
+DlgCellHorAlignRight: "Right",
+DlgCellVerAlign : "Vertical Alignment",
+DlgCellVerAlignNotSet : "<Not set>",
+DlgCellVerAlignTop : "Top",
+DlgCellVerAlignMiddle : "Middle",
+DlgCellVerAlignBottom : "Bottom",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Rows Span",
+DlgCellCollSpan : "Columns Span",
+DlgCellBackColor : "Background Color",
+DlgCellBorderColor : "Border Color",
+DlgCellBtnSelect : "Select...",
+
+// Find Dialog
+DlgFindTitle : "Find",
+DlgFindFindBtn : "Find",
+DlgFindNotFoundMsg : "The specified text was not found.",
+
+// Replace Dialog
+DlgReplaceTitle : "Replace",
+DlgReplaceFindLbl : "Find what:",
+DlgReplaceReplaceLbl : "Replace with:",
+DlgReplaceCaseChk : "Match case",
+DlgReplaceReplaceBtn : "Replace",
+DlgReplaceReplAllBtn : "Replace All",
+DlgReplaceWordChk : "Match whole word",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).",
+PasteErrorCopy : "Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).",
+
+PasteAsText : "Paste as Plain Text",
+PasteFromWord : "Paste from Word",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.",
+DlgPasteIgnoreFont : "Ignore Font Face definitions",
+DlgPasteRemoveStyles : "Remove Styles definitions",
+DlgPasteCleanBox : "Clean Up Box",
+
+// Color Picker
+ColorAutomatic : "Automatic",
+ColorMoreColors : "More Colors...",
+
+// Document Properties
+DocProps : "Document Properties",
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties",
+DlgAnchorName : "Anchor Name",
+DlgAnchorErrorName : "Please type the anchor name",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary",
+DlgSpellChangeTo : "Change to",
+DlgSpellBtnIgnore : "Ignore",
+DlgSpellBtnIgnoreAll : "Ignore All",
+DlgSpellBtnReplace : "Replace",
+DlgSpellBtnReplaceAll : "Replace All",
+DlgSpellBtnUndo : "Undo",
+DlgSpellNoSuggestions : "- No suggestions -",
+DlgSpellProgress : "Spell check in progress...",
+DlgSpellNoMispell : "Spell check complete: No misspellings found",
+DlgSpellNoChanges : "Spell check complete: No words changed",
+DlgSpellOneChange : "Spell check complete: One word changed",
+DlgSpellManyChanges : "Spell check complete: %1 words changed",
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?",
+
+// Button Dialog
+DlgButtonText : "Text (Value)",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name",
+DlgCheckboxValue : "Value",
+DlgCheckboxSelected : "Selected",
+
+// Form Dialog
+DlgFormName : "Name",
+DlgFormAction : "Action",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Name",
+DlgSelectValue : "Value",
+DlgSelectSize : "Size",
+DlgSelectLines : "lines",
+DlgSelectChkMulti : "Allow multiple selections",
+DlgSelectOpAvail : "Available Options",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Value",
+DlgSelectBtnAdd : "Add",
+DlgSelectBtnModify : "Modify",
+DlgSelectBtnUp : "Up",
+DlgSelectBtnDown : "Down",
+DlgSelectBtnSetValue : "Set as selected value",
+DlgSelectBtnDelete : "Delete",
+
+// Textarea Dialog
+DlgTextareaName : "Name",
+DlgTextareaCols : "Columns",
+DlgTextareaRows : "Rows",
+
+// Text Field Dialog
+DlgTextName : "Name",
+DlgTextValue : "Value",
+DlgTextCharWidth : "Character Width",
+DlgTextMaxChars : "Maximum Characters",
+DlgTextType : "Type",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Password",
+
+// Hidden Field Dialog
+DlgHiddenName : "Name",
+DlgHiddenValue : "Value",
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties",
+NumberedListProp : "Numbered List Properties",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Circle",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Square",
+DlgLstTypeNumbers : "Numbers (1, 2, 3)",
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)",
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)",
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)",
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Background",
+DlgDocColorsTab : "Colors and Margins",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Page Title",
+DlgDocLangDir : "Language Direction",
+DlgDocLangDirLTR : "Left to Right (LTR)",
+DlgDocLangDirRTL : "Right to Left (RTL)",
+DlgDocLangCode : "Language Code",
+DlgDocCharSet : "Character Set Encoding",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "Other Character Set Encoding",
+
+DlgDocDocType : "Document Type Heading",
+DlgDocDocTypeOther : "Other Document Type Heading",
+DlgDocIncXHTML : "Include XHTML Declarations",
+DlgDocBgColor : "Background Color",
+DlgDocBgImage : "Background Image URL",
+DlgDocBgNoScroll : "Nonscrolling Background",
+DlgDocCText : "Text",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Visited Link",
+DlgDocCActive : "Active Link",
+DlgDocMargins : "Page Margins",
+DlgDocMaTop : "Top",
+DlgDocMaLeft : "Left",
+DlgDocMaRight : "Right",
+DlgDocMaBottom : "Bottom",
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)",
+DlgDocMeDescr : "Document Description",
+DlgDocMeAuthor : "Author",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Preview",
+
+// Templates Dialog
+Templates : "Templates",
+DlgTemplatesTitle : "Content Templates",
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br />(the actual contents will be lost):",
+DlgTemplatesLoading : "Loading templates list. Please wait...",
+DlgTemplatesNoTpl : "(No templates defined)",
+DlgTemplatesReplace : "Replace actual contents",
+
+// About Dialog
+DlgAboutAboutTab : "About",
+DlgAboutBrowserInfoTab : "Browser Info",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "For further information go to"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/eo.js b/httemplate/elements/fckeditor/editor/lang/eo.js
new file mode 100644
index 000000000..04f7364f0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/eo.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Esperanto language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Kaŝi Ilobreton",
+ToolbarExpand : "Vidigi Ilojn",
+
+// Toolbar Items and Context Menu
+Save : "Sekurigi",
+NewPage : "Nova Paĝo",
+Preview : "Vidigi Aspekton",
+Cut : "Eltondi",
+Copy : "Kopii",
+Paste : "Interglui",
+PasteText : "Interglui kiel Tekston",
+PasteWord : "Interglui el Word",
+Print : "Presi",
+SelectAll : "Elekti ĉion",
+RemoveFormat : "Forigi Formaton",
+InsertLinkLbl : "Ligilo",
+InsertLink : "Enmeti/Ŝanĝi Ligilon",
+RemoveLink : "Forigi Ligilon",
+Anchor : "Enmeti/Ŝanĝi Ankron",
+InsertImageLbl : "Bildo",
+InsertImage : "Enmeti/Ŝanĝi Bildon",
+InsertFlashLbl : "Flash", //MISSING
+InsertFlash : "Insert/Edit Flash", //MISSING
+InsertTableLbl : "Tabelo",
+InsertTable : "Enmeti/Ŝanĝi Tabelon",
+InsertLineLbl : "Horizonta Linio",
+InsertLine : "Enmeti Horizonta Linio",
+InsertSpecialCharLbl: "Speciala Signo",
+InsertSpecialChar : "Enmeti Specialan Signon",
+InsertSmileyLbl : "Mienvinjeto",
+InsertSmiley : "Enmeti Mienvinjeton",
+About : "Pri FCKeditor",
+Bold : "Grasa",
+Italic : "Kursiva",
+Underline : "Substreko",
+StrikeThrough : "Trastreko",
+Subscript : "Subskribo",
+Superscript : "Superskribo",
+LeftJustify : "Maldekstrigi",
+CenterJustify : "Centrigi",
+RightJustify : "Dekstrigi",
+BlockJustify : "Ĝisrandigi Ambaŭflanke",
+DecreaseIndent : "Malpligrandigi Krommarĝenon",
+IncreaseIndent : "Pligrandigi Krommarĝenon",
+Undo : "Malfari",
+Redo : "Refari",
+NumberedListLbl : "Numera Listo",
+NumberedList : "Enmeti/Forigi Numeran Liston",
+BulletedListLbl : "Bula Listo",
+BulletedList : "Enmeti/Forigi Bulan Liston",
+ShowTableBorders : "Vidigi Borderojn de Tabelo",
+ShowDetails : "Vidigi Detalojn",
+Style : "Stilo",
+FontFormat : "Formato",
+Font : "Tiparo",
+FontSize : "Grando",
+TextColor : "Teksta Koloro",
+BGColor : "Fona Koloro",
+Source : "Fonto",
+Find : "Serĉi",
+Replace : "Anstataŭigi",
+SpellCheck : "Literumada Kontrolilo",
+UniversalKeyboard : "Universala Klavaro",
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Formularo",
+Checkbox : "Markobutono",
+RadioButton : "Radiobutono",
+TextField : "Teksta kampo",
+Textarea : "Teksta Areo",
+HiddenField : "Kaŝita Kampo",
+Button : "Butono",
+SelectionField : "Elekta Kampo",
+ImageButton : "Bildbutono",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Modifier Ligilon",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Enmeti Linion",
+DeleteRows : "Forigi Liniojn",
+InsertColumn : "Enmeti Kolumnon",
+DeleteColumns : "Forigi Kolumnojn",
+InsertCell : "Enmeti Ĉelon",
+DeleteCells : "Forigi Ĉelojn",
+MergeCells : "Kunfandi Ĉelojn",
+SplitCell : "Dividi Ĉelojn",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Atributoj de Ĉelo",
+TableProperties : "Atributoj de Tabelo",
+ImageProperties : "Atributoj de Bildo",
+FlashProperties : "Flash Properties", //MISSING
+
+AnchorProp : "Ankraj Atributoj",
+ButtonProp : "Butonaj Atributoj",
+CheckboxProp : "Markobutonaj Atributoj",
+HiddenFieldProp : "Atributoj de Kaŝita Kampo",
+RadioButtonProp : "Radiobutonaj Atributoj",
+ImageButtonProp : "Bildbutonaj Atributoj",
+TextFieldProp : "Atributoj de Teksta Kampo",
+SelectionFieldProp : "Atributoj de Elekta Kampo",
+TextareaProp : "Atributoj de Teksta Areo",
+FormProp : "Formularaj Atributoj",
+
+FontFormats : "Normala;Formatita;Adreso;Titolo 1;Titolo 2;Titolo 3;Titolo 4;Titolo 5;Titolo 6;Paragrafo (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Traktado de XHTML. Bonvolu pacienci...",
+Done : "Finita",
+PasteWordConfirm : "La algluota teksto ŝajnas esti Word-devena. Ĉu vi volas purigi ĝin antaŭ ol interglui?",
+NotCompatiblePaste : "Tiu ĉi komando bezonas almenaŭ Internet Explorer 5.5. Ĉu vi volas daŭrigi sen purigado?",
+UnknownToolbarItem : "Ilobretero nekonata \"%1\"",
+UnknownCommand : "Komandonomo nekonata \"%1\"",
+NotImplemented : "Komando ne ankoraŭ realigita",
+UnknownToolbarSet : "La ilobreto \"%1\" ne ekzistas",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "Akcepti",
+DlgBtnCancel : "Rezigni",
+DlgBtnClose : "Fermi",
+DlgBtnBrowseServer : "Foliumi en la Servilo",
+DlgAdvancedTag : "Speciala",
+DlgOpOther : "<Alia>",
+DlgInfoTab : "Info", //MISSING
+DlgAlertUrl : "Please insert the URL", //MISSING
+
+// General Dialogs Labels
+DlgGenNotSet : "<Defaŭlta>",
+DlgGenId : "Id",
+DlgGenLangDir : "Skribdirekto",
+DlgGenLangDirLtr : "De maldekstro dekstren (LTR)",
+DlgGenLangDirRtl : "De dekstro maldekstren (RTL)",
+DlgGenLangCode : "Lingva Kodo",
+DlgGenAccessKey : "Fulmoklavo",
+DlgGenName : "Nomo",
+DlgGenTabIndex : "Taba Ordo",
+DlgGenLongDescr : "URL de Longa Priskribo",
+DlgGenClass : "Klasoj de Stilfolioj",
+DlgGenTitle : "Indika Titolo",
+DlgGenContType : "Indika Enhavotipo",
+DlgGenLinkCharset : "Signaro de la Ligita Rimedo",
+DlgGenStyle : "Stilo",
+
+// Image Dialog
+DlgImgTitle : "Atributoj de Bildo",
+DlgImgInfoTab : "Informoj pri Bildo",
+DlgImgBtnUpload : "Sendu al Servilo",
+DlgImgURL : "URL",
+DlgImgUpload : "Alŝuti",
+DlgImgAlt : "Anstataŭiga Teksto",
+DlgImgWidth : "Larĝo",
+DlgImgHeight : "Alto",
+DlgImgLockRatio : "Konservi Proporcion",
+DlgBtnResetSize : "Origina Grando",
+DlgImgBorder : "Bordero",
+DlgImgHSpace : "HSpaco",
+DlgImgVSpace : "VSpaco",
+DlgImgAlign : "Ĝisrandigo",
+DlgImgAlignLeft : "Maldekstre",
+DlgImgAlignAbsBottom: "Abs Malsupre",
+DlgImgAlignAbsMiddle: "Abs Centre",
+DlgImgAlignBaseline : "Je Malsupro de Teksto",
+DlgImgAlignBottom : "Malsupre",
+DlgImgAlignMiddle : "Centre",
+DlgImgAlignRight : "Dekstre",
+DlgImgAlignTextTop : "Je Supro de Teksto",
+DlgImgAlignTop : "Supre",
+DlgImgPreview : "Vidigi Aspekton",
+DlgImgAlertUrl : "Bonvolu tajpi la URL de la bildo",
+DlgImgLinkTab : "Link", //MISSING
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties", //MISSING
+DlgFlashChkPlay : "Auto Play", //MISSING
+DlgFlashChkLoop : "Loop", //MISSING
+DlgFlashChkMenu : "Enable Flash Menu", //MISSING
+DlgFlashScale : "Scale", //MISSING
+DlgFlashScaleAll : "Show all", //MISSING
+DlgFlashScaleNoBorder : "No Border", //MISSING
+DlgFlashScaleFit : "Exact Fit", //MISSING
+
+// Link Dialog
+DlgLnkWindowTitle : "Ligilo",
+DlgLnkInfoTab : "Informoj pri la Ligilo",
+DlgLnkTargetTab : "Celo",
+
+DlgLnkType : "Tipo de Ligilo",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ankri en tiu ĉi paĝo",
+DlgLnkTypeEMail : "Retpoŝto",
+DlgLnkProto : "Protokolo",
+DlgLnkProtoOther : "<alia>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Elekti Ankron",
+DlgLnkAnchorByName : "Per Ankronomo",
+DlgLnkAnchorById : "Per Elementidentigilo",
+DlgLnkNoAnchors : "<Ne disponeblas ankroj en la dokumento>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Retadreso",
+DlgLnkEMailSubject : "Temlinio",
+DlgLnkEMailBody : "Mesaĝa korpo",
+DlgLnkUpload : "Alŝuti",
+DlgLnkBtnUpload : "Sendi al Servilo",
+
+DlgLnkTarget : "Celo",
+DlgLnkTargetFrame : "<kadro>",
+DlgLnkTargetPopup : "<ŝprucfenestro>",
+DlgLnkTargetBlank : "Nova Fenestro (_blank)",
+DlgLnkTargetParent : "Gepatra Fenestro (_parent)",
+DlgLnkTargetSelf : "Sama Fenestro (_self)",
+DlgLnkTargetTop : "Plej Supra Fenestro (_top)",
+DlgLnkTargetFrameName : "Nomo de Kadro",
+DlgLnkPopWinName : "Nomo de Ŝprucfenestro",
+DlgLnkPopWinFeat : "Atributoj de la Ŝprucfenestro",
+DlgLnkPopResize : "Grando Ŝanĝebla",
+DlgLnkPopLocation : "Adresobreto",
+DlgLnkPopMenu : "Menubreto",
+DlgLnkPopScroll : "Rulumlisteloj",
+DlgLnkPopStatus : "Statobreto",
+DlgLnkPopToolbar : "Ilobreto",
+DlgLnkPopFullScrn : "Tutekrane (IE)",
+DlgLnkPopDependent : "Dependa (Netscape)",
+DlgLnkPopWidth : "Larĝo",
+DlgLnkPopHeight : "Alto",
+DlgLnkPopLeft : "Pozicio de Maldekstro",
+DlgLnkPopTop : "Pozicio de Supro",
+
+DlnLnkMsgNoUrl : "Bonvolu entajpi la URL-on",
+DlnLnkMsgNoEMail : "Bonvolu entajpi la retadreson",
+DlnLnkMsgNoAnchor : "Bonvolu elekti ankron",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Elekti",
+DlgColorBtnClear : "Forigi",
+DlgColorHighlight : "Emfazi",
+DlgColorSelected : "Elektita",
+
+// Smiley Dialog
+DlgSmileyTitle : "Enmeti Mienvinjeton",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Enmeti Specialan Signon",
+
+// Table Dialog
+DlgTableTitle : "Atributoj de Tabelo",
+DlgTableRows : "Linioj",
+DlgTableColumns : "Kolumnoj",
+DlgTableBorder : "Bordero",
+DlgTableAlign : "Ĝisrandigo",
+DlgTableAlignNotSet : "<Defaŭlte>",
+DlgTableAlignLeft : "Maldekstre",
+DlgTableAlignCenter : "Centre",
+DlgTableAlignRight : "Dekstre",
+DlgTableWidth : "Larĝo",
+DlgTableWidthPx : "Bitbilderoj",
+DlgTableWidthPc : "elcentoj",
+DlgTableHeight : "Alto",
+DlgTableCellSpace : "Interspacigo de Ĉeloj",
+DlgTableCellPad : "Ĉirkaŭenhava Plenigado",
+DlgTableCaption : "Titolo",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Atributoj de Celo",
+DlgCellWidth : "Larĝo",
+DlgCellWidthPx : "bitbilderoj",
+DlgCellWidthPc : "elcentoj",
+DlgCellHeight : "Alto",
+DlgCellWordWrap : "Linifaldo",
+DlgCellWordWrapNotSet : "<Defaŭlte>",
+DlgCellWordWrapYes : "Jes",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Horizonta Ĝisrandigo",
+DlgCellHorAlignNotSet : "<Defaŭlte>",
+DlgCellHorAlignLeft : "Maldekstre",
+DlgCellHorAlignCenter : "Centre",
+DlgCellHorAlignRight: "Dekstre",
+DlgCellVerAlign : "Vertikala Ĝisrandigo",
+DlgCellVerAlignNotSet : "<Defaŭlte>",
+DlgCellVerAlignTop : "Supre",
+DlgCellVerAlignMiddle : "Centre",
+DlgCellVerAlignBottom : "Malsupre",
+DlgCellVerAlignBaseline : "Je Malsupro de Teksto",
+DlgCellRowSpan : "Linioj Kunfanditaj",
+DlgCellCollSpan : "Kolumnoj Kunfanditaj",
+DlgCellBackColor : "Fono",
+DlgCellBorderColor : "Bordero",
+DlgCellBtnSelect : "Elekti...",
+
+// Find Dialog
+DlgFindTitle : "Serĉi",
+DlgFindFindBtn : "Serĉi",
+DlgFindNotFoundMsg : "La celteksto ne estas trovita.",
+
+// Replace Dialog
+DlgReplaceTitle : "Anstataŭigi",
+DlgReplaceFindLbl : "Serĉi:",
+DlgReplaceReplaceLbl : "Anstataŭigi per:",
+DlgReplaceCaseChk : "Kongruigi Usklecon",
+DlgReplaceReplaceBtn : "Anstataŭigi",
+DlgReplaceReplAllBtn : "Anstataŭigi Ĉiun",
+DlgReplaceWordChk : "Tuta Vorto",
+
+// Paste Operations / Dialog
+PasteErrorCut : "La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras eltondajn operaciojn. Bonvolu uzi la klavaron por tio (ctrl-X).",
+PasteErrorCopy : "La sekurecagordo de via TTT-legilo ne permesas, ke la redaktilo faras kopiajn operaciojn. Bonvolu uzi la klavaron por tio (ctrl-C).",
+
+PasteAsText : "Interglui kiel Tekston",
+PasteFromWord : "Interglui el Word",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.", //MISSING
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING
+DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING
+DlgPasteCleanBox : "Clean Up Box", //MISSING
+
+// Color Picker
+ColorAutomatic : "Aŭtomata",
+ColorMoreColors : "Pli da Koloroj...",
+
+// Document Properties
+DocProps : "Dokumentaj Atributoj",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankraj Atributoj",
+DlgAnchorName : "Ankra Nomo",
+DlgAnchorErrorName : "Bv tajpi la ankran nomon",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ne trovita en la vortaro",
+DlgSpellChangeTo : "Ŝanĝi al",
+DlgSpellBtnIgnore : "Malatenti",
+DlgSpellBtnIgnoreAll : "Malatenti Ĉiun",
+DlgSpellBtnReplace : "Anstataŭigi",
+DlgSpellBtnReplaceAll : "Anstataŭigi Ĉiun",
+DlgSpellBtnUndo : "Malfari",
+DlgSpellNoSuggestions : "- Neniu propono -",
+DlgSpellProgress : "Literumkontrolado daŭras...",
+DlgSpellNoMispell : "Literumkontrolado finita: neniu fuŝo trovita",
+DlgSpellNoChanges : "Literumkontrolado finita: neniu vorto ŝanĝita",
+DlgSpellOneChange : "Literumkontrolado finita: unu vorto ŝanĝita",
+DlgSpellManyChanges : "Literumkontrolado finita: %1 vortoj ŝanĝitaj",
+
+IeSpellDownload : "Literumada Kontrolilo ne instalita. Ĉu vi volas elŝuti ĝin nun?",
+
+// Button Dialog
+DlgButtonText : "Teksto (Valoro)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nomo",
+DlgCheckboxValue : "Valoro",
+DlgCheckboxSelected : "Elektita",
+
+// Form Dialog
+DlgFormName : "Nomo",
+DlgFormAction : "Ago",
+DlgFormMethod : "Metodo",
+
+// Select Field Dialog
+DlgSelectName : "Nomo",
+DlgSelectValue : "Valoro",
+DlgSelectSize : "Grando",
+DlgSelectLines : "Linioj",
+DlgSelectChkMulti : "Permesi Plurajn Elektojn",
+DlgSelectOpAvail : "Elektoj Disponeblaj",
+DlgSelectOpText : "Teksto",
+DlgSelectOpValue : "Valoro",
+DlgSelectBtnAdd : "Aldoni",
+DlgSelectBtnModify : "Modifi",
+DlgSelectBtnUp : "Supren",
+DlgSelectBtnDown : "Malsupren",
+DlgSelectBtnSetValue : "Agordi kiel Elektitan Valoron",
+DlgSelectBtnDelete : "Forigi",
+
+// Textarea Dialog
+DlgTextareaName : "Nomo",
+DlgTextareaCols : "Kolumnoj",
+DlgTextareaRows : "Vicoj",
+
+// Text Field Dialog
+DlgTextName : "Nomo",
+DlgTextValue : "Valoro",
+DlgTextCharWidth : "Signolarĝo",
+DlgTextMaxChars : "Maksimuma Nombro da Signoj",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Teksto",
+DlgTextTypePass : "Pasvorto",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nomo",
+DlgHiddenValue : "Valoro",
+
+// Bulleted List Dialog
+BulletedListProp : "Atributoj de Bula Listo",
+NumberedListProp : "Atributoj de Numera Listo",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Cirklo",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Kvadrato",
+DlgLstTypeNumbers : "Ciferoj (1, 2, 3)",
+DlgLstTypeLCase : "Minusklaj Literoj (a, b, c)",
+DlgLstTypeUCase : "Majusklaj Literoj (A, B, C)",
+DlgLstTypeSRoman : "Malgrandaj Romanaj Ciferoj (i, ii, iii)",
+DlgLstTypeLRoman : "Grandaj Romanaj Ciferoj (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Ĝeneralaĵoj",
+DlgDocBackTab : "Fono",
+DlgDocColorsTab : "Koloroj kaj Marĝenoj",
+DlgDocMetaTab : "Metadatumoj",
+
+DlgDocPageTitle : "Paĝotitolo",
+DlgDocLangDir : "Skribdirekto de la Lingvo",
+DlgDocLangDirLTR : "De maldekstro dekstren (LTR)",
+DlgDocLangDirRTL : "De dekstro maldekstren (LTR)",
+DlgDocLangCode : "Lingvokodo",
+DlgDocCharSet : "Signara Kodo",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Alia Signara Kodo",
+
+DlgDocDocType : "Dokumenta Tipo",
+DlgDocDocTypeOther : "Alia Dokumenta Tipo",
+DlgDocIncXHTML : "Inkluzivi XHTML Deklaroj",
+DlgDocBgColor : "Fona Koloro",
+DlgDocBgImage : "URL de Fona Bildo",
+DlgDocBgNoScroll : "Neruluma Fono",
+DlgDocCText : "Teksto",
+DlgDocCLink : "Ligilo",
+DlgDocCVisited : "Vizitita Ligilo",
+DlgDocCActive : "Aktiva Ligilo",
+DlgDocMargins : "Paĝaj Marĝenoj",
+DlgDocMaTop : "Supra",
+DlgDocMaLeft : "Maldekstra",
+DlgDocMaRight : "Dekstra",
+DlgDocMaBottom : "Malsupra",
+DlgDocMeIndex : "Ŝlosilvortoj de la Dokumento (apartigita de komoj)",
+DlgDocMeDescr : "Dokumenta Priskribo",
+DlgDocMeAuthor : "Verkinto",
+DlgDocMeCopy : "Kopirajto",
+DlgDocPreview : "Aspekto",
+
+// Templates Dialog
+Templates : "Templates", //MISSING
+DlgTemplatesTitle : "Content Templates", //MISSING
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br />(the actual contents will be lost):", //MISSING
+DlgTemplatesLoading : "Loading templates list. Please wait...", //MISSING
+DlgTemplatesNoTpl : "(No templates defined)", //MISSING
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Pri",
+DlgAboutBrowserInfoTab : "Informoj pri TTT-legilo",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "versio",
+DlgAboutInfo : "Por pli da informoj, vizitu"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/es.js b/httemplate/elements/fckeditor/editor/lang/es.js
new file mode 100644
index 000000000..cfed8085c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/es.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Spanish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Contraer Barra",
+ToolbarExpand : "Expandir Barra",
+
+// Toolbar Items and Context Menu
+Save : "Guardar",
+NewPage : "Nueva Página",
+Preview : "Vista Previa",
+Cut : "Cortar",
+Copy : "Copiar",
+Paste : "Pegar",
+PasteText : "Pegar como texto plano",
+PasteWord : "Pegar desde Word",
+Print : "Imprimir",
+SelectAll : "Seleccionar Todo",
+RemoveFormat : "Eliminar Formato",
+InsertLinkLbl : "Vínculo",
+InsertLink : "Insertar/Editar Vínculo",
+RemoveLink : "Eliminar Vínculo",
+Anchor : "Referencia",
+InsertImageLbl : "Imagen",
+InsertImage : "Insertar/Editar Imagen",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insertar/Editar Flash",
+InsertTableLbl : "Tabla",
+InsertTable : "Insertar/Editar Tabla",
+InsertLineLbl : "Línea",
+InsertLine : "Insertar Línea Horizontal",
+InsertSpecialCharLbl: "Caracter Especial",
+InsertSpecialChar : "Insertar Caracter Especial",
+InsertSmileyLbl : "Emoticons",
+InsertSmiley : "Insertar Emoticons",
+About : "Acerca de FCKeditor",
+Bold : "Negrita",
+Italic : "Cursiva",
+Underline : "Subrayado",
+StrikeThrough : "Tachado",
+Subscript : "Subíndice",
+Superscript : "Superíndice",
+LeftJustify : "Alinear a Izquierda",
+CenterJustify : "Centrar",
+RightJustify : "Alinear a Derecha",
+BlockJustify : "Justificado",
+DecreaseIndent : "Disminuir Sangría",
+IncreaseIndent : "Aumentar Sangría",
+Undo : "Deshacer",
+Redo : "Rehacer",
+NumberedListLbl : "Numeración",
+NumberedList : "Insertar/Eliminar Numeración",
+BulletedListLbl : "Viñetas",
+BulletedList : "Insertar/Eliminar Viñetas",
+ShowTableBorders : "Mostrar Bordes de Tablas",
+ShowDetails : "Mostrar saltos de Párrafo",
+Style : "Estilo",
+FontFormat : "Formato",
+Font : "Fuente",
+FontSize : "Tamaño",
+TextColor : "Color de Texto",
+BGColor : "Color de Fondo",
+Source : "Fuente HTML",
+Find : "Buscar",
+Replace : "Reemplazar",
+SpellCheck : "Ortografía",
+UniversalKeyboard : "Teclado Universal",
+PageBreakLbl : "Salto de Página",
+PageBreak : "Insertar Salto de Página",
+
+Form : "Formulario",
+Checkbox : "Casilla de Verificación",
+RadioButton : "Botones de Radio",
+TextField : "Campo de Texto",
+Textarea : "Area de Texto",
+HiddenField : "Campo Oculto",
+Button : "Botón",
+SelectionField : "Campo de Selección",
+ImageButton : "Botón Imagen",
+
+FitWindow : "Maximizar el tamaño del editor",
+
+// Context Menu
+EditLink : "Editar Vínculo",
+CellCM : "Celda",
+RowCM : "Fila",
+ColumnCM : "Columna",
+InsertRow : "Insertar Fila",
+DeleteRows : "Eliminar Filas",
+InsertColumn : "Insertar Columna",
+DeleteColumns : "Eliminar Columnas",
+InsertCell : "Insertar Celda",
+DeleteCells : "Eliminar Celdas",
+MergeCells : "Combinar Celdas",
+SplitCell : "Dividir Celda",
+TableDelete : "Eliminar Tabla",
+CellProperties : "Propiedades de Celda",
+TableProperties : "Propiedades de Tabla",
+ImageProperties : "Propiedades de Imagen",
+FlashProperties : "Propiedades de Flash",
+
+AnchorProp : "Propiedades de Referencia",
+ButtonProp : "Propiedades de Botón",
+CheckboxProp : "Propiedades de Casilla",
+HiddenFieldProp : "Propiedades de Campo Oculto",
+RadioButtonProp : "Propiedades de Botón de Radio",
+ImageButtonProp : "Propiedades de Botón de Imagen",
+TextFieldProp : "Propiedades de Campo de Texto",
+SelectionFieldProp : "Propiedades de Campo de Selección",
+TextareaProp : "Propiedades de Area de Texto",
+FormProp : "Propiedades de Formulario",
+
+FontFormats : "Normal;Con formato;Dirección;Encabezado 1;Encabezado 2;Encabezado 3;Encabezado 4;Encabezado 5;Encabezado 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Procesando XHTML. Por favor, espere...",
+Done : "Hecho",
+PasteWordConfirm : "El texto que desea parece provenir de Word. Desea depurarlo antes de pegarlo?",
+NotCompatiblePaste : "Este comando está disponible sólo para Internet Explorer version 5.5 or superior. Desea pegar sin depurar?",
+UnknownToolbarItem : "Item de barra desconocido \"%1\"",
+UnknownCommand : "Nombre de comando desconocido \"%1\"",
+NotImplemented : "Comando no implementado",
+UnknownToolbarSet : "Nombre de barra \"%1\" no definido",
+NoActiveX : "La configuración de las opciones de seguridad de su navegador puede estar limitando algunas características del editor. Por favor active la opción \"Ejecutar controles y complementos de ActiveX \", de lo contrario puede experimentar errores o ausencia de funcionalidades.",
+BrowseServerBlocked : "La ventana de visualización del servidor no pudo ser abierta. Verifique que su navegador no esté bloqueando las ventanas emergentes (pop up).",
+DialogBlocked : "No se ha podido abrir la ventana de diálogo. Verifique que su navegador no esté bloqueando las ventanas emergentes (pop up).",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancelar",
+DlgBtnClose : "Cerrar",
+DlgBtnBrowseServer : "Ver Servidor",
+DlgAdvancedTag : "Avanzado",
+DlgOpOther : "<Otro>",
+DlgInfoTab : "Información",
+DlgAlertUrl : "Inserte el URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<No definido>",
+DlgGenId : "Id",
+DlgGenLangDir : "Orientación de idioma",
+DlgGenLangDirLtr : "Izquierda a Derecha (LTR)",
+DlgGenLangDirRtl : "Derecha a Izquierda (RTL)",
+DlgGenLangCode : "Código de idioma",
+DlgGenAccessKey : "Clave de Acceso",
+DlgGenName : "Nombre",
+DlgGenTabIndex : "Indice de tabulación",
+DlgGenLongDescr : "Descripción larga URL",
+DlgGenClass : "Clases de hojas de estilo",
+DlgGenTitle : "Título",
+DlgGenContType : "Tipo de Contenido",
+DlgGenLinkCharset : "Fuente de caracteres vinculado",
+DlgGenStyle : "Estilo",
+
+// Image Dialog
+DlgImgTitle : "Propiedades de Imagen",
+DlgImgInfoTab : "Información de Imagen",
+DlgImgBtnUpload : "Enviar al Servidor",
+DlgImgURL : "URL",
+DlgImgUpload : "Cargar",
+DlgImgAlt : "Texto Alternativo",
+DlgImgWidth : "Anchura",
+DlgImgHeight : "Altura",
+DlgImgLockRatio : "Proporcional",
+DlgBtnResetSize : "Tamaño Original",
+DlgImgBorder : "Borde",
+DlgImgHSpace : "Esp.Horiz",
+DlgImgVSpace : "Esp.Vert",
+DlgImgAlign : "Alineación",
+DlgImgAlignLeft : "Izquierda",
+DlgImgAlignAbsBottom: "Abs inferior",
+DlgImgAlignAbsMiddle: "Abs centro",
+DlgImgAlignBaseline : "Línea de base",
+DlgImgAlignBottom : "Pie",
+DlgImgAlignMiddle : "Centro",
+DlgImgAlignRight : "Derecha",
+DlgImgAlignTextTop : "Tope del texto",
+DlgImgAlignTop : "Tope",
+DlgImgPreview : "Vista Previa",
+DlgImgAlertUrl : "Por favor tipee el URL de la imagen",
+DlgImgLinkTab : "Vínculo",
+
+// Flash Dialog
+DlgFlashTitle : "Propiedades de Flash",
+DlgFlashChkPlay : "Autoejecución",
+DlgFlashChkLoop : "Repetir",
+DlgFlashChkMenu : "Activar Menú Flash",
+DlgFlashScale : "Escala",
+DlgFlashScaleAll : "Mostrar todo",
+DlgFlashScaleNoBorder : "Sin Borde",
+DlgFlashScaleFit : "Ajustado",
+
+// Link Dialog
+DlgLnkWindowTitle : "Vínculo",
+DlgLnkInfoTab : "Información de Vínculo",
+DlgLnkTargetTab : "Destino",
+
+DlgLnkType : "Tipo de vínculo",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Referencia en esta página",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocolo",
+DlgLnkProtoOther : "<otro>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Seleccionar una referencia",
+DlgLnkAnchorByName : "Por Nombre de Referencia",
+DlgLnkAnchorById : "Por ID de elemento",
+DlgLnkNoAnchors : "<No hay referencias disponibles en el documento>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Dirección de E-Mail",
+DlgLnkEMailSubject : "Título del Mensaje",
+DlgLnkEMailBody : "Cuerpo del Mensaje",
+DlgLnkUpload : "Cargar",
+DlgLnkBtnUpload : "Enviar al Servidor",
+
+DlgLnkTarget : "Destino",
+DlgLnkTargetFrame : "<marco>",
+DlgLnkTargetPopup : "<ventana emergente>",
+DlgLnkTargetBlank : "Nueva Ventana(_blank)",
+DlgLnkTargetParent : "Ventana Padre (_parent)",
+DlgLnkTargetSelf : "Misma Ventana (_self)",
+DlgLnkTargetTop : "Ventana primaria (_top)",
+DlgLnkTargetFrameName : "Nombre del Marco Destino",
+DlgLnkPopWinName : "Nombre de Ventana Emergente",
+DlgLnkPopWinFeat : "Características de Ventana Emergente",
+DlgLnkPopResize : "Ajustable",
+DlgLnkPopLocation : "Barra de ubicación",
+DlgLnkPopMenu : "Barra de Menú",
+DlgLnkPopScroll : "Barras de desplazamiento",
+DlgLnkPopStatus : "Barra de Estado",
+DlgLnkPopToolbar : "Barra de Herramientas",
+DlgLnkPopFullScrn : "Pantalla Completa (IE)",
+DlgLnkPopDependent : "Dependiente (Netscape)",
+DlgLnkPopWidth : "Anchura",
+DlgLnkPopHeight : "Altura",
+DlgLnkPopLeft : "Posición Izquierda",
+DlgLnkPopTop : "Posición Derecha",
+
+DlnLnkMsgNoUrl : "Por favor tipee el vínculo URL",
+DlnLnkMsgNoEMail : "Por favor tipee la dirección de e-mail",
+DlnLnkMsgNoAnchor : "Por favor seleccione una referencia",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Seleccionar Color",
+DlgColorBtnClear : "Ninguno",
+DlgColorHighlight : "Resaltado",
+DlgColorSelected : "Seleccionado",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insertar un Emoticon",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Seleccione un caracter especial",
+
+// Table Dialog
+DlgTableTitle : "Propiedades de Tabla",
+DlgTableRows : "Filas",
+DlgTableColumns : "Columnas",
+DlgTableBorder : "Tamaño de Borde",
+DlgTableAlign : "Alineación",
+DlgTableAlignNotSet : "<No establecido>",
+DlgTableAlignLeft : "Izquierda",
+DlgTableAlignCenter : "Centrado",
+DlgTableAlignRight : "Derecha",
+DlgTableWidth : "Anchura",
+DlgTableWidthPx : "pixeles",
+DlgTableWidthPc : "porcentaje",
+DlgTableHeight : "Altura",
+DlgTableCellSpace : "Esp. e/celdas",
+DlgTableCellPad : "Esp. interior",
+DlgTableCaption : "Título",
+DlgTableSummary : "Síntesis",
+
+// Table Cell Dialog
+DlgCellTitle : "Propiedades de Celda",
+DlgCellWidth : "Anchura",
+DlgCellWidthPx : "pixeles",
+DlgCellWidthPc : "porcentaje",
+DlgCellHeight : "Altura",
+DlgCellWordWrap : "Cortar Línea",
+DlgCellWordWrapNotSet : "<No establecido>",
+DlgCellWordWrapYes : "Si",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Alineación Horizontal",
+DlgCellHorAlignNotSet : "<No establecido>",
+DlgCellHorAlignLeft : "Izquierda",
+DlgCellHorAlignCenter : "Centrado",
+DlgCellHorAlignRight: "Derecha",
+DlgCellVerAlign : "Alineación Vertical",
+DlgCellVerAlignNotSet : "<Not establecido>",
+DlgCellVerAlignTop : "Tope",
+DlgCellVerAlignMiddle : "Medio",
+DlgCellVerAlignBottom : "ie",
+DlgCellVerAlignBaseline : "Línea de Base",
+DlgCellRowSpan : "Abarcar Filas",
+DlgCellCollSpan : "Abarcar Columnas",
+DlgCellBackColor : "Color de Fondo",
+DlgCellBorderColor : "Color de Borde",
+DlgCellBtnSelect : "Seleccione...",
+
+// Find Dialog
+DlgFindTitle : "Buscar",
+DlgFindFindBtn : "Buscar",
+DlgFindNotFoundMsg : "El texto especificado no ha sido encontrado.",
+
+// Replace Dialog
+DlgReplaceTitle : "Reemplazar",
+DlgReplaceFindLbl : "Texto a buscar:",
+DlgReplaceReplaceLbl : "Reemplazar con:",
+DlgReplaceCaseChk : "Coincidir may/min",
+DlgReplaceReplaceBtn : "Reemplazar",
+DlgReplaceReplAllBtn : "Reemplazar Todo",
+DlgReplaceWordChk : "Coincidir toda la palabra",
+
+// Paste Operations / Dialog
+PasteErrorCut : "La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado. Por favor use el teclado (Ctrl+X).",
+PasteErrorCopy : "La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de copiado. Por favor use el teclado (Ctrl+C).",
+
+PasteAsText : "Pegar como Texto Plano",
+PasteFromWord : "Pegar desde Word",
+
+DlgPasteMsg2 : "Por favor pegue dentro del cuadro utilizando el teclado (<STRONG>Ctrl+V</STRONG>); luego presione <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorar definiciones de fuentes",
+DlgPasteRemoveStyles : "Remover definiciones de estilo",
+DlgPasteCleanBox : "Borrar el contenido del cuadro",
+
+// Color Picker
+ColorAutomatic : "Automático",
+ColorMoreColors : "Más Colores...",
+
+// Document Properties
+DocProps : "Propiedades del Documento",
+
+// Anchor Dialog
+DlgAnchorTitle : "Propiedades de la Referencia",
+DlgAnchorName : "Nombre de la Referencia",
+DlgAnchorErrorName : "Por favor, complete el nombre de la Referencia",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "No se encuentra en el Diccionario",
+DlgSpellChangeTo : "Cambiar a",
+DlgSpellBtnIgnore : "Ignorar",
+DlgSpellBtnIgnoreAll : "Ignorar Todo",
+DlgSpellBtnReplace : "Reemplazar",
+DlgSpellBtnReplaceAll : "Reemplazar Todo",
+DlgSpellBtnUndo : "Deshacer",
+DlgSpellNoSuggestions : "- No hay sugerencias -",
+DlgSpellProgress : "Control de Ortografía en progreso...",
+DlgSpellNoMispell : "Control finalizado: no se encontraron errores",
+DlgSpellNoChanges : "Control finalizado: no se ha cambiado ninguna palabra",
+DlgSpellOneChange : "Control finalizado: se ha cambiado una palabra",
+DlgSpellManyChanges : "Control finalizado: se ha cambiado %1 palabras",
+
+IeSpellDownload : "Módulo de Control de Ortografía no instalado. ¿Desea descargarlo ahora?",
+
+// Button Dialog
+DlgButtonText : "Texto (Valor)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nombre",
+DlgCheckboxValue : "Valor",
+DlgCheckboxSelected : "Seleccionado",
+
+// Form Dialog
+DlgFormName : "Nombre",
+DlgFormAction : "Acción",
+DlgFormMethod : "Método",
+
+// Select Field Dialog
+DlgSelectName : "Nombre",
+DlgSelectValue : "Valor",
+DlgSelectSize : "Tamaño",
+DlgSelectLines : "Lineas",
+DlgSelectChkMulti : "Permitir múltiple selección",
+DlgSelectOpAvail : "Opciones disponibles",
+DlgSelectOpText : "Texto",
+DlgSelectOpValue : "Valor",
+DlgSelectBtnAdd : "Agregar",
+DlgSelectBtnModify : "Modificar",
+DlgSelectBtnUp : "Subir",
+DlgSelectBtnDown : "Bajar",
+DlgSelectBtnSetValue : "Establecer como predeterminado",
+DlgSelectBtnDelete : "Eliminar",
+
+// Textarea Dialog
+DlgTextareaName : "Nombre",
+DlgTextareaCols : "Columnas",
+DlgTextareaRows : "Filas",
+
+// Text Field Dialog
+DlgTextName : "Nombre",
+DlgTextValue : "Valor",
+DlgTextCharWidth : "Caracteres de ancho",
+DlgTextMaxChars : "Máximo caracteres",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Texto",
+DlgTextTypePass : "Contraseña",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nombre",
+DlgHiddenValue : "Valor",
+
+// Bulleted List Dialog
+BulletedListProp : "Propiedades de Viñetas",
+NumberedListProp : "Propiedades de Numeraciones",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Círculo",
+DlgLstTypeDisc : "Disco",
+DlgLstTypeSquare : "Cuadrado",
+DlgLstTypeNumbers : "Números (1, 2, 3)",
+DlgLstTypeLCase : "letras en minúsculas (a, b, c)",
+DlgLstTypeUCase : "letras en mayúsculas (A, B, C)",
+DlgLstTypeSRoman : "Números Romanos (i, ii, iii)",
+DlgLstTypeLRoman : "Números Romanos (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Fondo",
+DlgDocColorsTab : "Colores y Márgenes",
+DlgDocMetaTab : "Meta Información",
+
+DlgDocPageTitle : "Título de Página",
+DlgDocLangDir : "Orientación de idioma",
+DlgDocLangDirLTR : "Izq. a Derecha (LTR)",
+DlgDocLangDirRTL : "Der. a Izquierda (RTL)",
+DlgDocLangCode : "Código de Idioma",
+DlgDocCharSet : "Codif. de Conjunto de Caracteres",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Otra Codificación",
+
+DlgDocDocType : "Encabezado de Tipo de Documento",
+DlgDocDocTypeOther : "Otro Encabezado",
+DlgDocIncXHTML : "Incluir Declaraciones XHTML",
+DlgDocBgColor : "Color de Fondo",
+DlgDocBgImage : "URL de Imagen de Fondo",
+DlgDocBgNoScroll : "Fondo sin rolido",
+DlgDocCText : "Texto",
+DlgDocCLink : "Vínculo",
+DlgDocCVisited : "Vínculo Visitado",
+DlgDocCActive : "Vínculo Activo",
+DlgDocMargins : "Márgenes de Página",
+DlgDocMaTop : "Tope",
+DlgDocMaLeft : "Izquierda",
+DlgDocMaRight : "Derecha",
+DlgDocMaBottom : "Pie",
+DlgDocMeIndex : "Claves de indexación del Documento (separados por comas)",
+DlgDocMeDescr : "Descripción del Documento",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Vista Previa",
+
+// Templates Dialog
+Templates : "Plantillas",
+DlgTemplatesTitle : "Contenido de Plantillas",
+DlgTemplatesSelMsg : "Por favor selecciona la plantilla a abrir en el editor<br>(el contenido actual se perderá):",
+DlgTemplatesLoading : "Cargando lista de Plantillas. Por favor, aguarde...",
+DlgTemplatesNoTpl : "(No hay plantillas definidas)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Acerca de",
+DlgAboutBrowserInfoTab : "Información de Navegador",
+DlgAboutLicenseTab : "Licencia",
+DlgAboutVersion : "versión",
+DlgAboutInfo : "Para mayor información por favor dirigirse a"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/et.js b/httemplate/elements/fckeditor/editor/lang/et.js
new file mode 100644
index 000000000..53a147e11
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/et.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Estonian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Voldi tööriistariba",
+ToolbarExpand : "Laienda tööriistariba",
+
+// Toolbar Items and Context Menu
+Save : "Salvesta",
+NewPage : "Uus leht",
+Preview : "Eelvaade",
+Cut : "Lõika",
+Copy : "Kopeeri",
+Paste : "Kleebi",
+PasteText : "Kleebi tavalise tekstina",
+PasteWord : "Kleebi Wordist",
+Print : "Prindi",
+SelectAll : "Vali kõik",
+RemoveFormat : "Eemalda vorming",
+InsertLinkLbl : "Link",
+InsertLink : "Sisesta/Muuda link",
+RemoveLink : "Eemalda link",
+Anchor : "Sisesta/Muuda ankur",
+InsertImageLbl : "Pilt",
+InsertImage : "Sisesta/Muuda pilt",
+InsertFlashLbl : "Flash",
+InsertFlash : "Sisesta/Muuda flash",
+InsertTableLbl : "Tabel",
+InsertTable : "Sisesta/Muuda tabel",
+InsertLineLbl : "Joon",
+InsertLine : "Sisesta horisontaaljoon",
+InsertSpecialCharLbl: "Erimärgid",
+InsertSpecialChar : "Sisesta erimärk",
+InsertSmileyLbl : "Emotikon",
+InsertSmiley : "Sisesta emotikon",
+About : "FCKeditor teave",
+Bold : "Rasvane kiri",
+Italic : "Kursiiv kiri",
+Underline : "Allajoonitud kiri",
+StrikeThrough : "Läbijoonitud kiri",
+Subscript : "Allindeks",
+Superscript : "Ülaindeks",
+LeftJustify : "Vasakjoondus",
+CenterJustify : "Keskjoondus",
+RightJustify : "Paremjoondus",
+BlockJustify : "Rööpjoondus",
+DecreaseIndent : "Vähenda taanet",
+IncreaseIndent : "Suurenda taanet",
+Undo : "Võta tagasi",
+Redo : "Korda toimingut",
+NumberedListLbl : "Nummerdatud loetelu",
+NumberedList : "Sisesta/Eemalda nummerdatud loetelu",
+BulletedListLbl : "Punktiseeritud loetelu",
+BulletedList : "Sisesta/Eemalda punktiseeritud loetelu",
+ShowTableBorders : "Näita tabeli jooni",
+ShowDetails : "Näita üksikasju",
+Style : "Laad",
+FontFormat : "Vorming",
+Font : "Kiri",
+FontSize : "Suurus",
+TextColor : "Teksti värv",
+BGColor : "Tausta värv",
+Source : "Lähtekood",
+Find : "Otsi",
+Replace : "Asenda",
+SpellCheck : "Kontrolli õigekirja",
+UniversalKeyboard : "Universaalne klaviatuur",
+PageBreakLbl : "Lehepiir",
+PageBreak : "Sisesta lehevahetus koht",
+
+Form : "Vorm",
+Checkbox : "Märkeruut",
+RadioButton : "Raadionupp",
+TextField : "Tekstilahter",
+Textarea : "Tekstiala",
+HiddenField : "Varjatud lahter",
+Button : "Nupp",
+SelectionField : "Valiklahter",
+ImageButton : "Piltnupp",
+
+FitWindow : "Maksimeeri redaktori mõõtmed",
+
+// Context Menu
+EditLink : "Muuda linki",
+CellCM : "Lahter",
+RowCM : "Rida",
+ColumnCM : "Veerg",
+InsertRow : "Lisa rida",
+DeleteRows : "Eemalda ridu",
+InsertColumn : "Lisa veerg",
+DeleteColumns : "Eemalda veerud",
+InsertCell : "Lisa lahter",
+DeleteCells : "Eemalda lahtrid",
+MergeCells : "Ühenda lahtrid",
+SplitCell : "Lahuta lahtrid",
+TableDelete : "Kustuta tabel",
+CellProperties : "Lahtri atribuudid",
+TableProperties : "Tabeli atribuudid",
+ImageProperties : "Pildi atribuudid",
+FlashProperties : "Flash omadused",
+
+AnchorProp : "Ankru omadused",
+ButtonProp : "Nupu omadused",
+CheckboxProp : "Märkeruudu omadused",
+HiddenFieldProp : "Varjatud lahtri omadused",
+RadioButtonProp : "Raadionupu omadused",
+ImageButtonProp : "Piltnupu omadused",
+TextFieldProp : "Tekstilahtri omadused",
+SelectionFieldProp : "Valiklahtri omadused",
+TextareaProp : "Tekstiala omadused",
+FormProp : "Vormi omadused",
+
+FontFormats : "Tavaline;Vormindatud;Aadress;Pealkiri 1;Pealkiri 2;Pealkiri 3;Pealkiri 4;Pealkiri 5;Pealkiri 6;Tavaline (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Töötlen XHTML. Palun oota...",
+Done : "Tehtud",
+PasteWordConfirm : "Tekst, mida soovid lisada paistab pärinevat Wordist. Kas soovid seda enne kleepimist puhastada?",
+NotCompatiblePaste : "See käsk on saadaval ainult Internet Explorer versioon 5.5 või uuema puhul. Kas soovid kleepida ilma puhastamata?",
+UnknownToolbarItem : "Tundmatu tööriistariba üksus \"%1\"",
+UnknownCommand : "Tundmatu käsunimi \"%1\"",
+NotImplemented : "Käsku ei täidetud",
+UnknownToolbarSet : "Tööriistariba \"%1\" ei eksisteeri",
+NoActiveX : "Sinu veebisirvija turvalisuse seaded võivad limiteerida mõningaid tekstirdaktori kasutus võimalusi. Sa peaksid võimaldama valiku \"Run ActiveX controls and plug-ins\" oma sirvija seadetes. Muidu võid sa täheldada vigu tekstiredaktori töös ja märgata puuduvaid funktsioone.",
+BrowseServerBlocked : "Ressursside sirvija avamine ebaõnnestus. Võimalda pop-up akende avanemine.",
+DialogBlocked : "Ei olenud võimalik avada dialoogi akent. Võimalda pop-up akende avanemine.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Loobu",
+DlgBtnClose : "Sulge",
+DlgBtnBrowseServer : "Sirvi serverit",
+DlgAdvancedTag : "Täpsemalt",
+DlgOpOther : "<Teine>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Palun sisesta URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<määramata>",
+DlgGenId : "Id",
+DlgGenLangDir : "Keele suund",
+DlgGenLangDirLtr : "Vasakult paremale (LTR)",
+DlgGenLangDirRtl : "Paremalt vasakule (RTL)",
+DlgGenLangCode : "Keele kood",
+DlgGenAccessKey : "Juurdepääsu võti",
+DlgGenName : "Nimi",
+DlgGenTabIndex : "Tab indeks",
+DlgGenLongDescr : "Pikk kirjeldus URL",
+DlgGenClass : "Stiilistiku klassid",
+DlgGenTitle : "Juhendav tiitel",
+DlgGenContType : "Juhendava sisu tüüp",
+DlgGenLinkCharset : "Lingitud ressurssi märgistik",
+DlgGenStyle : "Laad",
+
+// Image Dialog
+DlgImgTitle : "Pildi atribuudid",
+DlgImgInfoTab : "Pildi info",
+DlgImgBtnUpload : "Saada serverissee",
+DlgImgURL : "URL",
+DlgImgUpload : "Lae üles",
+DlgImgAlt : "Alternatiivne tekst",
+DlgImgWidth : "Laius",
+DlgImgHeight : "Kõrgus",
+DlgImgLockRatio : "Lukusta kuvasuhe",
+DlgBtnResetSize : "Lähtesta suurus",
+DlgImgBorder : "Joon",
+DlgImgHSpace : "H. vaheruum",
+DlgImgVSpace : "V. vaheruum",
+DlgImgAlign : "Joondus",
+DlgImgAlignLeft : "Vasak",
+DlgImgAlignAbsBottom: "Abs alla",
+DlgImgAlignAbsMiddle: "Abs keskele",
+DlgImgAlignBaseline : "Baasjoonele",
+DlgImgAlignBottom : "Alla",
+DlgImgAlignMiddle : "Keskele",
+DlgImgAlignRight : "Paremale",
+DlgImgAlignTextTop : "Tekstit üles",
+DlgImgAlignTop : "Üles",
+DlgImgPreview : "Eelvaade",
+DlgImgAlertUrl : "Palun kirjuta pildi URL",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash omadused",
+DlgFlashChkPlay : "Automaatne start ",
+DlgFlashChkLoop : "Korduv",
+DlgFlashChkMenu : "Võimalda flash menüü",
+DlgFlashScale : "Mastaap",
+DlgFlashScaleAll : "Näita kõike",
+DlgFlashScaleNoBorder : "Äärist ei ole",
+DlgFlashScaleFit : "Täpne sobivus",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Lingi info",
+DlgLnkTargetTab : "Sihtkoht",
+
+DlgLnkType : "Lingi tüüp",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ankur sellel lehel",
+DlgLnkTypeEMail : "E-post",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<muu>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Vali ankur",
+DlgLnkAnchorByName : "Ankru nime järgi",
+DlgLnkAnchorById : "Elemendi id järgi",
+DlgLnkNoAnchors : "(Selles dokumendis ei ole ankruid)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-posti aadress",
+DlgLnkEMailSubject : "Sõnumi teema",
+DlgLnkEMailBody : "Sõnumi tekst",
+DlgLnkUpload : "Lae üles",
+DlgLnkBtnUpload : "Saada serverisse",
+
+DlgLnkTarget : "Sihtkoht",
+DlgLnkTargetFrame : "<raam>",
+DlgLnkTargetPopup : "<hüpikaken>",
+DlgLnkTargetBlank : "Uus aken (_blank)",
+DlgLnkTargetParent : "Vanem aken (_parent)",
+DlgLnkTargetSelf : "Sama aken (_self)",
+DlgLnkTargetTop : "Pealmine aken (_top)",
+DlgLnkTargetFrameName : "Sihtmärk raami nimi",
+DlgLnkPopWinName : "Hüpikakna nimi",
+DlgLnkPopWinFeat : "Hüpikakna omadused",
+DlgLnkPopResize : "Suurendatav",
+DlgLnkPopLocation : "Aadressiriba",
+DlgLnkPopMenu : "Menüüriba",
+DlgLnkPopScroll : "Kerimisribad",
+DlgLnkPopStatus : "Olekuriba",
+DlgLnkPopToolbar : "Tööriistariba",
+DlgLnkPopFullScrn : "Täisekraan (IE)",
+DlgLnkPopDependent : "Sõltuv (Netscape)",
+DlgLnkPopWidth : "Laius",
+DlgLnkPopHeight : "Kõrgus",
+DlgLnkPopLeft : "Vasak asukoht",
+DlgLnkPopTop : "Ülemine asukoht",
+
+DlnLnkMsgNoUrl : "Palun kirjuta lingi URL",
+DlnLnkMsgNoEMail : "Palun kirjuta E-Posti aadress",
+DlnLnkMsgNoAnchor : "Palun vali ankur",
+DlnLnkMsgInvPopName : "Hüpikakna nimi peab algama alfabeetilise tähega ja ei tohi sisaldada tühikuid",
+
+// Color Dialog
+DlgColorTitle : "Vali värv",
+DlgColorBtnClear : "Tühjenda",
+DlgColorHighlight : "Märgi",
+DlgColorSelected : "Valitud",
+
+// Smiley Dialog
+DlgSmileyTitle : "Sisesta emotikon",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Vali erimärk",
+
+// Table Dialog
+DlgTableTitle : "Tabeli atribuudid",
+DlgTableRows : "Read",
+DlgTableColumns : "Veerud",
+DlgTableBorder : "Joone suurus",
+DlgTableAlign : "Joondus",
+DlgTableAlignNotSet : "<Määramata>",
+DlgTableAlignLeft : "Vasak",
+DlgTableAlignCenter : "Kesk",
+DlgTableAlignRight : "Parem",
+DlgTableWidth : "Laius",
+DlgTableWidthPx : "pikslit",
+DlgTableWidthPc : "protsenti",
+DlgTableHeight : "Kõrgus",
+DlgTableCellSpace : "Lahtri vahe",
+DlgTableCellPad : "Lahtri täidis",
+DlgTableCaption : "Tabeli tiitel",
+DlgTableSummary : "Kokkuvõte",
+
+// Table Cell Dialog
+DlgCellTitle : "Lahtri atribuudid",
+DlgCellWidth : "Laius",
+DlgCellWidthPx : "pikslit",
+DlgCellWidthPc : "protsenti",
+DlgCellHeight : "Kõrgus",
+DlgCellWordWrap : "Sõna ülekanne",
+DlgCellWordWrapNotSet : "<Määramata>",
+DlgCellWordWrapYes : "Jah",
+DlgCellWordWrapNo : "Ei",
+DlgCellHorAlign : "Horisontaaljoondus",
+DlgCellHorAlignNotSet : "<Määramata>",
+DlgCellHorAlignLeft : "Vasak",
+DlgCellHorAlignCenter : "Kesk",
+DlgCellHorAlignRight: "Parem",
+DlgCellVerAlign : "Vertikaaljoondus",
+DlgCellVerAlignNotSet : "<Määramata>",
+DlgCellVerAlignTop : "Üles",
+DlgCellVerAlignMiddle : "Keskele",
+DlgCellVerAlignBottom : "Alla",
+DlgCellVerAlignBaseline : "Baasjoonele",
+DlgCellRowSpan : "Reaulatus",
+DlgCellCollSpan : "Veeruulatus",
+DlgCellBackColor : "Tausta värv",
+DlgCellBorderColor : "Joone värv",
+DlgCellBtnSelect : "Vali...",
+
+// Find Dialog
+DlgFindTitle : "Otsi",
+DlgFindFindBtn : "Otsi",
+DlgFindNotFoundMsg : "Valitud teksti ei leitud.",
+
+// Replace Dialog
+DlgReplaceTitle : "Asenda",
+DlgReplaceFindLbl : "Leia mida:",
+DlgReplaceReplaceLbl : "Asenda millega:",
+DlgReplaceCaseChk : "Erista suur- ja väiketähti",
+DlgReplaceReplaceBtn : "Asenda",
+DlgReplaceReplAllBtn : "Asenda kõik",
+DlgReplaceWordChk : "Otsi terviklike sõnu",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl+X).",
+PasteErrorCopy : "Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl+C).",
+
+PasteAsText : "Kleebi tavalise tekstina",
+PasteFromWord : "Kleebi Wordist",
+
+DlgPasteMsg2 : "Palun kleebi järgnevasse kasti kasutades klaviatuuri klahvikombinatsiooni (<STRONG>Ctrl+V</STRONG>) ja vajuta seejärel <STRONG>OK</STRONG>.",
+DlgPasteSec : "Sinu veebisirvija turvaseadete tõttu, ei oma redaktor otsest ligipääsu lõikelaua andmetele. Sa pead kleepima need uuesti siia aknasse.",
+DlgPasteIgnoreFont : "Ignoreeri kirja definitsioone",
+DlgPasteRemoveStyles : "Eemalda stiilide definitsioonid",
+DlgPasteCleanBox : "Puhasta ära kast",
+
+// Color Picker
+ColorAutomatic : "Automaatne",
+ColorMoreColors : "Rohkem värve...",
+
+// Document Properties
+DocProps : "Dokumendi omadused",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankru omadused",
+DlgAnchorName : "Ankru nimi",
+DlgAnchorErrorName : "Palun sisest ankru nimi",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Puudub sõnastikust",
+DlgSpellChangeTo : "Muuda",
+DlgSpellBtnIgnore : "Ignoreeri",
+DlgSpellBtnIgnoreAll : "Ignoreeri kõiki",
+DlgSpellBtnReplace : "Asenda",
+DlgSpellBtnReplaceAll : "Asenda kõik",
+DlgSpellBtnUndo : "Võta tagasi",
+DlgSpellNoSuggestions : "- Soovitused puuduvad -",
+DlgSpellProgress : "Toimub õigekirja kontroll...",
+DlgSpellNoMispell : "Õigekirja kontroll sooritatud: õigekirjuvigu ei leitud",
+DlgSpellNoChanges : "Õigekirja kontroll sooritatud: ühtegi sõna ei muudetud",
+DlgSpellOneChange : "Õigekirja kontroll sooritatud: üks sõna muudeti",
+DlgSpellManyChanges : "Õigekirja kontroll sooritatud: %1 sõna muudetud",
+
+IeSpellDownload : "Õigekirja kontrollija ei ole installeeritud. Soovid sa selle alla laadida?",
+
+// Button Dialog
+DlgButtonText : "Tekst (väärtus)",
+DlgButtonType : "Tüüp",
+DlgButtonTypeBtn : "Nupp",
+DlgButtonTypeSbm : "Saada",
+DlgButtonTypeRst : "Lähtesta",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nimi",
+DlgCheckboxValue : "Väärtus",
+DlgCheckboxSelected : "Valitud",
+
+// Form Dialog
+DlgFormName : "Nimi",
+DlgFormAction : "Toiming",
+DlgFormMethod : "Meetod",
+
+// Select Field Dialog
+DlgSelectName : "Nimi",
+DlgSelectValue : "Väärtus",
+DlgSelectSize : "Suurus",
+DlgSelectLines : "ridu",
+DlgSelectChkMulti : "Võimalda mitu valikut",
+DlgSelectOpAvail : "Võimalikud valikud",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Väärtus",
+DlgSelectBtnAdd : "Lisa",
+DlgSelectBtnModify : "Muuda",
+DlgSelectBtnUp : "Üles",
+DlgSelectBtnDown : "Alla",
+DlgSelectBtnSetValue : "Sea valitud olekuna",
+DlgSelectBtnDelete : "Kustuta",
+
+// Textarea Dialog
+DlgTextareaName : "Nimi",
+DlgTextareaCols : "Veerge",
+DlgTextareaRows : "Ridu",
+
+// Text Field Dialog
+DlgTextName : "Nimi",
+DlgTextValue : "Väärtus",
+DlgTextCharWidth : "Laius (tähemärkides)",
+DlgTextMaxChars : "Maksimaalselt tähemärke",
+DlgTextType : "Tüüp",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Parool",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nimi",
+DlgHiddenValue : "Väärtus",
+
+// Bulleted List Dialog
+BulletedListProp : "Täpitud loetelu omadused",
+NumberedListProp : "Nummerdatud loetelu omadused",
+DlgLstStart : "Alusta",
+DlgLstType : "Tüüp",
+DlgLstTypeCircle : "Ring",
+DlgLstTypeDisc : "Ketas",
+DlgLstTypeSquare : "Ruut",
+DlgLstTypeNumbers : "Numbrid (1, 2, 3)",
+DlgLstTypeLCase : "Väiketähed (a, b, c)",
+DlgLstTypeUCase : "Suurtähed (A, B, C)",
+DlgLstTypeSRoman : "Väiksed Rooma numbrid (i, ii, iii)",
+DlgLstTypeLRoman : "Suured Rooma numbrid (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Üldine",
+DlgDocBackTab : "Taust",
+DlgDocColorsTab : "Värvid ja veerised",
+DlgDocMetaTab : "Meta andmed",
+
+DlgDocPageTitle : "Lehekülje tiitel",
+DlgDocLangDir : "Kirja suund",
+DlgDocLangDirLTR : "Vasakult paremale (LTR)",
+DlgDocLangDirRTL : "Paremalt vasakule (RTL)",
+DlgDocLangCode : "Keele kood",
+DlgDocCharSet : "Märgistiku kodeering",
+DlgDocCharSetCE : "Kesk-Euroopa",
+DlgDocCharSetCT : "Hiina traditsiooniline (Big5)",
+DlgDocCharSetCR : "Kirillisa",
+DlgDocCharSetGR : "Kreeka",
+DlgDocCharSetJP : "Jaapani",
+DlgDocCharSetKR : "Korea",
+DlgDocCharSetTR : "Türgi",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Lääne-Euroopa",
+DlgDocCharSetOther : "Ülejäänud märgistike kodeeringud",
+
+DlgDocDocType : "Dokumendi tüüppäis",
+DlgDocDocTypeOther : "Teised dokumendi tüüppäised",
+DlgDocIncXHTML : "Arva kaasa XHTML deklaratsioonid",
+DlgDocBgColor : "Taustavärv",
+DlgDocBgImage : "Taustapildi URL",
+DlgDocBgNoScroll : "Mittekeritav tagataust",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Külastatud link",
+DlgDocCActive : "Aktiivne link",
+DlgDocMargins : "Lehekülje äärised",
+DlgDocMaTop : "Ülaserv",
+DlgDocMaLeft : "Vasakserv",
+DlgDocMaRight : "Paremserv",
+DlgDocMaBottom : "Alaserv",
+DlgDocMeIndex : "Dokumendi võtmesõnad (eraldatud komadega)",
+DlgDocMeDescr : "Dokumendi kirjeldus",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Autoriõigus",
+DlgDocPreview : "Eelvaade",
+
+// Templates Dialog
+Templates : "Šabloon",
+DlgTemplatesTitle : "Sisu šabloonid",
+DlgTemplatesSelMsg : "Palun vali šabloon, et avada see redaktoris<br />(praegune sisu läheb kaotsi):",
+DlgTemplatesLoading : "Laen šabloonide nimekirja. Palun oota...",
+DlgTemplatesNoTpl : "(Ühtegi šablooni ei ole defineeritud)",
+DlgTemplatesReplace : "Asenda tegelik sisu",
+
+// About Dialog
+DlgAboutAboutTab : "Teave",
+DlgAboutBrowserInfoTab : "Veebisirvija info",
+DlgAboutLicenseTab : "Litsents",
+DlgAboutVersion : "versioon",
+DlgAboutInfo : "Täpsema info saamiseks mine"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/eu.js b/httemplate/elements/fckeditor/editor/lang/eu.js
new file mode 100644
index 000000000..266d427b8
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/eu.js
@@ -0,0 +1,505 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Basque language file.
+ * Euskara hizkuntza fitxategia.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Estutu Tresna Barra",
+ToolbarExpand : "Hedatu Tresna Barra",
+
+// Toolbar Items and Context Menu
+Save : "Gorde",
+NewPage : "Orrialde Berria",
+Preview : "Aurrebista",
+Cut : "Ebaki",
+Copy : "Kopiatu",
+Paste : "Itsatsi",
+PasteText : "Itsatsi testu bezala",
+PasteWord : "Itsatsi Word-etik",
+Print : "Inprimatu",
+SelectAll : "Hautatu dena",
+RemoveFormat : "Kendu Formatoa",
+InsertLinkLbl : "Esteka",
+InsertLink : "Txertatu/Editatu Esteka",
+RemoveLink : "Kendu Esteka",
+Anchor : "Aingura",
+InsertImageLbl : "Irudia",
+InsertImage : "Txertatu/Editatu Irudia",
+InsertFlashLbl : "Flasha",
+InsertFlash : "Txertatu/Editatu Flasha",
+InsertTableLbl : "Taula",
+InsertTable : "Txertatu/Editatu Taula",
+InsertLineLbl : "Lerroa",
+InsertLine : "Txertatu Marra Horizontala",
+InsertSpecialCharLbl: "Karaktere Berezia",
+InsertSpecialChar : "Txertatu Karaktere Berezia",
+InsertSmileyLbl : "Aurpegierak",
+InsertSmiley : "Txertatu Aurpegierak",
+About : "FCKeditor-ri buruz",
+Bold : "Lodia",
+Italic : "Etzana",
+Underline : "Azpimarratu",
+StrikeThrough : "Marratua",
+Subscript : "Azpi-indize",
+Superscript : "Goi-indize",
+LeftJustify : "Lerrokatu Ezkerrean",
+CenterJustify : "Lerrokatu Erdian",
+RightJustify : "Lerrokatu Eskuman",
+BlockJustify : "Justifikatu",
+DecreaseIndent : "Txikitu Koska",
+IncreaseIndent : "Handitu Koska",
+Undo : "Desegin",
+Redo : "Berregin",
+NumberedListLbl : "Zenbakidun Zerrenda",
+NumberedList : "Txertatu/Kendu Zenbakidun zerrenda",
+BulletedListLbl : "Buletdun Zerrenda",
+BulletedList : "Txertatu/Kendu Buletdun zerrenda",
+ShowTableBorders : "Erakutsi Taularen Ertzak",
+ShowDetails : "Erakutsi Xehetasunak",
+Style : "Estiloa",
+FontFormat : "Formatoa",
+Font : "Letra-tipoa",
+FontSize : "Tamaina",
+TextColor : "Testu Kolorea",
+BGColor : "Atzeko kolorea",
+Source : "HTML Iturburua",
+Find : "Bilatu",
+Replace : "Ordezkatu",
+SpellCheck : "Ortografia",
+UniversalKeyboard : "Teklatu Unibertsala",
+PageBreakLbl : "Orrialde-jauzia",
+PageBreak : "Txertatu Orrialde-jauzia",
+
+Form : "Formularioa",
+Checkbox : "Kontrol-laukia",
+RadioButton : "Aukera-botoia",
+TextField : "Testu Eremua",
+Textarea : "Testu-area",
+HiddenField : "Ezkutuko Eremua",
+Button : "Botoia",
+SelectionField : "Hautespen Eremua",
+ImageButton : "Irudi Botoia",
+
+FitWindow : "Maximizatu editorearen tamaina",
+
+// Context Menu
+EditLink : "Aldatu Esteka",
+CellCM : "Gelaxka",
+RowCM : "Errenkada",
+ColumnCM : "Zutabea",
+InsertRow : "Txertatu Errenkada",
+DeleteRows : "Ezabatu Errenkadak",
+InsertColumn : "Txertatu Zutabea",
+DeleteColumns : "Ezabatu Zutabeak",
+InsertCell : "Txertatu Gelaxka",
+DeleteCells : "Kendu Gelaxkak",
+MergeCells : "Batu Gelaxkak",
+SplitCell : "Zatitu Gelaxka",
+TableDelete : "Ezabatu Taula",
+CellProperties : "Gelaxkaren Ezaugarriak",
+TableProperties : "Taularen Ezaugarriak",
+ImageProperties : "Irudiaren Ezaugarriak",
+FlashProperties : "Flasharen Ezaugarriak",
+
+AnchorProp : "Ainguraren Ezaugarriak",
+ButtonProp : "Botoiaren Ezaugarriak",
+CheckboxProp : "Kontrol-laukiko Ezaugarriak",
+HiddenFieldProp : "Ezkutuko Eremuaren Ezaugarriak",
+RadioButtonProp : "Aukera-botoiaren Ezaugarriak",
+ImageButtonProp : "Irudi Botoiaren Ezaugarriak",
+TextFieldProp : "Testu Eremuaren Ezaugarriak",
+SelectionFieldProp : "Hautespen Eremuaren Ezaugarriak",
+TextareaProp : "Testu-arearen Ezaugarriak",
+FormProp : "Formularioaren Ezaugarriak",
+
+FontFormats : "Arrunta;Formateatua;Helbidea;Izenburua 1;Izenburua 2;Izenburua 3;Izenburua 4;Izenburua 5;Izenburua 6;Paragrafoa (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML Prozesatzen. Itxaron mesedez...",
+Done : "Eginda",
+PasteWordConfirm : "Itsatsi nahi duzun textua Wordetik hartua dela dirudi. Itsatsi baino lehen garbitu nahi duzu?",
+NotCompatiblePaste : "Komando hau Internet Explorer 5.5 bertsiorako edo ondorengoentzako erabilgarria dago. Garbitu gabe itsatsi nahi duzu?",
+UnknownToolbarItem : "Ataza barrako elementu ezezaguna \"%1\"",
+UnknownCommand : "Komando izen ezezaguna \"%1\"",
+NotImplemented : "Komando ez inplementatua",
+UnknownToolbarSet : "Ataza barra \"%1\" taldea ez da existitzen",
+NoActiveX : "Zure nabigatzailearen segustasun hobespenak editore honen zenbait ezaugarri mugatu ditzake. \"ActiveX kontrolak eta plug-inak\" aktibatu beharko zenituzke, bestela erroreak eta ezaugarrietan mugak egon daitezke.",
+BrowseServerBlocked : "Baliabideen arakatzailea ezin da ireki. Ziurtatu popup blokeatzaileak desgaituta dituzula.",
+DialogBlocked : "Ezin da elkarrizketa-leihoa ireki. Ziurtatu popup blokeatzaileak desgaituta dituzula.",
+
+// Dialogs
+DlgBtnOK : "Ados",
+DlgBtnCancel : "Utzi",
+DlgBtnClose : "Itxi",
+DlgBtnBrowseServer : "Zerbitzaria arakatu",
+DlgAdvancedTag : "Aurreratua",
+DlgOpOther : "<Bestelakoak>",
+DlgInfoTab : "Informazioa",
+DlgAlertUrl : "Mesedez URLa idatzi ezazu",
+
+// General Dialogs Labels
+DlgGenNotSet : "<Ezarri gabe>",
+DlgGenId : "Id",
+DlgGenLangDir : "Hizkuntzaren Norabidea",
+DlgGenLangDirLtr : "Ezkerretik Eskumara(LTR)",
+DlgGenLangDirRtl : "Eskumatik Ezkerrera (RTL)",
+DlgGenLangCode : "Hizkuntza Kodea",
+DlgGenAccessKey : "Sarbide-gakoa",
+DlgGenName : "Izena",
+DlgGenTabIndex : "Tabulazio Indizea",
+DlgGenLongDescr : "URL Deskribapen Luzea",
+DlgGenClass : "Estilo-orriko Klaseak",
+DlgGenTitle : "Izenburua",
+DlgGenContType : "Eduki Mota (Content Type)",
+DlgGenLinkCharset : "Estekatutako Karaktere Multzoa",
+DlgGenStyle : "Estiloa",
+
+// Image Dialog
+DlgImgTitle : "Irudi Ezaugarriak",
+DlgImgInfoTab : "Irudi informazioa",
+DlgImgBtnUpload : "Zerbitzarira bidalia",
+DlgImgURL : "URL",
+DlgImgUpload : "Gora Kargatu",
+DlgImgAlt : "Textu Alternatiboa",
+DlgImgWidth : "Zabalera",
+DlgImgHeight : "Altuera",
+DlgImgLockRatio : "Erlazioa Blokeatu",
+DlgBtnResetSize : "Tamaina Berrezarri",
+DlgImgBorder : "Ertza",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Lerrokatu",
+DlgImgAlignLeft : "Ezkerrera",
+DlgImgAlignAbsBottom: "Abs Behean",
+DlgImgAlignAbsMiddle: "Abs Erdian",
+DlgImgAlignBaseline : "Oinan",
+DlgImgAlignBottom : "Behean",
+DlgImgAlignMiddle : "Erdian",
+DlgImgAlignRight : "Eskuman",
+DlgImgAlignTextTop : "Testua Goian",
+DlgImgAlignTop : "Goian",
+DlgImgPreview : "Aurrebista",
+DlgImgAlertUrl : "Mesedez Irudiaren URLa idatzi",
+DlgImgLinkTab : "Esteka",
+
+// Flash Dialog
+DlgFlashTitle : "Flasharen Ezaugarriak",
+DlgFlashChkPlay : "Automatikoki Erreproduzitu",
+DlgFlashChkLoop : "Begizta",
+DlgFlashChkMenu : "Flasharen Menua Gaitu",
+DlgFlashScale : "Eskalatu",
+DlgFlashScaleAll : "Dena erakutsi",
+DlgFlashScaleNoBorder : "Ertzarik gabe",
+DlgFlashScaleFit : "Doitu",
+
+// Link Dialog
+DlgLnkWindowTitle : "Esteka",
+DlgLnkInfoTab : "Estekaren Informazioa",
+DlgLnkTargetTab : "Helburua",
+
+DlgLnkType : "Esteka Mota",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Aingura horrialde honentan",
+DlgLnkTypeEMail : "ePosta",
+DlgLnkProto : "Protokoloa",
+DlgLnkProtoOther : "<Beste batzuk>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Aingura bat hautatu",
+DlgLnkAnchorByName : "Aingura izenagatik",
+DlgLnkAnchorById : "Elementuaren ID-gatik",
+DlgLnkNoAnchors : "<Ez daude aingurak eskuragarri dokumentuan>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "ePosta Helbidea",
+DlgLnkEMailSubject : "Mezuaren Gaia",
+DlgLnkEMailBody : "Mezuaren Gorputza",
+DlgLnkUpload : "Gora kargatu",
+DlgLnkBtnUpload : "Zerbitzarira bidali",
+
+DlgLnkTarget : "Target (Helburua)",
+DlgLnkTargetFrame : "<marko>",
+DlgLnkTargetPopup : "<popup lehioa>",
+DlgLnkTargetBlank : "Lehio Berria (_blank)",
+DlgLnkTargetParent : "Lehio Gurasoa (_parent)",
+DlgLnkTargetSelf : "Lehio Berdina (_self)",
+DlgLnkTargetTop : "Goiko Lehioa (_top)",
+DlgLnkTargetFrameName : "Marko Helburuaren Izena",
+DlgLnkPopWinName : "Popup Lehioaren Izena",
+DlgLnkPopWinFeat : "Popup Lehioaren Ezaugarriak",
+DlgLnkPopResize : "Tamaina Aldakorra",
+DlgLnkPopLocation : "Kokaleku Barra",
+DlgLnkPopMenu : "Menu Barra",
+DlgLnkPopScroll : "Korritze Barrak",
+DlgLnkPopStatus : "Egoera Barra",
+DlgLnkPopToolbar : "Tresna Barra",
+DlgLnkPopFullScrn : "Pantaila Osoa (IE)",
+DlgLnkPopDependent : "Menpekoa (Netscape)",
+DlgLnkPopWidth : "Zabalera",
+DlgLnkPopHeight : "Altuera",
+DlgLnkPopLeft : "Ezkerreko Posizioa",
+DlgLnkPopTop : "Goiko Posizioa",
+
+DlnLnkMsgNoUrl : "Mesedez URL esteka idatzi",
+DlnLnkMsgNoEMail : "Mesedez ePosta helbidea idatzi",
+DlnLnkMsgNoAnchor : "Mesedez aingura bat aukeratu",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Kolore Aukeraketa",
+DlgColorBtnClear : "Garbitu",
+DlgColorHighlight : "Nabarmendu",
+DlgColorSelected : "Aukeratuta",
+
+// Smiley Dialog
+DlgSmileyTitle : "Aurpegiera Sartu",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Karaktere Berezia Aukeratu",
+
+// Table Dialog
+DlgTableTitle : "Taularen Ezaugarriak",
+DlgTableRows : "Lerroak",
+DlgTableColumns : "Zutabeak",
+DlgTableBorder : "Ertzaren Zabalera",
+DlgTableAlign : "Lerrokatu",
+DlgTableAlignNotSet : "<Ezarri gabe>",
+DlgTableAlignLeft : "Ezkerrean",
+DlgTableAlignCenter : "Erdian",
+DlgTableAlignRight : "Eskuman",
+DlgTableWidth : "Zabalera",
+DlgTableWidthPx : "pixel",
+DlgTableWidthPc : "ehuneko",
+DlgTableHeight : "Altuera",
+DlgTableCellSpace : "Gelaxka arteko tartea",
+DlgTableCellPad : "Gelaxken betegarria",
+DlgTableCaption : "Epigrafea",
+DlgTableSummary : "Laburpena",
+
+// Table Cell Dialog
+DlgCellTitle : "Gelaxken Ezaugarriak",
+DlgCellWidth : "Zabalera",
+DlgCellWidthPx : "pixel",
+DlgCellWidthPc : "ehuneko",
+DlgCellHeight : "Altuera",
+DlgCellWordWrap : "Itzulbira",
+DlgCellWordWrapNotSet : "<Ezarri gabe>",
+DlgCellWordWrapYes : "Bai",
+DlgCellWordWrapNo : "Ez",
+DlgCellHorAlign : "Horizontal Alignment",
+DlgCellHorAlignNotSet : "<Ezarri gabe>",
+DlgCellHorAlignLeft : "Ezkerrean",
+DlgCellHorAlignCenter : "Erdian",
+DlgCellHorAlignRight: "Eskuman",
+DlgCellVerAlign : "Lerrokatu Bertikalki",
+DlgCellVerAlignNotSet : "<Ezarri gabe>",
+DlgCellVerAlignTop : "Goian",
+DlgCellVerAlignMiddle : "Erdian",
+DlgCellVerAlignBottom : "Behean",
+DlgCellVerAlignBaseline : "Oinan",
+DlgCellRowSpan : "Lerroak Hedatu",
+DlgCellCollSpan : "Zutabeak Hedatu",
+DlgCellBackColor : "Atzeko Kolorea",
+DlgCellBorderColor : "Ertzako Kolorea",
+DlgCellBtnSelect : "Aukertau...",
+
+// Find Dialog
+DlgFindTitle : "Bilaketa",
+DlgFindFindBtn : "Bilatu",
+DlgFindNotFoundMsg : "Idatzitako testua ez da topatu.",
+
+// Replace Dialog
+DlgReplaceTitle : "Ordeztu",
+DlgReplaceFindLbl : "Zer bilatu:",
+DlgReplaceReplaceLbl : "Zerekin ordeztu:",
+DlgReplaceCaseChk : "Maiuskula/minuskula",
+DlgReplaceReplaceBtn : "Ordeztu",
+DlgReplaceReplAllBtn : "Ordeztu Guztiak",
+DlgReplaceWordChk : "Esaldi osoa bilatu",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Zure web nabigatzailearen segurtasun ezarpenak testuak automatikoki moztea ez dute baimentzen. Mesedez teklatua erabili ezazu (Ctrl+X).",
+PasteErrorCopy : "Zure web nabigatzailearen segurtasun ezarpenak testuak automatikoki kopiatzea ez dute baimentzen. Mesedez teklatua erabili ezazu (Ctrl+C).",
+
+PasteAsText : "Testu Arrunta bezala Itsatsi",
+PasteFromWord : "Word-etik itsatsi",
+
+DlgPasteMsg2 : "Mesedez teklatua erabilita (<STRONG>Ctrl+V</STRONG>) ondorego eremuan testua itsatsi eta <STRONG>OK</STRONG> sakatu.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Letra Motaren definizioa ezikusi",
+DlgPasteRemoveStyles : "Estilo definizioak kendu",
+DlgPasteCleanBox : "Testu-eremua Garbitu",
+
+// Color Picker
+ColorAutomatic : "Automatikoa",
+ColorMoreColors : "Kolore gehiago...",
+
+// Document Properties
+DocProps : "Dokumentuaren Ezarpenak",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ainguraren Ezaugarriak",
+DlgAnchorName : "Ainguraren Izena",
+DlgAnchorErrorName : "Idatzi ainguraren izena",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ez dago hiztegian",
+DlgSpellChangeTo : "Honekin ordezkatu",
+DlgSpellBtnIgnore : "Ezikusi",
+DlgSpellBtnIgnoreAll : "Denak Ezikusi",
+DlgSpellBtnReplace : "Ordezkatu",
+DlgSpellBtnReplaceAll : "Denak Ordezkatu",
+DlgSpellBtnUndo : "Desegin",
+DlgSpellNoSuggestions : "- Iradokizunik ez -",
+DlgSpellProgress : "Zuzenketa ortografikoa martxan...",
+DlgSpellNoMispell : "Zuzenketa ortografikoa bukatuta: Akatsik ez",
+DlgSpellNoChanges : "Zuzenketa ortografikoa bukatuta: Ez da ezer aldatu",
+DlgSpellOneChange : "Zuzenketa ortografikoa bukatuta: Hitz bat aldatu da",
+DlgSpellManyChanges : "Zuzenketa ortografikoa bukatuta: %1 hitz aldatu dira",
+
+IeSpellDownload : "Zuzentzaile ortografikoa ez dago instalatuta. Deskargatu nahi duzu?",
+
+// Button Dialog
+DlgButtonText : "Testua (Balorea)",
+DlgButtonType : "Mota",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Izena",
+DlgCheckboxValue : "Balorea",
+DlgCheckboxSelected : "Hautatuta",
+
+// Form Dialog
+DlgFormName : "Izena",
+DlgFormAction : "Ekintza",
+DlgFormMethod : "Method",
+
+// Select Field Dialog
+DlgSelectName : "Izena",
+DlgSelectValue : "Balorea",
+DlgSelectSize : "Tamaina",
+DlgSelectLines : "lerro kopurura",
+DlgSelectChkMulti : "Hautaketa anitzak baimendu",
+DlgSelectOpAvail : "Aukera Eskuragarriak",
+DlgSelectOpText : "Testua",
+DlgSelectOpValue : "Balorea",
+DlgSelectBtnAdd : "Gehitu",
+DlgSelectBtnModify : "Aldatu",
+DlgSelectBtnUp : "Gora",
+DlgSelectBtnDown : "Behera",
+DlgSelectBtnSetValue : "Aukeratutako balorea ezarri",
+DlgSelectBtnDelete : "Ezabatu",
+
+// Textarea Dialog
+DlgTextareaName : "Izena",
+DlgTextareaCols : "Zutabeak",
+DlgTextareaRows : "Lerroak",
+
+// Text Field Dialog
+DlgTextName : "Izena",
+DlgTextValue : "Balorea",
+DlgTextCharWidth : "Zabalera",
+DlgTextMaxChars : "Zenbat karaktere gehienez",
+DlgTextType : "Mota",
+DlgTextTypeText : "Testua",
+DlgTextTypePass : "Pasahitza",
+
+// Hidden Field Dialog
+DlgHiddenName : "Izena",
+DlgHiddenValue : "Balorea",
+
+// Bulleted List Dialog
+BulletedListProp : "Buletdun Zerrendaren Ezarpenak",
+NumberedListProp : "Zenbakidun Zerrendaren Ezarpenak",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Mota",
+DlgLstTypeCircle : "Zirkulua",
+DlgLstTypeDisc : "Diskoa",
+DlgLstTypeSquare : "Karratua",
+DlgLstTypeNumbers : "Zenbakiak (1, 2, 3)",
+DlgLstTypeLCase : "Letra xeheak (a, b, c)",
+DlgLstTypeUCase : "Letra larriak (A, B, C)",
+DlgLstTypeSRoman : "Erromatar zenbaki zeheak (i, ii, iii)",
+DlgLstTypeLRoman : "Erromatar zenbaki larriak (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Orokorra",
+DlgDocBackTab : "Atzekaldea",
+DlgDocColorsTab : "Koloreak eta Marjinak",
+DlgDocMetaTab : "Meta Informazioa",
+
+DlgDocPageTitle : "Orriaren Izenburua",
+DlgDocLangDir : "Hizkuntzaren Norabidea",
+DlgDocLangDirLTR : "Ezkerretik eskumara (LTR)",
+DlgDocLangDirRTL : "Eskumatik ezkerrera (RTL)",
+DlgDocLangCode : "Hizkuntzaren Kodea",
+DlgDocCharSet : "Karaktere Multzoaren Kodeketa",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Beste Karaktere Multzoaren Kodeketa",
+
+DlgDocDocType : "Document Type Goiburua",
+DlgDocDocTypeOther : "Beste Document Type Goiburua",
+DlgDocIncXHTML : "XHTML Ezarpenak",
+DlgDocBgColor : "Atzeko Kolorea",
+DlgDocBgImage : "Atzeko Irudiaren URL-a",
+DlgDocBgNoScroll : "Korritze gabeko Atzekaldea",
+DlgDocCText : "Testua",
+DlgDocCLink : "Estekak",
+DlgDocCVisited : "Bisitatutako Estekak",
+DlgDocCActive : "Esteka Aktiboa",
+DlgDocMargins : "Orrialdearen marjinak",
+DlgDocMaTop : "Goian",
+DlgDocMaLeft : "Ezkerrean",
+DlgDocMaRight : "Eskuman",
+DlgDocMaBottom : "Behean",
+DlgDocMeIndex : "Dokumentuaren Gako-hitzak (komarekin bananduta)",
+DlgDocMeDescr : "Dokumentuaren Deskribapena",
+DlgDocMeAuthor : "Egilea",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Aurrebista",
+
+// Templates Dialog
+Templates : "Txantiloiak",
+DlgTemplatesTitle : "Eduki Txantiloiak",
+DlgTemplatesSelMsg : "Mesedez txantiloia aukeratu editorean kargatzeko<br>(orain dauden edukiak galduko dira):",
+DlgTemplatesLoading : "Txantiloiak kargatzen. Itxaron mesedez...",
+DlgTemplatesNoTpl : "(Ez dago definitutako txantiloirik)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Honi buruz",
+DlgAboutBrowserInfoTab : "Nabigatzailearen Informazioa",
+DlgAboutLicenseTab : "Lizentzia",
+DlgAboutVersion : "bertsioa",
+DlgAboutInfo : "Informazio gehiago eskuratzeko hona joan"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/fa.js b/httemplate/elements/fckeditor/editor/lang/fa.js
new file mode 100644
index 000000000..e1bc9735e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/fa.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Persian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "rtl",
+
+ToolbarCollapse : "برچیدن نوارابزار",
+ToolbarExpand : "گستردن نوارابزار",
+
+// Toolbar Items and Context Menu
+Save : "ذخیره",
+NewPage : "برگهٴ تازه",
+Preview : "پیش‌نمایش",
+Cut : "برش",
+Copy : "کپی",
+Paste : "چسباندن",
+PasteText : "چسباندن به عنوان متن ِساده",
+PasteWord : "چسباندن از Word",
+Print : "چاپ",
+SelectAll : "گزینش همه",
+RemoveFormat : "برداشتن فرمت",
+InsertLinkLbl : "پیوند",
+InsertLink : "گنجاندن/ویرایش ِپیوند",
+RemoveLink : "برداشتن پیوند",
+Anchor : "گنجاندن/ویرایش ِلنگر",
+InsertImageLbl : "تصویر",
+InsertImage : "گنجاندن/ویرایش ِتصویر",
+InsertFlashLbl : "Flash",
+InsertFlash : "گنجاندن/ویرایش ِFlash",
+InsertTableLbl : "جدول",
+InsertTable : "گنجاندن/ویرایش ِجدول",
+InsertLineLbl : "خط",
+InsertLine : "گنجاندن خط ِافقی",
+InsertSpecialCharLbl: "نویسهٴ ویژه",
+InsertSpecialChar : "گنجاندن نویسهٴ ویژه",
+InsertSmileyLbl : "خندانک",
+InsertSmiley : "گنجاندن خندانک",
+About : "دربارهٴ FCKeditor",
+Bold : "درشت",
+Italic : "خمیده",
+Underline : "خط‌زیردار",
+StrikeThrough : "میان‌خط",
+Subscript : "زیرنویس",
+Superscript : "بالانویس",
+LeftJustify : "چپ‌چین",
+CenterJustify : "میان‌چین",
+RightJustify : "راست‌چین",
+BlockJustify : "بلوک‌چین",
+DecreaseIndent : "کاهش تورفتگی",
+IncreaseIndent : "افزایش تورفتگی",
+Undo : "واچیدن",
+Redo : "بازچیدن",
+NumberedListLbl : "فهرست شماره‌دار",
+NumberedList : "گنجاندن/برداشتن فهرست شماره‌دار",
+BulletedListLbl : "فهرست نقطه‌ای",
+BulletedList : "گنجاندن/برداشتن فهرست نقطه‌ای",
+ShowTableBorders : "نمایش لبهٴ جدول",
+ShowDetails : "نمایش جزئیات",
+Style : "سبک",
+FontFormat : "فرمت",
+Font : "قلم",
+FontSize : "اندازه",
+TextColor : "رنگ متن",
+BGColor : "رنگ پس‌زمینه",
+Source : "منبع",
+Find : "جستجو",
+Replace : "جایگزینی",
+SpellCheck : "بررسی املا",
+UniversalKeyboard : "صفحه‌کلید جهانی",
+PageBreakLbl : "شکستگی ِپایان ِبرگه",
+PageBreak : "گنجاندن شکستگی ِپایان ِبرگه",
+
+Form : "فرم",
+Checkbox : "خانهٴ گزینه‌ای",
+RadioButton : "دکمهٴ رادیویی",
+TextField : "فیلد متنی",
+Textarea : "ناحیهٴ متنی",
+HiddenField : "فیلد پنهان",
+Button : "دکمه",
+SelectionField : "فیلد چندگزینه‌ای",
+ImageButton : "دکمهٴ تصویری",
+
+FitWindow : "بیشینه‌سازی ِاندازهٴ ویرایشگر",
+
+// Context Menu
+EditLink : "ویرایش پیوند",
+CellCM : "سلول",
+RowCM : "سطر",
+ColumnCM : "ستون",
+InsertRow : "گنجاندن سطر",
+DeleteRows : "حذف سطرها",
+InsertColumn : "گنجاندن ستون",
+DeleteColumns : "حذف ستونها",
+InsertCell : "گنجاندن سلول",
+DeleteCells : "حذف سلولها",
+MergeCells : "ادغام سلولها",
+SplitCell : "جداسازی سلول",
+TableDelete : "پاک‌کردن جدول",
+CellProperties : "ویژگیهای سلول",
+TableProperties : "ویژگیهای جدول",
+ImageProperties : "ویژگیهای تصویر",
+FlashProperties : "ویژگیهای Flash",
+
+AnchorProp : "ویژگیهای لنگر",
+ButtonProp : "ویژگیهای دکمه",
+CheckboxProp : "ویژگیهای خانهٴ گزینه‌ای",
+HiddenFieldProp : "ویژگیهای فیلد پنهان",
+RadioButtonProp : "ویژگیهای دکمهٴ رادیویی",
+ImageButtonProp : "ویژگیهای دکمهٴ تصویری",
+TextFieldProp : "ویژگیهای فیلد متنی",
+SelectionFieldProp : "ویژگیهای فیلد چندگزینه‌ای",
+TextareaProp : "ویژگیهای ناحیهٴ متنی",
+FormProp : "ویژگیهای فرم",
+
+FontFormats : "نرمال;فرمت‌شده;آدرس;سرنویس 1;سرنویس 2;سرنویس 3;سرنویس 4;سرنویس 5;سرنویس 6;بند;(DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "پردازش XHTML. لطفا صبر کنید...",
+Done : "انجام شد",
+PasteWordConfirm : "متنی که می‌خواهید بچسبانید به نظر می‌رسد از Word کپی شده است. آیا می‌خواهید قبل از چسباندن آن را پاک‌سازی کنید؟",
+NotCompatiblePaste : "این فرمان برای مرورگر Internet Explorer از نگارش 5.5 یا بالاتر در دسترس است. آیا می‌خواهید بدون پاک‌سازی، متن را بچسبانید؟",
+UnknownToolbarItem : "فقرهٴ نوارابزار ناشناخته \"%1\"",
+UnknownCommand : "نام دستور ناشناخته \"%1\"",
+NotImplemented : "دستور پیاده‌سازی‌نشده",
+UnknownToolbarSet : "مجموعهٴ نوارابزار \"%1\" وجود ندارد",
+NoActiveX : "تنظیمات امنیتی مرورگر شما ممکن است در بعضی از ویژگیهای مرورگر محدودیت ایجاد کند. شما باید گزینهٴ \"Run ActiveX controls and plug-ins\" را فعال کنید. ممکن است شما با خطاهایی روبرو باشید و متوجه کمبود ویژگیهایی شوید.",
+BrowseServerBlocked : "توانایی بازگشایی مرورگر منابع فراهم نیست. اطمینان حاصل کنید که تمامی برنامه‌های پیشگیری از نمایش popup را از کار بازداشته‌اید.",
+DialogBlocked : "توانایی بازگشایی پنجرهٴ کوچک ِگفتگو فراهم نیست. اطمینان حاصل کنید که تمامی برنامه‌های پیشگیری از نمایش popup را از کار بازداشته‌اید.",
+
+// Dialogs
+DlgBtnOK : "پذیرش",
+DlgBtnCancel : "انصراف",
+DlgBtnClose : "بستن",
+DlgBtnBrowseServer : "فهرست‌نمایی سرور",
+DlgAdvancedTag : "پیشرفته",
+DlgOpOther : "<غیره>",
+DlgInfoTab : "اطلاعات",
+DlgAlertUrl : "لطفاً URL را بنویسید",
+
+// General Dialogs Labels
+DlgGenNotSet : "<تعین‌نشده>",
+DlgGenId : "شناسه",
+DlgGenLangDir : "جهت‌نمای زبان",
+DlgGenLangDirLtr : "چپ به راست (LTR)",
+DlgGenLangDirRtl : "راست به چپ (RTL)",
+DlgGenLangCode : "کد زبان",
+DlgGenAccessKey : "کلید دستیابی",
+DlgGenName : "نام",
+DlgGenTabIndex : "نمایهٴ دسترسی با Tab",
+DlgGenLongDescr : "URL توصیف طولانی",
+DlgGenClass : "کلاسهای شیوه‌نامه(Stylesheet)",
+DlgGenTitle : "عنوان کمکی",
+DlgGenContType : "نوع محتوای کمکی",
+DlgGenLinkCharset : "نویسه‌گان منبع ِپیوندشده",
+DlgGenStyle : "شیوه(style)",
+
+// Image Dialog
+DlgImgTitle : "ویژگیهای تصویر",
+DlgImgInfoTab : "اطلاعات تصویر",
+DlgImgBtnUpload : "به سرور بفرست",
+DlgImgURL : "URL",
+DlgImgUpload : "انتقال به سرور",
+DlgImgAlt : "متن جایگزین",
+DlgImgWidth : "پهنا",
+DlgImgHeight : "درازا",
+DlgImgLockRatio : "قفل‌کردن ِنسبت",
+DlgBtnResetSize : "بازنشانی اندازه",
+DlgImgBorder : "لبه",
+DlgImgHSpace : "فاصلهٴ افقی",
+DlgImgVSpace : "فاصلهٴ عمودی",
+DlgImgAlign : "چینش",
+DlgImgAlignLeft : "چپ",
+DlgImgAlignAbsBottom: "پائین مطلق",
+DlgImgAlignAbsMiddle: "وسط مطلق",
+DlgImgAlignBaseline : "خط‌پایه",
+DlgImgAlignBottom : "پائین",
+DlgImgAlignMiddle : "وسط",
+DlgImgAlignRight : "راست",
+DlgImgAlignTextTop : "متن بالا",
+DlgImgAlignTop : "بالا",
+DlgImgPreview : "پیش‌نمایش",
+DlgImgAlertUrl : "لطفا URL تصویر را بنویسید",
+DlgImgLinkTab : "پیوند",
+
+// Flash Dialog
+DlgFlashTitle : "ویژگیهای Flash",
+DlgFlashChkPlay : "آغاز ِخودکار",
+DlgFlashChkLoop : "اجرای پیاپی",
+DlgFlashChkMenu : "دردسترس‌بودن منوی Flash",
+DlgFlashScale : "مقیاس",
+DlgFlashScaleAll : "نمایش همه",
+DlgFlashScaleNoBorder : "بدون کران",
+DlgFlashScaleFit : "جایگیری کامل",
+
+// Link Dialog
+DlgLnkWindowTitle : "پیوند",
+DlgLnkInfoTab : "اطلاعات پیوند",
+DlgLnkTargetTab : "مقصد",
+
+DlgLnkType : "نوع پیوند",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "لنگر در همین صفحه",
+DlgLnkTypeEMail : "پست الکترونیکی",
+DlgLnkProto : "پروتکل",
+DlgLnkProtoOther : "<دیگر>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "یک لنگر برگزینید",
+DlgLnkAnchorByName : "با نام لنگر",
+DlgLnkAnchorById : "با شناسهٴ المان",
+DlgLnkNoAnchors : "(در این سند لنگری دردسترس نیست)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "نشانی پست الکترونیکی",
+DlgLnkEMailSubject : "موضوع پیام",
+DlgLnkEMailBody : "متن پیام",
+DlgLnkUpload : "انتقال به سرور",
+DlgLnkBtnUpload : "به سرور بفرست",
+
+DlgLnkTarget : "مقصد",
+DlgLnkTargetFrame : "<فریم>",
+DlgLnkTargetPopup : "<پنجرهٴ پاپاپ>",
+DlgLnkTargetBlank : "پنجرهٴ دیگر (_blank)",
+DlgLnkTargetParent : "پنجرهٴ والد (_parent)",
+DlgLnkTargetSelf : "همان پنجره (_self)",
+DlgLnkTargetTop : "بالاترین پنجره (_top)",
+DlgLnkTargetFrameName : "نام فریم مقصد",
+DlgLnkPopWinName : "نام پنجرهٴ پاپاپ",
+DlgLnkPopWinFeat : "ویژگیهای پنجرهٴ پاپاپ",
+DlgLnkPopResize : "قابل تغییر اندازه",
+DlgLnkPopLocation : "نوار موقعیت",
+DlgLnkPopMenu : "نوار منو",
+DlgLnkPopScroll : "میله‌های پیمایش",
+DlgLnkPopStatus : "نوار وضعیت",
+DlgLnkPopToolbar : "نوارابزار",
+DlgLnkPopFullScrn : "تمام‌صفحه (IE)",
+DlgLnkPopDependent : "وابسته (Netscape)",
+DlgLnkPopWidth : "پهنا",
+DlgLnkPopHeight : "درازا",
+DlgLnkPopLeft : "موقعیت ِچپ",
+DlgLnkPopTop : "موقعیت ِبالا",
+
+DlnLnkMsgNoUrl : "لطفا URL پیوند را بنویسید",
+DlnLnkMsgNoEMail : "لطفا نشانی پست الکترونیکی را بنویسید",
+DlnLnkMsgNoAnchor : "لطفا لنگری را برگزینید",
+DlnLnkMsgInvPopName : "نام پنجرهٴ پاپاپ باید با یک نویسهٴ الفبایی آغاز گردد و نباید فاصله‌های خالی در آن باشند",
+
+// Color Dialog
+DlgColorTitle : "گزینش رنگ",
+DlgColorBtnClear : "پاک‌کردن",
+DlgColorHighlight : "نمونه",
+DlgColorSelected : "برگزیده",
+
+// Smiley Dialog
+DlgSmileyTitle : "گنجاندن خندانک",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "گزینش نویسهٴ‌ویژه",
+
+// Table Dialog
+DlgTableTitle : "ویژگیهای جدول",
+DlgTableRows : "سطرها",
+DlgTableColumns : "ستونها",
+DlgTableBorder : "اندازهٴ لبه",
+DlgTableAlign : "چینش",
+DlgTableAlignNotSet : "<تعین‌نشده>",
+DlgTableAlignLeft : "چپ",
+DlgTableAlignCenter : "وسط",
+DlgTableAlignRight : "راست",
+DlgTableWidth : "پهنا",
+DlgTableWidthPx : "پیکسل",
+DlgTableWidthPc : "درصد",
+DlgTableHeight : "درازا",
+DlgTableCellSpace : "فاصلهٴ میان سلولها",
+DlgTableCellPad : "فاصلهٴ پرشده در سلول",
+DlgTableCaption : "عنوان",
+DlgTableSummary : "خلاصه",
+
+// Table Cell Dialog
+DlgCellTitle : "ویژگیهای سلول",
+DlgCellWidth : "پهنا",
+DlgCellWidthPx : "پیکسل",
+DlgCellWidthPc : "درصد",
+DlgCellHeight : "درازا",
+DlgCellWordWrap : "شکستن واژه‌ها",
+DlgCellWordWrapNotSet : "<تعین‌نشده>",
+DlgCellWordWrapYes : "بله",
+DlgCellWordWrapNo : "خیر",
+DlgCellHorAlign : "چینش ِافقی",
+DlgCellHorAlignNotSet : "<تعین‌نشده>",
+DlgCellHorAlignLeft : "چپ",
+DlgCellHorAlignCenter : "وسط",
+DlgCellHorAlignRight: "راست",
+DlgCellVerAlign : "چینش ِعمودی",
+DlgCellVerAlignNotSet : "<تعین‌نشده>",
+DlgCellVerAlignTop : "بالا",
+DlgCellVerAlignMiddle : "میان",
+DlgCellVerAlignBottom : "پائین",
+DlgCellVerAlignBaseline : "خط‌پایه",
+DlgCellRowSpan : "گستردگی سطرها",
+DlgCellCollSpan : "گستردگی ستونها",
+DlgCellBackColor : "رنگ پس‌زمینه",
+DlgCellBorderColor : "رنگ لبه",
+DlgCellBtnSelect : "برگزینید...",
+
+// Find Dialog
+DlgFindTitle : "یافتن",
+DlgFindFindBtn : "یافتن",
+DlgFindNotFoundMsg : "متن موردنظر یافت نشد.",
+
+// Replace Dialog
+DlgReplaceTitle : "جایگزینی",
+DlgReplaceFindLbl : "چه‌چیز را می‌یابید:",
+DlgReplaceReplaceLbl : "جایگزینی با:",
+DlgReplaceCaseChk : "همسانی در بزرگی و کوچکی نویسه‌ها",
+DlgReplaceReplaceBtn : "جایگزینی",
+DlgReplaceReplAllBtn : "جایگزینی همهٴ یافته‌ها",
+DlgReplaceWordChk : "همسانی با واژهٴ کامل",
+
+// Paste Operations / Dialog
+PasteErrorCut : "تنظیمات امنیتی مرورگر شما اجازه نمی‌دهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمه‌های صفحه‌کلید این کار را انجام دهید (Ctrl+X).",
+PasteErrorCopy : "تنظیمات امنیتی مرورگر شما اجازه نمی‌دهد که ویرایشگر به طور خودکار عملکردهای کپی‌کردن را انجام دهد. لطفا با دکمه‌های صفحه‌کلید این کار را انجام دهید (Ctrl+C).",
+
+PasteAsText : "چسباندن به عنوان متن ِساده",
+PasteFromWord : "چسباندن از Word",
+
+DlgPasteMsg2 : "لطفا متن را با کلیدهای (<STRONG>Ctrl+V</STRONG>) در این جعبهٴ متنی بچسبانید و <STRONG>پذیرش</STRONG> را بزنید.",
+DlgPasteSec : "به خاطر تنظیمات امنیتی مرورگر شما، ویرایشگر نمی‌تواند دسترسی مستقیم به داده‌های clipboard داشته باشد. شما باید دوباره آنرا در این پنجره بچسبانید.",
+DlgPasteIgnoreFont : "چشم‌پوشی از تعاریف نوع قلم",
+DlgPasteRemoveStyles : "چشم‌پوشی از تعاریف سبک (style)",
+DlgPasteCleanBox : "پاک‌کردن ناحیه",
+
+// Color Picker
+ColorAutomatic : "خودکار",
+ColorMoreColors : "رنگهای بیشتر...",
+
+// Document Properties
+DocProps : "ویژگیهای سند",
+
+// Anchor Dialog
+DlgAnchorTitle : "ویژگیهای لنگر",
+DlgAnchorName : "نام لنگر",
+DlgAnchorErrorName : "لطفا نام لنگر را بنویسید",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "در واژه‌نامه یافت نشد",
+DlgSpellChangeTo : "تغییر به",
+DlgSpellBtnIgnore : "چشم‌پوشی",
+DlgSpellBtnIgnoreAll : "چشم‌پوشی همه",
+DlgSpellBtnReplace : "جایگزینی",
+DlgSpellBtnReplaceAll : "جایگزینی همه",
+DlgSpellBtnUndo : "واچینش",
+DlgSpellNoSuggestions : "- پیشنهادی نیست -",
+DlgSpellProgress : "بررسی املا در حال انجام...",
+DlgSpellNoMispell : "بررسی املا انجام شد. هیچ غلط‌املائی یافت نشد",
+DlgSpellNoChanges : "بررسی املا انجام شد. هیچ واژه‌ای تغییر نیافت",
+DlgSpellOneChange : "بررسی املا انجام شد. یک واژه تغییر یافت",
+DlgSpellManyChanges : "بررسی املا انجام شد. %1 واژه تغییر یافت",
+
+IeSpellDownload : "بررسی‌کنندهٴ املا نصب نشده است. آیا می‌خواهید آن را هم‌اکنون دریافت کنید؟",
+
+// Button Dialog
+DlgButtonText : "متن (مقدار)",
+DlgButtonType : "نوع",
+DlgButtonTypeBtn : "دکمه",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "بازنشانی (Reset)",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "نام",
+DlgCheckboxValue : "مقدار",
+DlgCheckboxSelected : "برگزیده",
+
+// Form Dialog
+DlgFormName : "نام",
+DlgFormAction : "رویداد",
+DlgFormMethod : "متد",
+
+// Select Field Dialog
+DlgSelectName : "نام",
+DlgSelectValue : "مقدار",
+DlgSelectSize : "اندازه",
+DlgSelectLines : "خطوط",
+DlgSelectChkMulti : "گزینش چندگانه فراهم باشد",
+DlgSelectOpAvail : "گزینه‌های دردسترس",
+DlgSelectOpText : "متن",
+DlgSelectOpValue : "مقدار",
+DlgSelectBtnAdd : "افزودن",
+DlgSelectBtnModify : "ویرایش",
+DlgSelectBtnUp : "بالا",
+DlgSelectBtnDown : "پائین",
+DlgSelectBtnSetValue : "تنظیم به عنوان مقدار ِبرگزیده",
+DlgSelectBtnDelete : "پاک‌کردن",
+
+// Textarea Dialog
+DlgTextareaName : "نام",
+DlgTextareaCols : "ستونها",
+DlgTextareaRows : "سطرها",
+
+// Text Field Dialog
+DlgTextName : "نام",
+DlgTextValue : "مقدار",
+DlgTextCharWidth : "پهنای نویسه",
+DlgTextMaxChars : "بیشینهٴ نویسه‌ها",
+DlgTextType : "نوع",
+DlgTextTypeText : "متن",
+DlgTextTypePass : "گذرواژه",
+
+// Hidden Field Dialog
+DlgHiddenName : "نام",
+DlgHiddenValue : "مقدار",
+
+// Bulleted List Dialog
+BulletedListProp : "ویژگیهای فهرست نقطه‌ای",
+NumberedListProp : "ویژگیهای فهرست شماره‌دار",
+DlgLstStart : "آغاز",
+DlgLstType : "نوع",
+DlgLstTypeCircle : "دایره",
+DlgLstTypeDisc : "قرص",
+DlgLstTypeSquare : "چهارگوش",
+DlgLstTypeNumbers : "شماره‌ها (1، 2، 3)",
+DlgLstTypeLCase : "نویسه‌های کوچک (a، b، c)",
+DlgLstTypeUCase : "نویسه‌های بزرگ (A، B، C)",
+DlgLstTypeSRoman : "شمارگان رومی کوچک (i، ii، iii)",
+DlgLstTypeLRoman : "شمارگان رومی بزرگ (I، II، III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "عمومی",
+DlgDocBackTab : "پس‌زمینه",
+DlgDocColorsTab : "رنگها و حاشیه‌ها",
+DlgDocMetaTab : "فراداده",
+
+DlgDocPageTitle : "عنوان صفحه",
+DlgDocLangDir : "جهت زبان",
+DlgDocLangDirLTR : "چپ به راست (LTR(",
+DlgDocLangDirRTL : "راست به چپ (RTL(",
+DlgDocLangCode : "کد زبان",
+DlgDocCharSet : "رمزگذاری نویسه‌گان",
+DlgDocCharSetCE : "اروپای مرکزی",
+DlgDocCharSetCT : "چینی رسمی (Big5)",
+DlgDocCharSetCR : "سیریلیک",
+DlgDocCharSetGR : "یونانی",
+DlgDocCharSetJP : "ژاپنی",
+DlgDocCharSetKR : "کره‌ای",
+DlgDocCharSetTR : "ترکی",
+DlgDocCharSetUN : "یونیکُد (UTF-8)",
+DlgDocCharSetWE : "اروپای غربی",
+DlgDocCharSetOther : "رمزگذاری نویسه‌گان دیگر",
+
+DlgDocDocType : "عنوان نوع سند",
+DlgDocDocTypeOther : "عنوان نوع سند دیگر",
+DlgDocIncXHTML : "شامل تعاریف XHTML",
+DlgDocBgColor : "رنگ پس‌زمینه",
+DlgDocBgImage : "URL تصویر پس‌زمینه",
+DlgDocBgNoScroll : "پس‌زمینهٴ پیمایش‌ناپذیر",
+DlgDocCText : "متن",
+DlgDocCLink : "پیوند",
+DlgDocCVisited : "پیوند مشاهده‌شده",
+DlgDocCActive : "پیوند فعال",
+DlgDocMargins : "حاشیه‌های صفحه",
+DlgDocMaTop : "بالا",
+DlgDocMaLeft : "چپ",
+DlgDocMaRight : "راست",
+DlgDocMaBottom : "پایین",
+DlgDocMeIndex : "کلیدواژگان نمایه‌گذاری سند (با کاما جدا شوند)",
+DlgDocMeDescr : "توصیف سند",
+DlgDocMeAuthor : "نویسنده",
+DlgDocMeCopy : "کپی‌رایت",
+DlgDocPreview : "پیش‌نمایش",
+
+// Templates Dialog
+Templates : "الگوها",
+DlgTemplatesTitle : "الگوهای محتویات",
+DlgTemplatesSelMsg : "لطفا الگوی موردنظر را برای بازکردن در ویرایشگر برگزینید<br>(محتویات کنونی از دست خواهند رفت):",
+DlgTemplatesLoading : "بارگذاری فهرست الگوها. لطفا صبر کنید...",
+DlgTemplatesNoTpl : "(الگوئی تعریف نشده است)",
+DlgTemplatesReplace : "محتویات کنونی جایگزین شوند",
+
+// About Dialog
+DlgAboutAboutTab : "درباره",
+DlgAboutBrowserInfoTab : "اطلاعات مرورگر",
+DlgAboutLicenseTab : "گواهینامه",
+DlgAboutVersion : "نگارش",
+DlgAboutInfo : "برای آگاهی بیشتر به این نشانی بروید"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/fi.js b/httemplate/elements/fckeditor/editor/lang/fi.js
new file mode 100644
index 000000000..7e7986a69
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/fi.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Finnish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Piilota työkalurivi",
+ToolbarExpand : "Näytä työkalurivi",
+
+// Toolbar Items and Context Menu
+Save : "Tallenna",
+NewPage : "Tyhjennä",
+Preview : "Esikatsele",
+Cut : "Leikkaa",
+Copy : "Kopioi",
+Paste : "Liitä",
+PasteText : "Liitä tekstinä",
+PasteWord : "Liitä Wordista",
+Print : "Tulosta",
+SelectAll : "Valitse kaikki",
+RemoveFormat : "Poista muotoilu",
+InsertLinkLbl : "Linkki",
+InsertLink : "Lisää linkki/muokkaa linkkiä",
+RemoveLink : "Poista linkki",
+Anchor : "Lisää ankkuri/muokkaa ankkuria",
+InsertImageLbl : "Kuva",
+InsertImage : "Lisää kuva/muokkaa kuvaa",
+InsertFlashLbl : "Flash",
+InsertFlash : "Lisää/muokkaa Flashia",
+InsertTableLbl : "Taulu",
+InsertTable : "Lisää taulu/muokkaa taulua",
+InsertLineLbl : "Murtoviiva",
+InsertLine : "Lisää murtoviiva",
+InsertSpecialCharLbl: "Erikoismerkki",
+InsertSpecialChar : "Lisää erikoismerkki",
+InsertSmileyLbl : "Hymiö",
+InsertSmiley : "Lisää hymiö",
+About : "FCKeditorista",
+Bold : "Lihavoitu",
+Italic : "Kursivoitu",
+Underline : "Alleviivattu",
+StrikeThrough : "Yliviivattu",
+Subscript : "Alaindeksi",
+Superscript : "Yläindeksi",
+LeftJustify : "Tasaa vasemmat reunat",
+CenterJustify : "Keskitä",
+RightJustify : "Tasaa oikeat reunat",
+BlockJustify : "Tasaa molemmat reunat",
+DecreaseIndent : "Pienennä sisennystä",
+IncreaseIndent : "Suurenna sisennystä",
+Undo : "Kumoa",
+Redo : "Toista",
+NumberedListLbl : "Numerointi",
+NumberedList : "Lisää/poista numerointi",
+BulletedListLbl : "Luottelomerkit",
+BulletedList : "Lisää/poista luottelomerkit",
+ShowTableBorders : "Näytä taulun rajat",
+ShowDetails : "Näytä muotoilu",
+Style : "Tyyli",
+FontFormat : "Muotoilu",
+Font : "Fontti",
+FontSize : "Koko",
+TextColor : "Tekstiväri",
+BGColor : "Taustaväri",
+Source : "Koodi",
+Find : "Etsi",
+Replace : "Korvaa",
+SpellCheck : "Tarkista oikeinkirjoitus",
+UniversalKeyboard : "Universaali näppäimistö",
+PageBreakLbl : "Sivun vaihto",
+PageBreak : "Lisää sivun vaihto",
+
+Form : "Lomake",
+Checkbox : "Valintaruutu",
+RadioButton : "Radiopainike",
+TextField : "Tekstikenttä",
+Textarea : "Tekstilaatikko",
+HiddenField : "Piilokenttä",
+Button : "Painike",
+SelectionField : "Valintakenttä",
+ImageButton : "Kuvapainike",
+
+FitWindow : "Suurenna editori koko ikkunaan",
+
+// Context Menu
+EditLink : "Muokkaa linkkiä",
+CellCM : "Solu",
+RowCM : "Rivi",
+ColumnCM : "Sarake",
+InsertRow : "Lisää rivi",
+DeleteRows : "Poista rivit",
+InsertColumn : "Lisää sarake",
+DeleteColumns : "Poista sarakkeet",
+InsertCell : "Lisää solu",
+DeleteCells : "Poista solut",
+MergeCells : "Yhdistä solut",
+SplitCell : "Jaa solu",
+TableDelete : "Poista taulu",
+CellProperties : "Solun ominaisuudet",
+TableProperties : "Taulun ominaisuudet",
+ImageProperties : "Kuvan ominaisuudet",
+FlashProperties : "Flash ominaisuudet",
+
+AnchorProp : "Ankkurin ominaisuudet",
+ButtonProp : "Painikkeen ominaisuudet",
+CheckboxProp : "Valintaruudun ominaisuudet",
+HiddenFieldProp : "Piilokentän ominaisuudet",
+RadioButtonProp : "Radiopainikkeen ominaisuudet",
+ImageButtonProp : "Kuvapainikkeen ominaisuudet",
+TextFieldProp : "Tekstikentän ominaisuudet",
+SelectionFieldProp : "Valintakentän ominaisuudet",
+TextareaProp : "Tekstilaatikon ominaisuudet",
+FormProp : "Lomakkeen ominaisuudet",
+
+FontFormats : "Normaali;Muotoiltu;Osoite;Otsikko 1;Otsikko 2;Otsikko 3;Otsikko 4;Otsikko 5;Otsikko 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Prosessoidaan XHTML:ää. Odota hetki...",
+Done : "Valmis",
+PasteWordConfirm : "Teksti, jonka haluat liittää, näyttää olevan kopioitu Wordista. Haluatko puhdistaa sen ennen liittämistä?",
+NotCompatiblePaste : "Tämä komento toimii vain Internet Explorer 5.5:ssa tai uudemmassa. Haluatko liittää ilman puhdistusta?",
+UnknownToolbarItem : "Tuntemanton työkalu \"%1\"",
+UnknownCommand : "Tuntematon komento \"%1\"",
+NotImplemented : "Komentoa ei ole liitetty sovellukseen",
+UnknownToolbarSet : "Työkalukokonaisuus \"%1\" ei ole olemassa",
+NoActiveX : "Selaimesi turvallisuusasetukset voivat rajoittaa joitain editorin ominaisuuksia. Sinun pitää ottaa käyttöön asetuksista \"Suorita ActiveX komponentit ja -plugin-laajennukset\". Saatat kohdata virheitä ja huomata puuttuvia ominaisuuksia.",
+BrowseServerBlocked : "Resurssiselainta ei voitu avata. Varmista, että ponnahdusikkunoiden estäjät eivät ole päällä.",
+DialogBlocked : "Apuikkunaa ei voitu avaata. Varmista, että ponnahdusikkunoiden estäjät eivät ole päällä.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Peruuta",
+DlgBtnClose : "Sulje",
+DlgBtnBrowseServer : "Selaa palvelinta",
+DlgAdvancedTag : "Lisäominaisuudet",
+DlgOpOther : "Muut",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Lisää URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ei asetettu>",
+DlgGenId : "Tunniste",
+DlgGenLangDir : "Kielen suunta",
+DlgGenLangDirLtr : "Vasemmalta oikealle (LTR)",
+DlgGenLangDirRtl : "Oikealta vasemmalle (RTL)",
+DlgGenLangCode : "Kielikoodi",
+DlgGenAccessKey : "Pikanäppäin",
+DlgGenName : "Nimi",
+DlgGenTabIndex : "Tabulaattori indeksi",
+DlgGenLongDescr : "Pitkän kuvauksen URL",
+DlgGenClass : "Tyyliluokat",
+DlgGenTitle : "Avustava otsikko",
+DlgGenContType : "Avustava sisällön tyyppi",
+DlgGenLinkCharset : "Linkitetty kirjaimisto",
+DlgGenStyle : "Tyyli",
+
+// Image Dialog
+DlgImgTitle : "Kuvan ominaisuudet",
+DlgImgInfoTab : "Kuvan tiedot",
+DlgImgBtnUpload : "Lähetä palvelimelle",
+DlgImgURL : "Osoite",
+DlgImgUpload : "Lisää kuva",
+DlgImgAlt : "Vaihtoehtoinen teksti",
+DlgImgWidth : "Leveys",
+DlgImgHeight : "Korkeus",
+DlgImgLockRatio : "Lukitse suhteet",
+DlgBtnResetSize : "Alkuperäinen koko",
+DlgImgBorder : "Raja",
+DlgImgHSpace : "Vaakatila",
+DlgImgVSpace : "Pystytila",
+DlgImgAlign : "Kohdistus",
+DlgImgAlignLeft : "Vasemmalle",
+DlgImgAlignAbsBottom: "Aivan alas",
+DlgImgAlignAbsMiddle: "Aivan keskelle",
+DlgImgAlignBaseline : "Alas (teksti)",
+DlgImgAlignBottom : "Alas",
+DlgImgAlignMiddle : "Keskelle",
+DlgImgAlignRight : "Oikealle",
+DlgImgAlignTextTop : "Ylös (teksti)",
+DlgImgAlignTop : "Ylös",
+DlgImgPreview : "Esikatselu",
+DlgImgAlertUrl : "Kirjoita kuvan osoite (URL)",
+DlgImgLinkTab : "Linkki",
+
+// Flash Dialog
+DlgFlashTitle : "Flash ominaisuudet",
+DlgFlashChkPlay : "Automaattinen käynnistys",
+DlgFlashChkLoop : "Toisto",
+DlgFlashChkMenu : "Näytä Flash-valikko",
+DlgFlashScale : "Levitä",
+DlgFlashScaleAll : "Näytä kaikki",
+DlgFlashScaleNoBorder : "Ei rajaa",
+DlgFlashScaleFit : "Tarkka koko",
+
+// Link Dialog
+DlgLnkWindowTitle : "Linkki",
+DlgLnkInfoTab : "Linkin tiedot",
+DlgLnkTargetTab : "Kohde",
+
+DlgLnkType : "Linkkityyppi",
+DlgLnkTypeURL : "Osoite",
+DlgLnkTypeAnchor : "Ankkuri tässä sivussa",
+DlgLnkTypeEMail : "Sähköposti",
+DlgLnkProto : "Protokolla",
+DlgLnkProtoOther : "<muu>",
+DlgLnkURL : "Osoite",
+DlgLnkAnchorSel : "Valitse ankkuri",
+DlgLnkAnchorByName : "Ankkurin nimen mukaan",
+DlgLnkAnchorById : "Ankkurin ID:n mukaan",
+DlgLnkNoAnchors : "<Ei ankkureita tässä dokumentissa>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Sähköpostiosoite",
+DlgLnkEMailSubject : "Aihe",
+DlgLnkEMailBody : "Viesti",
+DlgLnkUpload : "Lisää tiedosto",
+DlgLnkBtnUpload : "Lähetä palvelimelle",
+
+DlgLnkTarget : "Kohde",
+DlgLnkTargetFrame : "<kehys>",
+DlgLnkTargetPopup : "<popup ikkuna>",
+DlgLnkTargetBlank : "Uusi ikkuna (_blank)",
+DlgLnkTargetParent : "Emoikkuna (_parent)",
+DlgLnkTargetSelf : "Sama ikkuna (_self)",
+DlgLnkTargetTop : "Päällimmäisin ikkuna (_top)",
+DlgLnkTargetFrameName : "Kohdekehyksen nimi",
+DlgLnkPopWinName : "Popup ikkunan nimi",
+DlgLnkPopWinFeat : "Popup ikkunan ominaisuudet",
+DlgLnkPopResize : "Venytettävä",
+DlgLnkPopLocation : "Osoiterivi",
+DlgLnkPopMenu : "Valikkorivi",
+DlgLnkPopScroll : "Vierityspalkit",
+DlgLnkPopStatus : "Tilarivi",
+DlgLnkPopToolbar : "Vakiopainikkeet",
+DlgLnkPopFullScrn : "Täysi ikkuna (IE)",
+DlgLnkPopDependent : "Riippuva (Netscape)",
+DlgLnkPopWidth : "Leveys",
+DlgLnkPopHeight : "Korkeus",
+DlgLnkPopLeft : "Vasemmalta (px)",
+DlgLnkPopTop : "Ylhäältä (px)",
+
+DlnLnkMsgNoUrl : "Linkille on kirjoitettava URL",
+DlnLnkMsgNoEMail : "Kirjoita sähköpostiosoite",
+DlnLnkMsgNoAnchor : "Valitse ankkuri",
+DlnLnkMsgInvPopName : "Popup-ikkunan nimi pitää alkaa aakkosella ja ei saa sisältää välejä",
+
+// Color Dialog
+DlgColorTitle : "Valitse väri",
+DlgColorBtnClear : "Tyhjennä",
+DlgColorHighlight : "Kohdalla",
+DlgColorSelected : "Valittu",
+
+// Smiley Dialog
+DlgSmileyTitle : "Lisää hymiö",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Valitse erikoismerkki",
+
+// Table Dialog
+DlgTableTitle : "Taulun ominaisuudet",
+DlgTableRows : "Rivit",
+DlgTableColumns : "Sarakkeet",
+DlgTableBorder : "Rajan paksuus",
+DlgTableAlign : "Kohdistus",
+DlgTableAlignNotSet : "<ei asetettu>",
+DlgTableAlignLeft : "Vasemmalle",
+DlgTableAlignCenter : "Keskelle",
+DlgTableAlignRight : "Oikealle",
+DlgTableWidth : "Leveys",
+DlgTableWidthPx : "pikseliä",
+DlgTableWidthPc : "prosenttia",
+DlgTableHeight : "Korkeus",
+DlgTableCellSpace : "Solujen väli",
+DlgTableCellPad : "Solujen sisennys",
+DlgTableCaption : "Otsikko",
+DlgTableSummary : "Yhteenveto",
+
+// Table Cell Dialog
+DlgCellTitle : "Solun ominaisuudet",
+DlgCellWidth : "Leveys",
+DlgCellWidthPx : "pikseliä",
+DlgCellWidthPc : "prosenttia",
+DlgCellHeight : "Korkeus",
+DlgCellWordWrap : "Tekstikierrätys",
+DlgCellWordWrapNotSet : "<Ei asetettu>",
+DlgCellWordWrapYes : "Kyllä",
+DlgCellWordWrapNo : "Ei",
+DlgCellHorAlign : "Vaakakohdistus",
+DlgCellHorAlignNotSet : "<Ei asetettu>",
+DlgCellHorAlignLeft : "Vasemmalle",
+DlgCellHorAlignCenter : "Keskelle",
+DlgCellHorAlignRight: "Oikealle",
+DlgCellVerAlign : "Pystykohdistus",
+DlgCellVerAlignNotSet : "<Ei asetettu>",
+DlgCellVerAlignTop : "Ylös",
+DlgCellVerAlignMiddle : "Keskelle",
+DlgCellVerAlignBottom : "Alas",
+DlgCellVerAlignBaseline : "Tekstin alas",
+DlgCellRowSpan : "Rivin jatkuvuus",
+DlgCellCollSpan : "Sarakkeen jatkuvuus",
+DlgCellBackColor : "Taustaväri",
+DlgCellBorderColor : "Rajan väri",
+DlgCellBtnSelect : "Valitse...",
+
+// Find Dialog
+DlgFindTitle : "Etsi",
+DlgFindFindBtn : "Etsi",
+DlgFindNotFoundMsg : "Etsittyä tekstiä ei löytynyt.",
+
+// Replace Dialog
+DlgReplaceTitle : "Korvaa",
+DlgReplaceFindLbl : "Etsi mitä:",
+DlgReplaceReplaceLbl : "Korvaa tällä:",
+DlgReplaceCaseChk : "Sama kirjainkoko",
+DlgReplaceReplaceBtn : "Korvaa",
+DlgReplaceReplAllBtn : "Korvaa kaikki",
+DlgReplaceWordChk : "Koko sana",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Selaimesi turva-asetukset eivät salli editorin toteuttaa leikkaamista. Käytä näppäimistöä leikkaamiseen (Ctrl+X).",
+PasteErrorCopy : "Selaimesi turva-asetukset eivät salli editorin toteuttaa kopioimista. Käytä näppäimistöä kopioimiseen (Ctrl+C).",
+
+PasteAsText : "Liitä tekstinä",
+PasteFromWord : "Liitä Wordista",
+
+DlgPasteMsg2 : "Liitä painamalla (<STRONG>Ctrl+V</STRONG>) ja painamalla <STRONG>OK</STRONG>.",
+DlgPasteSec : "Selaimesi turva-asetukset eivät salli editorin käyttää leikepöytää suoraan. Sinun pitää suorittaa liittäminen tässä ikkunassa.",
+DlgPasteIgnoreFont : "Jätä huomioimatta fonttimääritykset",
+DlgPasteRemoveStyles : "Poista tyylimääritykset",
+DlgPasteCleanBox : "Tyhjennä",
+
+// Color Picker
+ColorAutomatic : "Automaattinen",
+ColorMoreColors : "Lisää värejä...",
+
+// Document Properties
+DocProps : "Dokumentin ominaisuudet",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankkurin ominaisuudet",
+DlgAnchorName : "Nimi",
+DlgAnchorErrorName : "Ankkurille on kirjoitettava nimi",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ei sanakirjassa",
+DlgSpellChangeTo : "Vaihda",
+DlgSpellBtnIgnore : "Jätä huomioimatta",
+DlgSpellBtnIgnoreAll : "Jätä kaikki huomioimatta",
+DlgSpellBtnReplace : "Korvaa",
+DlgSpellBtnReplaceAll : "Korvaa kaikki",
+DlgSpellBtnUndo : "Kumoa",
+DlgSpellNoSuggestions : "Ei ehdotuksia",
+DlgSpellProgress : "Tarkistus käynnissä...",
+DlgSpellNoMispell : "Tarkistus valmis: Ei virheitä",
+DlgSpellNoChanges : "Tarkistus valmis: Yhtään sanaa ei muutettu",
+DlgSpellOneChange : "Tarkistus valmis: Yksi sana muutettiin",
+DlgSpellManyChanges : "Tarkistus valmis: %1 sanaa muutettiin",
+
+IeSpellDownload : "Oikeinkirjoituksen tarkistusta ei ole asennettu. Haluatko ladata sen nyt?",
+
+// Button Dialog
+DlgButtonText : "Teksti (arvo)",
+DlgButtonType : "Tyyppi",
+DlgButtonTypeBtn : "Painike",
+DlgButtonTypeSbm : "Lähetä",
+DlgButtonTypeRst : "Tyhjennä",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nimi",
+DlgCheckboxValue : "Arvo",
+DlgCheckboxSelected : "Valittu",
+
+// Form Dialog
+DlgFormName : "Nimi",
+DlgFormAction : "Toiminto",
+DlgFormMethod : "Tapa",
+
+// Select Field Dialog
+DlgSelectName : "Nimi",
+DlgSelectValue : "Arvo",
+DlgSelectSize : "Koko",
+DlgSelectLines : "Rivit",
+DlgSelectChkMulti : "Salli usea valinta",
+DlgSelectOpAvail : "Ominaisuudet",
+DlgSelectOpText : "Teksti",
+DlgSelectOpValue : "Arvo",
+DlgSelectBtnAdd : "Lisää",
+DlgSelectBtnModify : "Muuta",
+DlgSelectBtnUp : "Ylös",
+DlgSelectBtnDown : "Alas",
+DlgSelectBtnSetValue : "Aseta valituksi",
+DlgSelectBtnDelete : "Poista",
+
+// Textarea Dialog
+DlgTextareaName : "Nimi",
+DlgTextareaCols : "Sarakkeita",
+DlgTextareaRows : "Rivejä",
+
+// Text Field Dialog
+DlgTextName : "Nimi",
+DlgTextValue : "Arvo",
+DlgTextCharWidth : "Leveys",
+DlgTextMaxChars : "Maksimi merkkimäärä",
+DlgTextType : "Tyyppi",
+DlgTextTypeText : "Teksti",
+DlgTextTypePass : "Salasana",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nimi",
+DlgHiddenValue : "Arvo",
+
+// Bulleted List Dialog
+BulletedListProp : "Luettelon ominaisuudet",
+NumberedListProp : "Numeroinnin ominaisuudet",
+DlgLstStart : "Alku",
+DlgLstType : "Tyyppi",
+DlgLstTypeCircle : "Kehä",
+DlgLstTypeDisc : "Ympyrä",
+DlgLstTypeSquare : "Neliö",
+DlgLstTypeNumbers : "Numerot (1, 2, 3)",
+DlgLstTypeLCase : "Pienet kirjaimet (a, b, c)",
+DlgLstTypeUCase : "Isot kirjaimet (A, B, C)",
+DlgLstTypeSRoman : "Pienet roomalaiset numerot (i, ii, iii)",
+DlgLstTypeLRoman : "Isot roomalaiset numerot (Ii, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Yleiset",
+DlgDocBackTab : "Tausta",
+DlgDocColorsTab : "Värit ja marginaalit",
+DlgDocMetaTab : "Meta-tieto",
+
+DlgDocPageTitle : "Sivun nimi",
+DlgDocLangDir : "Kielen suunta",
+DlgDocLangDirLTR : "Vasemmalta oikealle (LTR)",
+DlgDocLangDirRTL : "Oikealta vasemmalle (RTL)",
+DlgDocLangCode : "Kielikoodi",
+DlgDocCharSet : "Merkistökoodaus",
+DlgDocCharSetCE : "Keskieurooppalainen",
+DlgDocCharSetCT : "Kiina, perinteinen (Big5)",
+DlgDocCharSetCR : "Kyrillinen",
+DlgDocCharSetGR : "Kreikka",
+DlgDocCharSetJP : "Japani",
+DlgDocCharSetKR : "Korealainen",
+DlgDocCharSetTR : "Turkkilainen",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Länsieurooppalainen",
+DlgDocCharSetOther : "Muu merkistökoodaus",
+
+DlgDocDocType : "Dokumentin tyyppi",
+DlgDocDocTypeOther : "Muu dokumentin tyyppi",
+DlgDocIncXHTML : "Lisää XHTML julistukset",
+DlgDocBgColor : "Taustaväri",
+DlgDocBgImage : "Taustakuva",
+DlgDocBgNoScroll : "Paikallaanpysyvä tausta",
+DlgDocCText : "Teksti",
+DlgDocCLink : "Linkki",
+DlgDocCVisited : "Vierailtu linkki",
+DlgDocCActive : "Aktiivinen linkki",
+DlgDocMargins : "Sivun marginaalit",
+DlgDocMaTop : "Ylä",
+DlgDocMaLeft : "Vasen",
+DlgDocMaRight : "Oikea",
+DlgDocMaBottom : "Ala",
+DlgDocMeIndex : "Hakusanat (pilkulla erotettuna)",
+DlgDocMeDescr : "Kuvaus",
+DlgDocMeAuthor : "Tekijä",
+DlgDocMeCopy : "Tekijänoikeudet",
+DlgDocPreview : "Esikatselu",
+
+// Templates Dialog
+Templates : "Pohjat",
+DlgTemplatesTitle : "Sisältöpohjat",
+DlgTemplatesSelMsg : "Valitse pohja editoriin<br>(aiempi sisältö menetetään):",
+DlgTemplatesLoading : "Ladataan listaa pohjista. Hetkinen...",
+DlgTemplatesNoTpl : "(Ei määriteltyjä pohjia)",
+DlgTemplatesReplace : "Korvaa editorin koko sisältö",
+
+// About Dialog
+DlgAboutAboutTab : "Editorista",
+DlgAboutBrowserInfoTab : "Selaimen tiedot",
+DlgAboutLicenseTab : "Lisenssi",
+DlgAboutVersion : "versio",
+DlgAboutInfo : "Lisää tietoa osoitteesta"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/fo.js b/httemplate/elements/fckeditor/editor/lang/fo.js
new file mode 100644
index 000000000..830c43eea
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/fo.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Faroese language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Fjal amboðsbjálkan",
+ToolbarExpand : "Vís amboðsbjálkan",
+
+// Toolbar Items and Context Menu
+Save : "Goym",
+NewPage : "Nýggj síða",
+Preview : "Frumsýning",
+Cut : "Kvett",
+Copy : "Avrita",
+Paste : "Innrita",
+PasteText : "Innrita reinan tekst",
+PasteWord : "Innrita frá Word",
+Print : "Prenta",
+SelectAll : "Markera alt",
+RemoveFormat : "Strika sniðgeving",
+InsertLinkLbl : "Tilknýti",
+InsertLink : "Ger/broyt tilknýti",
+RemoveLink : "Strika tilknýti",
+Anchor : "Ger/broyt marknastein",
+InsertImageLbl : "Myndir",
+InsertImage : "Set inn/broyt mynd",
+InsertFlashLbl : "Flash",
+InsertFlash : "Set inn/broyt Flash",
+InsertTableLbl : "Tabell",
+InsertTable : "Set inn/broyt tabell",
+InsertLineLbl : "Linja",
+InsertLine : "Ger vatnrætta linju",
+InsertSpecialCharLbl: "Sertekn",
+InsertSpecialChar : "Set inn sertekn",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Set inn Smiley",
+About : "Um FCKeditor",
+Bold : "Feit skrift",
+Italic : "Skráskrift",
+Underline : "Undirstrikað",
+StrikeThrough : "Yvirstrikað",
+Subscript : "Lækkað skrift",
+Superscript : "Hækkað skrift",
+LeftJustify : "Vinstrasett",
+CenterJustify : "Miðsett",
+RightJustify : "Høgrasett",
+BlockJustify : "Javnir tekstkantar",
+DecreaseIndent : "Minka reglubrotarinntriv",
+IncreaseIndent : "Økja reglubrotarinntriv",
+Undo : "Angra",
+Redo : "Vend aftur",
+NumberedListLbl : "Talmerktur listi",
+NumberedList : "Ger/strika talmerktan lista",
+BulletedListLbl : "Punktmerktur listi",
+BulletedList : "Ger/strika punktmerktan lista",
+ShowTableBorders : "Vís tabellbordar",
+ShowDetails : "Vís í smálutum",
+Style : "Typografi",
+FontFormat : "Skriftsnið",
+Font : "Skrift",
+FontSize : "Skriftstødd",
+TextColor : "Tekstlitur",
+BGColor : "Bakgrundslitur",
+Source : "Kelda",
+Find : "Leita",
+Replace : "Yvirskriva",
+SpellCheck : "Kanna stavseting",
+UniversalKeyboard : "Knappaborð",
+PageBreakLbl : "Síðuskift",
+PageBreak : "Ger síðuskift",
+
+Form : "Formur",
+Checkbox : "Flugubein",
+RadioButton : "Radioknøttur",
+TextField : "Tekstteigur",
+Textarea : "Tekstumráði",
+HiddenField : "Fjaldur teigur",
+Button : "Knøttur",
+SelectionField : "Valskrá",
+ImageButton : "Myndaknøttur",
+
+FitWindow : "Set tekstviðgera til fulla stødd",
+
+// Context Menu
+EditLink : "Broyt tilknýti",
+CellCM : "Meski",
+RowCM : "Rað",
+ColumnCM : "Kolonna",
+InsertRow : "Nýtt rað",
+DeleteRows : "Strika røðir",
+InsertColumn : "Nýggj kolonna",
+DeleteColumns : "Strika kolonnur",
+InsertCell : "Nýggjur meski",
+DeleteCells : "Strika meskar",
+MergeCells : "Flætta meskar",
+SplitCell : "Být sundur meskar",
+TableDelete : "Strika tabell",
+CellProperties : "Meskueginleikar",
+TableProperties : "Tabelleginleikar",
+ImageProperties : "Myndaeginleikar",
+FlashProperties : "Flash eginleikar",
+
+AnchorProp : "Eginleikar fyri marknastein",
+ButtonProp : "Eginleikar fyri knøtt",
+CheckboxProp : "Eginleikar fyri flugubein",
+HiddenFieldProp : "Eginleikar fyri fjaldan teig",
+RadioButtonProp : "Eginleikar fyri radioknøtt",
+ImageButtonProp : "Eginleikar fyri myndaknøtt",
+TextFieldProp : "Eginleikar fyri tekstteig",
+SelectionFieldProp : "Eginleikar fyri valskrá",
+TextareaProp : "Eginleikar fyri tekstumráði",
+FormProp : "Eginleikar fyri Form",
+
+FontFormats : "Vanligt;Sniðgivið;Adressa;Yvirskrift 1;Yvirskrift 2;Yvirskrift 3;Yvirskrift 4;Yvirskrift 5;Yvirskrift 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML verður viðgjørt. Bíða við...",
+Done : "Liðugt",
+PasteWordConfirm : "Teksturin, royndur verður at seta inn, tykist at stava frá Word. Vilt tú reinsa tekstin, áðrenn hann verður settur inn?",
+NotCompatiblePaste : "Hetta er bert tøkt í Internet Explorer 5.5 og nýggjari. Vilt tú seta tekstin inn kortini - óreinsaðan?",
+UnknownToolbarItem : "Ókendur lutur í amboðsbjálkanum \"%1\"",
+UnknownCommand : "Ókend kommando \"%1\"",
+NotImplemented : "Hetta er ikki tøkt í hesi útgávuni",
+UnknownToolbarSet : "Amboðsbjálkin \"%1\" finst ikki",
+NoActiveX : "Trygdaruppsetingin í alnótskaganum kann sum er avmarka onkrar hentleikar í tekstviðgeranum. Tú mást loyva møguleikanum \"Run/Kør ActiveX controls and plug-ins\". Tú kanst uppliva feilir og ávaringar um tvørrandi hentleikar.",
+BrowseServerBlocked : "Ambætarakagin kundi ikki opnast. Tryggja tær, at allar pop-up forðingar eru óvirknar.",
+DialogBlocked : "Tað eyðnaðist ikki at opna samskiftisrútin. Tryggja tær, at allar pop-up forðingar eru óvirknar.",
+
+// Dialogs
+DlgBtnOK : "Góðkent",
+DlgBtnCancel : "Avlýst",
+DlgBtnClose : "Lat aftur",
+DlgBtnBrowseServer : "Ambætarakagi",
+DlgAdvancedTag : "Fjølbroytt",
+DlgOpOther : "<Annað>",
+DlgInfoTab : "Upplýsingar",
+DlgAlertUrl : "Vinarliga veit ein URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ikki sett>",
+DlgGenId : "Id",
+DlgGenLangDir : "Tekstkós",
+DlgGenLangDirLtr : "Frá vinstru til høgru (LTR)",
+DlgGenLangDirRtl : "Frá høgru til vinstru (RTL)",
+DlgGenLangCode : "Málkoda",
+DlgGenAccessKey : "Snarvegisknappur",
+DlgGenName : "Navn",
+DlgGenTabIndex : "Inntriv indeks",
+DlgGenLongDescr : "Víðkað URL frágreiðing",
+DlgGenClass : "Typografi klassar",
+DlgGenTitle : "Vegleiðandi heiti",
+DlgGenContType : "Vegleiðandi innihaldsslag",
+DlgGenLinkCharset : "Atknýtt teknsett",
+DlgGenStyle : "Typografi",
+
+// Image Dialog
+DlgImgTitle : "Myndaeginleikar",
+DlgImgInfoTab : "Myndaupplýsingar",
+DlgImgBtnUpload : "Send til ambætaran",
+DlgImgURL : "URL",
+DlgImgUpload : "Send",
+DlgImgAlt : "Alternativur tekstur",
+DlgImgWidth : "Breidd",
+DlgImgHeight : "Hædd",
+DlgImgLockRatio : "Læs lutfallið",
+DlgBtnResetSize : "Upprunastødd",
+DlgImgBorder : "Bordi",
+DlgImgHSpace : "Høgri breddi",
+DlgImgVSpace : "Vinstri breddi",
+DlgImgAlign : "Justering",
+DlgImgAlignLeft : "Vinstra",
+DlgImgAlignAbsBottom: "Abs botnur",
+DlgImgAlignAbsMiddle: "Abs miðja",
+DlgImgAlignBaseline : "Basislinja",
+DlgImgAlignBottom : "Botnur",
+DlgImgAlignMiddle : "Miðja",
+DlgImgAlignRight : "Høgra",
+DlgImgAlignTextTop : "Tekst toppur",
+DlgImgAlignTop : "Ovast",
+DlgImgPreview : "Frumsýning",
+DlgImgAlertUrl : "Rita slóðina til myndina",
+DlgImgLinkTab : "Tilknýti",
+
+// Flash Dialog
+DlgFlashTitle : "Flash eginleikar",
+DlgFlashChkPlay : "Avspælingin byrjar sjálv",
+DlgFlashChkLoop : "Endurspæl",
+DlgFlashChkMenu : "Ger Flash skrá virkna",
+DlgFlashScale : "Skalering",
+DlgFlashScaleAll : "Vís alt",
+DlgFlashScaleNoBorder : "Eingin bordi",
+DlgFlashScaleFit : "Neyv skalering",
+
+// Link Dialog
+DlgLnkWindowTitle : "Tilknýti",
+DlgLnkInfoTab : "Tilknýtis upplýsingar",
+DlgLnkTargetTab : "Mál",
+
+DlgLnkType : "Tilknýtisslag",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Tilknýti til marknastein í tekstinum",
+DlgLnkTypeEMail : "Teldupostur",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<Annað>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Vel ein marknastein",
+DlgLnkAnchorByName : "Eftir navni á marknasteini",
+DlgLnkAnchorById : "Eftir element Id",
+DlgLnkNoAnchors : "(Eingir marknasteinar eru í hesum dokumentið)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Teldupost-adressa",
+DlgLnkEMailSubject : "Evni",
+DlgLnkEMailBody : "Breyðtekstur",
+DlgLnkUpload : "Send til ambætaran",
+DlgLnkBtnUpload : "Send til ambætaran",
+
+DlgLnkTarget : "Mál",
+DlgLnkTargetFrame : "<ramma>",
+DlgLnkTargetPopup : "<popup vindeyga>",
+DlgLnkTargetBlank : "Nýtt vindeyga (_blank)",
+DlgLnkTargetParent : "Upphavliga vindeygað (_parent)",
+DlgLnkTargetSelf : "Sama vindeygað (_self)",
+DlgLnkTargetTop : "Alt vindeygað (_top)",
+DlgLnkTargetFrameName : "Vís navn vindeygans",
+DlgLnkPopWinName : "Popup vindeygans navn",
+DlgLnkPopWinFeat : "Popup vindeygans víðkaðu eginleikar",
+DlgLnkPopResize : "Kann broyta stødd",
+DlgLnkPopLocation : "Adressulinja",
+DlgLnkPopMenu : "Skrábjálki",
+DlgLnkPopScroll : "Rullibjálki",
+DlgLnkPopStatus : "Støðufrágreiðingarbjálki",
+DlgLnkPopToolbar : "Amboðsbjálki",
+DlgLnkPopFullScrn : "Fullur skermur (IE)",
+DlgLnkPopDependent : "Bundið (Netscape)",
+DlgLnkPopWidth : "Breidd",
+DlgLnkPopHeight : "Hædd",
+DlgLnkPopLeft : "Frástøða frá vinstru",
+DlgLnkPopTop : "Frástøða frá íerva",
+
+DlnLnkMsgNoUrl : "Vinarliga skriva tilknýti (URL)",
+DlnLnkMsgNoEMail : "Vinarliga skriva teldupost-adressu",
+DlnLnkMsgNoAnchor : "Vinarliga vel marknastein",
+DlnLnkMsgInvPopName : "Popup navnið má byrja við bókstavi og má ikki hava millumrúm",
+
+// Color Dialog
+DlgColorTitle : "Vel lit",
+DlgColorBtnClear : "Strika alt",
+DlgColorHighlight : "Framhevja",
+DlgColorSelected : "Valt",
+
+// Smiley Dialog
+DlgSmileyTitle : "Vel Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Vel sertekn",
+
+// Table Dialog
+DlgTableTitle : "Eginleikar fyri tabell",
+DlgTableRows : "Røðir",
+DlgTableColumns : "Kolonnur",
+DlgTableBorder : "Bordabreidd",
+DlgTableAlign : "Justering",
+DlgTableAlignNotSet : "<Einki valt>",
+DlgTableAlignLeft : "Vinstrasett",
+DlgTableAlignCenter : "Miðsett",
+DlgTableAlignRight : "Høgrasett",
+DlgTableWidth : "Breidd",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "prosent",
+DlgTableHeight : "Hædd",
+DlgTableCellSpace : "Fjarstøða millum meskar",
+DlgTableCellPad : "Meskubreddi",
+DlgTableCaption : "Tabellfrágreiðing",
+DlgTableSummary : "Samandráttur",
+
+// Table Cell Dialog
+DlgCellTitle : "Mesku eginleikar",
+DlgCellWidth : "Breidd",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "prosent",
+DlgCellHeight : "Hædd",
+DlgCellWordWrap : "Orðkloyving",
+DlgCellWordWrapNotSet : "<Einki valt>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nei",
+DlgCellHorAlign : "Vatnrøtt justering",
+DlgCellHorAlignNotSet : "<Einki valt>",
+DlgCellHorAlignLeft : "Vinstrasett",
+DlgCellHorAlignCenter : "Miðsett",
+DlgCellHorAlignRight: "Høgrasett",
+DlgCellVerAlign : "Lodrøtt justering",
+DlgCellVerAlignNotSet : "<Ikki sett>",
+DlgCellVerAlignTop : "Ovast",
+DlgCellVerAlignMiddle : "Miðjan",
+DlgCellVerAlignBottom : "Niðast",
+DlgCellVerAlignBaseline : "Basislinja",
+DlgCellRowSpan : "Røðir, meskin fevnir um",
+DlgCellCollSpan : "Kolonnur, meskin fevnir um",
+DlgCellBackColor : "Bakgrundslitur",
+DlgCellBorderColor : "Litur á borda",
+DlgCellBtnSelect : "Vel...",
+
+// Find Dialog
+DlgFindTitle : "Finn",
+DlgFindFindBtn : "Finn",
+DlgFindNotFoundMsg : "Leititeksturin varð ikki funnin",
+
+// Replace Dialog
+DlgReplaceTitle : "Yvirskriva",
+DlgReplaceFindLbl : "Finn:",
+DlgReplaceReplaceLbl : "Yvirskriva við:",
+DlgReplaceCaseChk : "Munur á stórum og smáðum bókstavum",
+DlgReplaceReplaceBtn : "Yvirskriva",
+DlgReplaceReplAllBtn : "Yvirskriva alt",
+DlgReplaceWordChk : "Bert heil orð",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Trygdaruppseting alnótskagans forðar tekstviðgeranum í at kvetta tekstin. vinarliga nýt knappaborðið til at kvetta tekstin (CTRL+X).",
+PasteErrorCopy : "Trygdaruppseting alnótskagans forðar tekstviðgeranum í at avrita tekstin. Vinarliga nýt knappaborðið til at avrita tekstin (CTRL+C).",
+
+PasteAsText : "Innrita som reinan tekst",
+PasteFromWord : "Innrita fra Word",
+
+DlgPasteMsg2 : "Vinarliga koyr tekstin í hendan rútin við knappaborðinum (<strong>CTRL+V</strong>) og klikk á <strong>Góðtak</strong>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Forfjóna Font definitiónirnar",
+DlgPasteRemoveStyles : "Strika Styles definitiónir",
+DlgPasteCleanBox : "Reinskanarkassi",
+
+// Color Picker
+ColorAutomatic : "Av sær sjálvum",
+ColorMoreColors : "Fleiri litir...",
+
+// Document Properties
+DocProps : "Eginleikar fyri dokument",
+
+// Anchor Dialog
+DlgAnchorTitle : "Eginleikar fyri marknastein",
+DlgAnchorName : "Heiti marknasteinsins",
+DlgAnchorErrorName : "Vinarliga rita marknasteinsins heiti",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Finst ikki í orðabókini",
+DlgSpellChangeTo : "Broyt til",
+DlgSpellBtnIgnore : "Forfjóna",
+DlgSpellBtnIgnoreAll : "Forfjóna alt",
+DlgSpellBtnReplace : "Yvirskriva",
+DlgSpellBtnReplaceAll : "Yvirskriva alt",
+DlgSpellBtnUndo : "Angra",
+DlgSpellNoSuggestions : "- Einki uppskot -",
+DlgSpellProgress : "Rættstavarin arbeiðir...",
+DlgSpellNoMispell : "Rættstavarain liðugur: Eingin feilur funnin",
+DlgSpellNoChanges : "Rættstavarain liðugur: Einki orð varð broytt",
+DlgSpellOneChange : "Rættstavarain liðugur: Eitt orð er broytt",
+DlgSpellManyChanges : "Rættstavarain liðugur: %1 orð broytt",
+
+IeSpellDownload : "Rættstavarin er ikki tøkur í tekstviðgeranum. Vilt tú heinta hann nú?",
+
+// Button Dialog
+DlgButtonText : "Tekstur",
+DlgButtonType : "Slag",
+DlgButtonTypeBtn : "Knøttur",
+DlgButtonTypeSbm : "Send",
+DlgButtonTypeRst : "Nullstilla",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Navn",
+DlgCheckboxValue : "Virði",
+DlgCheckboxSelected : "Valt",
+
+// Form Dialog
+DlgFormName : "Navn",
+DlgFormAction : "Hending",
+DlgFormMethod : "Háttur",
+
+// Select Field Dialog
+DlgSelectName : "Navn",
+DlgSelectValue : "Virði",
+DlgSelectSize : "Stødd",
+DlgSelectLines : "Linjur",
+DlgSelectChkMulti : "Loyv fleiri valmøguleikum samstundis",
+DlgSelectOpAvail : "Tøkir møguleikar",
+DlgSelectOpText : "Tekstur",
+DlgSelectOpValue : "Virði",
+DlgSelectBtnAdd : "Legg afturat",
+DlgSelectBtnModify : "Broyt",
+DlgSelectBtnUp : "Upp",
+DlgSelectBtnDown : "Niður",
+DlgSelectBtnSetValue : "Set sum valt virði",
+DlgSelectBtnDelete : "Strika",
+
+// Textarea Dialog
+DlgTextareaName : "Navn",
+DlgTextareaCols : "kolonnur",
+DlgTextareaRows : "røðir",
+
+// Text Field Dialog
+DlgTextName : "Navn",
+DlgTextValue : "Virði",
+DlgTextCharWidth : "Breidd (sjónlig tekn)",
+DlgTextMaxChars : "Mest loyvdu tekn",
+DlgTextType : "Slag",
+DlgTextTypeText : "Tekstur",
+DlgTextTypePass : "Loyniorð",
+
+// Hidden Field Dialog
+DlgHiddenName : "Navn",
+DlgHiddenValue : "Virði",
+
+// Bulleted List Dialog
+BulletedListProp : "Eginleikar fyri punktmerktan lista",
+NumberedListProp : "Eginleikar fyri talmerktan lista",
+DlgLstStart : "Byrjan",
+DlgLstType : "Slag",
+DlgLstTypeCircle : "Sirkul",
+DlgLstTypeDisc : "Fyltur sirkul",
+DlgLstTypeSquare : "Fjórhyrningur",
+DlgLstTypeNumbers : "Talmerkt (1, 2, 3)",
+DlgLstTypeLCase : "Smáir bókstavir (a, b, c)",
+DlgLstTypeUCase : "Stórir bókstavir (A, B, C)",
+DlgLstTypeSRoman : "Smá rómaratøl (i, ii, iii)",
+DlgLstTypeLRoman : "Stór rómaratøl (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Generelt",
+DlgDocBackTab : "Bakgrund",
+DlgDocColorsTab : "Litir og breddar",
+DlgDocMetaTab : "META-upplýsingar",
+
+DlgDocPageTitle : "Síðuheiti",
+DlgDocLangDir : "Tekstkós",
+DlgDocLangDirLTR : "Frá vinstru móti høgru (LTR)",
+DlgDocLangDirRTL : "Frá høgru móti vinstru (RTL)",
+DlgDocLangCode : "Málkoda",
+DlgDocCharSet : "Teknsett koda",
+DlgDocCharSetCE : "Miðeuropa",
+DlgDocCharSetCT : "Kinesiskt traditionelt (Big5)",
+DlgDocCharSetCR : "Cyrilliskt",
+DlgDocCharSetGR : "Grikst",
+DlgDocCharSetJP : "Japanskt",
+DlgDocCharSetKR : "Koreanskt",
+DlgDocCharSetTR : "Turkiskt",
+DlgDocCharSetUN : "UNICODE (UTF-8)",
+DlgDocCharSetWE : "Vestureuropa",
+DlgDocCharSetOther : "Onnur teknsett koda",
+
+DlgDocDocType : "Dokumentslag yvirskrift",
+DlgDocDocTypeOther : "Annað dokumentslag yvirskrift",
+DlgDocIncXHTML : "Viðfest XHTML deklaratiónir",
+DlgDocBgColor : "Bakgrundslitur",
+DlgDocBgImage : "Leið til bakgrundsmynd (URL)",
+DlgDocBgNoScroll : "Læst bakgrund (rullar ikki)",
+DlgDocCText : "Tekstur",
+DlgDocCLink : "Tilknýti",
+DlgDocCVisited : "Vitjaði tilknýti",
+DlgDocCActive : "Virkin tilknýti",
+DlgDocMargins : "Síðubreddar",
+DlgDocMaTop : "Ovast",
+DlgDocMaLeft : "Vinstra",
+DlgDocMaRight : "Høgra",
+DlgDocMaBottom : "Niðast",
+DlgDocMeIndex : "Dokument index lyklaorð (sundurbýtt við komma)",
+DlgDocMeDescr : "Dokumentlýsing",
+DlgDocMeAuthor : "Høvundur",
+DlgDocMeCopy : "Upphavsrættindi",
+DlgDocPreview : "Frumsýning",
+
+// Templates Dialog
+Templates : "Skabelónir",
+DlgTemplatesTitle : "Innihaldsskabelónir",
+DlgTemplatesSelMsg : "Vinarliga vel ta skabelón, ið skal opnast í tekstviðgeranum<br>(Hetta yvirskrivar núverandi innihald):",
+DlgTemplatesLoading : "Heinti yvirlit yvir skabelónir. Vinarliga bíða við...",
+DlgTemplatesNoTpl : "(Ongar skabelónir tøkar)",
+DlgTemplatesReplace : "Yvirskriva núverandi innihald",
+
+// About Dialog
+DlgAboutAboutTab : "Um",
+DlgAboutBrowserInfoTab : "Upplýsingar um alnótskagan",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "Fyri fleiri upplýsingar, far til"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/fr.js b/httemplate/elements/fckeditor/editor/lang/fr.js
new file mode 100644
index 000000000..6d46fa0fc
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/fr.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * French language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Masquer Outils",
+ToolbarExpand : "Afficher Outils",
+
+// Toolbar Items and Context Menu
+Save : "Enregistrer",
+NewPage : "Nouvelle page",
+Preview : "Prévisualisation",
+Cut : "Couper",
+Copy : "Copier",
+Paste : "Coller",
+PasteText : "Coller comme texte",
+PasteWord : "Coller de Word",
+Print : "Imprimer",
+SelectAll : "Tout sélectionner",
+RemoveFormat : "Supprimer le format",
+InsertLinkLbl : "Lien",
+InsertLink : "Insérer/modifier le lien",
+RemoveLink : "Supprimer le lien",
+Anchor : "Insérer/modifier l'ancre",
+InsertImageLbl : "Image",
+InsertImage : "Insérer/modifier l'image",
+InsertFlashLbl : "Animation Flash",
+InsertFlash : "Insérer/modifier l'animation Flash",
+InsertTableLbl : "Tableau",
+InsertTable : "Insérer/modifier le tableau",
+InsertLineLbl : "Séparateur",
+InsertLine : "Insérer un séparateur",
+InsertSpecialCharLbl: "Caractères spéciaux",
+InsertSpecialChar : "Insérer un caractère spécial",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Insérer un Smiley",
+About : "A propos de FCKeditor",
+Bold : "Gras",
+Italic : "Italique",
+Underline : "Souligné",
+StrikeThrough : "Barré",
+Subscript : "Indice",
+Superscript : "Exposant",
+LeftJustify : "Aligné à gauche",
+CenterJustify : "Centré",
+RightJustify : "Aligné à Droite",
+BlockJustify : "Texte justifié",
+DecreaseIndent : "Diminuer le retrait",
+IncreaseIndent : "Augmenter le retrait",
+Undo : "Annuler",
+Redo : "Refaire",
+NumberedListLbl : "Liste numérotée",
+NumberedList : "Insérer/supprimer la liste numérotée",
+BulletedListLbl : "Liste à puces",
+BulletedList : "Insérer/supprimer la liste à puces",
+ShowTableBorders : "Afficher les bordures du tableau",
+ShowDetails : "Afficher les caractères invisibles",
+Style : "Style",
+FontFormat : "Format",
+Font : "Police",
+FontSize : "Taille",
+TextColor : "Couleur de caractère",
+BGColor : "Couleur de fond",
+Source : "Source",
+Find : "Chercher",
+Replace : "Remplacer",
+SpellCheck : "Orthographe",
+UniversalKeyboard : "Clavier universel",
+PageBreakLbl : "Saut de page",
+PageBreak : "Insérer un saut de page",
+
+Form : "Formulaire",
+Checkbox : "Case à cocher",
+RadioButton : "Bouton radio",
+TextField : "Champ texte",
+Textarea : "Zone de texte",
+HiddenField : "Champ caché",
+Button : "Bouton",
+SelectionField : "Liste/menu",
+ImageButton : "Bouton image",
+
+FitWindow : "Edition pleine page",
+
+// Context Menu
+EditLink : "Modifier le lien",
+CellCM : "Cellule",
+RowCM : "Ligne",
+ColumnCM : "Colonne",
+InsertRow : "Insérer une ligne",
+DeleteRows : "Supprimer des lignes",
+InsertColumn : "Insérer une colonne",
+DeleteColumns : "Supprimer des colonnes",
+InsertCell : "Insérer une cellule",
+DeleteCells : "Supprimer des cellules",
+MergeCells : "Fusionner les cellules",
+SplitCell : "Scinder les cellules",
+TableDelete : "Supprimer le tableau",
+CellProperties : "Propriétés de cellule",
+TableProperties : "Propriétés du tableau",
+ImageProperties : "Propriétés de l'image",
+FlashProperties : "Propriétés de l'animation Flash",
+
+AnchorProp : "Propriétés de l'ancre",
+ButtonProp : "Propriétés du bouton",
+CheckboxProp : "Propriétés de la case à cocher",
+HiddenFieldProp : "Propriétés du champ caché",
+RadioButtonProp : "Propriétés du bouton radio",
+ImageButtonProp : "Propriétés du bouton image",
+TextFieldProp : "Propriétés du champ texte",
+SelectionFieldProp : "Propriétés de la liste/du menu",
+TextareaProp : "Propriétés de la zone de texte",
+FormProp : "Propriétés du formulaire",
+
+FontFormats : "Normal;Formaté;Adresse;En-tête 1;En-tête 2;En-tête 3;En-tête 4;En-tête 5;En-tête 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Calcul XHTML. Veuillez patienter...",
+Done : "Terminé",
+PasteWordConfirm : "Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller?",
+NotCompatiblePaste : "Cette commande nécessite Internet Explorer version 5.5 minimum. Souhaitez-vous coller sans nettoyage?",
+UnknownToolbarItem : "Elément de barre d'outil inconnu \"%1\"",
+UnknownCommand : "Nom de commande inconnu \"%1\"",
+NotImplemented : "Commande non encore écrite",
+UnknownToolbarSet : "La barre d'outils \"%1\" n'existe pas",
+NoActiveX : "Les paramètres de sécurité de votre navigateur peuvent limiter quelques fonctionnalités de l'éditeur. Veuillez activer l'option \"Exécuter les contrôles ActiveX et les plug-ins\". Il se peut que vous rencontriez des erreurs et remarquiez quelques limitations.",
+BrowseServerBlocked : "Le navigateur n'a pas pu être ouvert. Assurez-vous que les bloqueurs de popups soient désactivés.",
+DialogBlocked : "La fenêtre de dialogue n'a pas pu s'ouvrir. Assurez-vous que les bloqueurs de popups soient désactivés.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Annuler",
+DlgBtnClose : "Fermer",
+DlgBtnBrowseServer : "Parcourir le serveur",
+DlgAdvancedTag : "Avancé",
+DlgOpOther : "<Autre>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Veuillez saisir l'URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<Par défaut>",
+DlgGenId : "Id",
+DlgGenLangDir : "Sens d'écriture",
+DlgGenLangDirLtr : "De gauche à droite (LTR)",
+DlgGenLangDirRtl : "De droite à gauche (RTL)",
+DlgGenLangCode : "Code langue",
+DlgGenAccessKey : "Equivalent clavier",
+DlgGenName : "Nom",
+DlgGenTabIndex : "Ordre de tabulation",
+DlgGenLongDescr : "URL de description longue",
+DlgGenClass : "Classes de feuilles de style",
+DlgGenTitle : "Titre",
+DlgGenContType : "Type de contenu",
+DlgGenLinkCharset : "Encodage de caractère",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Propriétés de l'image",
+DlgImgInfoTab : "Informations sur l'image",
+DlgImgBtnUpload : "Envoyer sur le serveur",
+DlgImgURL : "URL",
+DlgImgUpload : "Télécharger",
+DlgImgAlt : "Texte de remplacement",
+DlgImgWidth : "Largeur",
+DlgImgHeight : "Hauteur",
+DlgImgLockRatio : "Garder les proportions",
+DlgBtnResetSize : "Taille originale",
+DlgImgBorder : "Bordure",
+DlgImgHSpace : "Espacement horizontal",
+DlgImgVSpace : "Espacement vertical",
+DlgImgAlign : "Alignement",
+DlgImgAlignLeft : "Gauche",
+DlgImgAlignAbsBottom: "Abs Bas",
+DlgImgAlignAbsMiddle: "Abs Milieu",
+DlgImgAlignBaseline : "Bas du texte",
+DlgImgAlignBottom : "Bas",
+DlgImgAlignMiddle : "Milieu",
+DlgImgAlignRight : "Droite",
+DlgImgAlignTextTop : "Haut du texte",
+DlgImgAlignTop : "Haut",
+DlgImgPreview : "Prévisualisation",
+DlgImgAlertUrl : "Veuillez saisir l'URL de l'image",
+DlgImgLinkTab : "Lien",
+
+// Flash Dialog
+DlgFlashTitle : "Propriétés de l'animation Flash",
+DlgFlashChkPlay : "Lecture automatique",
+DlgFlashChkLoop : "Boucle",
+DlgFlashChkMenu : "Activer le menu Flash",
+DlgFlashScale : "Affichage",
+DlgFlashScaleAll : "Par défaut (tout montrer)",
+DlgFlashScaleNoBorder : "Sans bordure",
+DlgFlashScaleFit : "Ajuster aux dimensions",
+
+// Link Dialog
+DlgLnkWindowTitle : "Propriétés du lien",
+DlgLnkInfoTab : "Informations sur le lien",
+DlgLnkTargetTab : "Destination",
+
+DlgLnkType : "Type de lien",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ancre dans cette page",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocole",
+DlgLnkProtoOther : "<autre>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Sélectionner une ancre",
+DlgLnkAnchorByName : "Par nom",
+DlgLnkAnchorById : "Par id",
+DlgLnkNoAnchors : "<Pas d'ancre disponible dans le document>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Adresse E-Mail",
+DlgLnkEMailSubject : "Sujet du message",
+DlgLnkEMailBody : "Corps du message",
+DlgLnkUpload : "Télécharger",
+DlgLnkBtnUpload : "Envoyer sur le serveur",
+
+DlgLnkTarget : "Destination",
+DlgLnkTargetFrame : "<cadre>",
+DlgLnkTargetPopup : "<fenêtre popup>",
+DlgLnkTargetBlank : "Nouvelle fenêtre (_blank)",
+DlgLnkTargetParent : "Fenêtre mère (_parent)",
+DlgLnkTargetSelf : "Même fenêtre (_self)",
+DlgLnkTargetTop : "Fenêtre supérieure (_top)",
+DlgLnkTargetFrameName : "Nom du cadre de destination",
+DlgLnkPopWinName : "Nom de la fenêtre popup",
+DlgLnkPopWinFeat : "Caractéristiques de la fenêtre popup",
+DlgLnkPopResize : "Taille modifiable",
+DlgLnkPopLocation : "Barre d'adresses",
+DlgLnkPopMenu : "Barre de menu",
+DlgLnkPopScroll : "Barres de défilement",
+DlgLnkPopStatus : "Barre d'état",
+DlgLnkPopToolbar : "Barre d'outils",
+DlgLnkPopFullScrn : "Plein écran (IE)",
+DlgLnkPopDependent : "Dépendante (Netscape)",
+DlgLnkPopWidth : "Largeur",
+DlgLnkPopHeight : "Hauteur",
+DlgLnkPopLeft : "Position à partir de la gauche",
+DlgLnkPopTop : "Position à partir du haut",
+
+DlnLnkMsgNoUrl : "Veuillez saisir l'URL",
+DlnLnkMsgNoEMail : "Veuillez saisir l'adresse e-mail",
+DlnLnkMsgNoAnchor : "Veuillez sélectionner une ancre",
+DlnLnkMsgInvPopName : "Le nom de la fenêtre popup doit commencer par une lettre et ne doit pas contenir d'espace",
+
+// Color Dialog
+DlgColorTitle : "Sélectionner",
+DlgColorBtnClear : "Effacer",
+DlgColorHighlight : "Prévisualisation",
+DlgColorSelected : "Sélectionné",
+
+// Smiley Dialog
+DlgSmileyTitle : "Insérer un Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Insérer un caractère spécial",
+
+// Table Dialog
+DlgTableTitle : "Propriétés du tableau",
+DlgTableRows : "Lignes",
+DlgTableColumns : "Colonnes",
+DlgTableBorder : "Bordure",
+DlgTableAlign : "Alignement",
+DlgTableAlignNotSet : "<Par défaut>",
+DlgTableAlignLeft : "Gauche",
+DlgTableAlignCenter : "Centré",
+DlgTableAlignRight : "Droite",
+DlgTableWidth : "Largeur",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "pourcentage",
+DlgTableHeight : "Hauteur",
+DlgTableCellSpace : "Espacement",
+DlgTableCellPad : "Contour",
+DlgTableCaption : "Titre",
+DlgTableSummary : "Résumé",
+
+// Table Cell Dialog
+DlgCellTitle : "Propriétés de la cellule",
+DlgCellWidth : "Largeur",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "pourcentage",
+DlgCellHeight : "Hauteur",
+DlgCellWordWrap : "Retour à la ligne",
+DlgCellWordWrapNotSet : "<Par défaut>",
+DlgCellWordWrapYes : "Oui",
+DlgCellWordWrapNo : "Non",
+DlgCellHorAlign : "Alignement horizontal",
+DlgCellHorAlignNotSet : "<Par défaut>",
+DlgCellHorAlignLeft : "Gauche",
+DlgCellHorAlignCenter : "Centré",
+DlgCellHorAlignRight: "Droite",
+DlgCellVerAlign : "Alignement vertical",
+DlgCellVerAlignNotSet : "<Par défaut>",
+DlgCellVerAlignTop : "Haut",
+DlgCellVerAlignMiddle : "Milieu",
+DlgCellVerAlignBottom : "Bas",
+DlgCellVerAlignBaseline : "Bas du texte",
+DlgCellRowSpan : "Lignes fusionnées",
+DlgCellCollSpan : "Colonnes fusionnées",
+DlgCellBackColor : "Fond",
+DlgCellBorderColor : "Bordure",
+DlgCellBtnSelect : "Choisir...",
+
+// Find Dialog
+DlgFindTitle : "Chercher",
+DlgFindFindBtn : "Chercher",
+DlgFindNotFoundMsg : "Le texte indiqué est introuvable.",
+
+// Replace Dialog
+DlgReplaceTitle : "Remplacer",
+DlgReplaceFindLbl : "Rechercher:",
+DlgReplaceReplaceLbl : "Remplacer par:",
+DlgReplaceCaseChk : "Respecter la casse",
+DlgReplaceReplaceBtn : "Remplacer",
+DlgReplaceReplAllBtn : "Tout remplacer",
+DlgReplaceWordChk : "Mot entier",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de couper automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+X).",
+PasteErrorCopy : "Les paramètres de sécurité de votre navigateur empêchent l'éditeur de copier automatiquement vos données. Veuillez utiliser les équivalents claviers (Ctrl+C).",
+
+PasteAsText : "Coller comme texte",
+PasteFromWord : "Coller à partir de Word",
+
+DlgPasteMsg2 : "Veuillez coller dans la zone ci-dessous en utilisant le clavier (<STRONG>Ctrl+V</STRONG>) et cliquez sur <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorer les polices de caractères",
+DlgPasteRemoveStyles : "Supprimer les styles",
+DlgPasteCleanBox : "Effacer le contenu",
+
+// Color Picker
+ColorAutomatic : "Automatique",
+ColorMoreColors : "Plus de couleurs...",
+
+// Document Properties
+DocProps : "Propriétés du document",
+
+// Anchor Dialog
+DlgAnchorTitle : "Propriétés de l'ancre",
+DlgAnchorName : "Nom de l'ancre",
+DlgAnchorErrorName : "Veuillez saisir le nom de l'ancre",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Pas dans le dictionnaire",
+DlgSpellChangeTo : "Changer en",
+DlgSpellBtnIgnore : "Ignorer",
+DlgSpellBtnIgnoreAll : "Ignorer tout",
+DlgSpellBtnReplace : "Remplacer",
+DlgSpellBtnReplaceAll : "Remplacer tout",
+DlgSpellBtnUndo : "Annuler",
+DlgSpellNoSuggestions : "- Aucune suggestion -",
+DlgSpellProgress : "Vérification d'orthographe en cours...",
+DlgSpellNoMispell : "Vérification d'orthographe terminée: Aucune erreur trouvée",
+DlgSpellNoChanges : "Vérification d'orthographe terminée: Pas de modifications",
+DlgSpellOneChange : "Vérification d'orthographe terminée: Un mot modifié",
+DlgSpellManyChanges : "Vérification d'orthographe terminée: %1 mots modifiés",
+
+IeSpellDownload : "Le Correcteur n'est pas installé. Souhaitez-vous le télécharger maintenant?",
+
+// Button Dialog
+DlgButtonText : "Texte (valeur)",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Bouton",
+DlgButtonTypeSbm : "Envoyer",
+DlgButtonTypeRst : "Réinitialiser",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nom",
+DlgCheckboxValue : "Valeur",
+DlgCheckboxSelected : "Sélectionné",
+
+// Form Dialog
+DlgFormName : "Nom",
+DlgFormAction : "Action",
+DlgFormMethod : "Méthode",
+
+// Select Field Dialog
+DlgSelectName : "Nom",
+DlgSelectValue : "Valeur",
+DlgSelectSize : "Taille",
+DlgSelectLines : "lignes",
+DlgSelectChkMulti : "Sélection multiple",
+DlgSelectOpAvail : "Options disponibles",
+DlgSelectOpText : "Texte",
+DlgSelectOpValue : "Valeur",
+DlgSelectBtnAdd : "Ajouter",
+DlgSelectBtnModify : "Modifier",
+DlgSelectBtnUp : "Monter",
+DlgSelectBtnDown : "Descendre",
+DlgSelectBtnSetValue : "Valeur sélectionnée",
+DlgSelectBtnDelete : "Supprimer",
+
+// Textarea Dialog
+DlgTextareaName : "Nom",
+DlgTextareaCols : "Colonnes",
+DlgTextareaRows : "Lignes",
+
+// Text Field Dialog
+DlgTextName : "Nom",
+DlgTextValue : "Valeur",
+DlgTextCharWidth : "Largeur en caractères",
+DlgTextMaxChars : "Nombre maximum de caractères",
+DlgTextType : "Type",
+DlgTextTypeText : "Texte",
+DlgTextTypePass : "Mot de passe",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nom",
+DlgHiddenValue : "Valeur",
+
+// Bulleted List Dialog
+BulletedListProp : "Propriétés de liste à puces",
+NumberedListProp : "Propriétés de liste numérotée",
+DlgLstStart : "Début",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Cercle",
+DlgLstTypeDisc : "Disque",
+DlgLstTypeSquare : "Carré",
+DlgLstTypeNumbers : "Nombres (1, 2, 3)",
+DlgLstTypeLCase : "Lettres minuscules (a, b, c)",
+DlgLstTypeUCase : "Lettres majuscules (A, B, C)",
+DlgLstTypeSRoman : "Chiffres romains minuscules (i, ii, iii)",
+DlgLstTypeLRoman : "Chiffres romains majuscules (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Général",
+DlgDocBackTab : "Fond",
+DlgDocColorsTab : "Couleurs et marges",
+DlgDocMetaTab : "Métadonnées",
+
+DlgDocPageTitle : "Titre de la page",
+DlgDocLangDir : "Sens d'écriture",
+DlgDocLangDirLTR : "De la gauche vers la droite (LTR)",
+DlgDocLangDirRTL : "De la droite vers la gauche (RTL)",
+DlgDocLangCode : "Code langue",
+DlgDocCharSet : "Encodage de caractère",
+DlgDocCharSetCE : "Europe Centrale",
+DlgDocCharSetCT : "Chinois Traditionnel (Big5)",
+DlgDocCharSetCR : "Cyrillique",
+DlgDocCharSetGR : "Grec",
+DlgDocCharSetJP : "Japanais",
+DlgDocCharSetKR : "Coréen",
+DlgDocCharSetTR : "Turc",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Occidental",
+DlgDocCharSetOther : "Autre encodage de caractère",
+
+DlgDocDocType : "Type de document",
+DlgDocDocTypeOther : "Autre type de document",
+DlgDocIncXHTML : "Inclure les déclarations XHTML",
+DlgDocBgColor : "Couleur de fond",
+DlgDocBgImage : "Image de fond",
+DlgDocBgNoScroll : "Image fixe sans défilement",
+DlgDocCText : "Texte",
+DlgDocCLink : "Lien",
+DlgDocCVisited : "Lien visité",
+DlgDocCActive : "Lien activé",
+DlgDocMargins : "Marges",
+DlgDocMaTop : "Haut",
+DlgDocMaLeft : "Gauche",
+DlgDocMaRight : "Droite",
+DlgDocMaBottom : "Bas",
+DlgDocMeIndex : "Mots-clés (séparés par des virgules)",
+DlgDocMeDescr : "Description",
+DlgDocMeAuthor : "Auteur",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Prévisualisation",
+
+// Templates Dialog
+Templates : "Modèles",
+DlgTemplatesTitle : "Modèles de contenu",
+DlgTemplatesSelMsg : "Veuillez sélectionner le modèle à ouvrir dans l'éditeur<br>(le contenu actuel sera remplacé):",
+DlgTemplatesLoading : "Chargement de la liste des modèles. Veuillez patienter...",
+DlgTemplatesNoTpl : "(Aucun modèle disponible)",
+DlgTemplatesReplace : "Remplacer tout le contenu",
+
+// About Dialog
+DlgAboutAboutTab : "A propos de",
+DlgAboutBrowserInfoTab : "Navigateur",
+DlgAboutLicenseTab : "License",
+DlgAboutVersion : "version",
+DlgAboutInfo : "Pour plus d'informations, aller à"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/gl.js b/httemplate/elements/fckeditor/editor/lang/gl.js
new file mode 100644
index 000000000..238d108a0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/gl.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Galician language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Ocultar Ferramentas",
+ToolbarExpand : "Mostrar Ferramentas",
+
+// Toolbar Items and Context Menu
+Save : "Gardar",
+NewPage : "Nova Páxina",
+Preview : "Vista Previa",
+Cut : "Cortar",
+Copy : "Copiar",
+Paste : "Pegar",
+PasteText : "Pegar como texto plano",
+PasteWord : "Pegar dende Word",
+Print : "Imprimir",
+SelectAll : "Seleccionar todo",
+RemoveFormat : "Eliminar Formato",
+InsertLinkLbl : "Ligazón",
+InsertLink : "Inserir/Editar Ligazón",
+RemoveLink : "Eliminar Ligazón",
+Anchor : "Inserir/Editar Referencia",
+InsertImageLbl : "Imaxe",
+InsertImage : "Inserir/Editar Imaxe",
+InsertFlashLbl : "Flash",
+InsertFlash : "Inserir/Editar Flash",
+InsertTableLbl : "Tabla",
+InsertTable : "Inserir/Editar Tabla",
+InsertLineLbl : "Liña",
+InsertLine : "Inserir Liña Horizontal",
+InsertSpecialCharLbl: "Carácter Special",
+InsertSpecialChar : "Inserir Carácter Especial",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Inserir Smiley",
+About : "Acerca de FCKeditor",
+Bold : "Negrita",
+Italic : "Cursiva",
+Underline : "Sub-raiado",
+StrikeThrough : "Tachado",
+Subscript : "Subíndice",
+Superscript : "Superíndice",
+LeftJustify : "Aliñar á Esquerda",
+CenterJustify : "Centrado",
+RightJustify : "Aliñar á Dereita",
+BlockJustify : "Xustificado",
+DecreaseIndent : "Disminuir Sangría",
+IncreaseIndent : "Aumentar Sangría",
+Undo : "Desfacer",
+Redo : "Refacer",
+NumberedListLbl : "Lista Numerada",
+NumberedList : "Inserir/Eliminar Lista Numerada",
+BulletedListLbl : "Marcas",
+BulletedList : "Inserir/Eliminar Marcas",
+ShowTableBorders : "Mostrar Bordes das Táboas",
+ShowDetails : "Mostrar Marcas Parágrafo",
+Style : "Estilo",
+FontFormat : "Formato",
+Font : "Tipo",
+FontSize : "Tamaño",
+TextColor : "Cor do Texto",
+BGColor : "Cor do Fondo",
+Source : "Código Fonte",
+Find : "Procurar",
+Replace : "Substituir",
+SpellCheck : "Corrección Ortográfica",
+UniversalKeyboard : "Teclado Universal",
+PageBreakLbl : "Salto de Páxina",
+PageBreak : "Inserir Salto de Páxina",
+
+Form : "Formulario",
+Checkbox : "Cadro de Verificación",
+RadioButton : "Botón de Radio",
+TextField : "Campo de Texto",
+Textarea : "Área de Texto",
+HiddenField : "Campo Oculto",
+Button : "Botón",
+SelectionField : "Campo de Selección",
+ImageButton : "Botón de Imaxe",
+
+FitWindow : "Maximizar o tamaño do editor",
+
+// Context Menu
+EditLink : "Editar Ligazón",
+CellCM : "Cela",
+RowCM : "Fila",
+ColumnCM : "Columna",
+InsertRow : "Inserir Fila",
+DeleteRows : "Borrar Filas",
+InsertColumn : "Inserir Columna",
+DeleteColumns : "Borrar Columnas",
+InsertCell : "Inserir Cela",
+DeleteCells : "Borrar Cela",
+MergeCells : "Unir Celas",
+SplitCell : "Partir Celas",
+TableDelete : "Borrar Táboa",
+CellProperties : "Propriedades da Cela",
+TableProperties : "Propriedades da Táboa",
+ImageProperties : "Propriedades Imaxe",
+FlashProperties : "Propriedades Flash",
+
+AnchorProp : "Propriedades da Referencia",
+ButtonProp : "Propriedades do Botón",
+CheckboxProp : "Propriedades do Cadro de Verificación",
+HiddenFieldProp : "Propriedades do Campo Oculto",
+RadioButtonProp : "Propriedades do Botón de Radio",
+ImageButtonProp : "Propriedades do Botón de Imaxe",
+TextFieldProp : "Propriedades do Campo de Texto",
+SelectionFieldProp : "Propriedades do Campo de Selección",
+TextareaProp : "Propriedades da Área de Texto",
+FormProp : "Propriedades do Formulario",
+
+FontFormats : "Normal;Formateado;Enderezo;Enacabezado 1;Encabezado 2;Encabezado 3;Encabezado 4;Encabezado 5;Encabezado 6;Paragraph (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Procesando XHTML. Por facor, agarde...",
+Done : "Feiro",
+PasteWordConfirm : "Parece que o texto que quere pegar está copiado do Word.¿Quere limpar o formato antes de pegalo?",
+NotCompatiblePaste : "Este comando está disponible para Internet Explorer versión 5.5 ou superior. ¿Quere pegalo sen limpar o formato?",
+UnknownToolbarItem : "Ítem de ferramentas descoñecido \"%1\"",
+UnknownCommand : "Nome de comando descoñecido \"%1\"",
+NotImplemented : "Comando non implementado",
+UnknownToolbarSet : "O conxunto de ferramentas \"%1\" non existe",
+NoActiveX : "As opcións de seguridade do seu navegador poderían limitar algunha das características de editor. Debe activar a opción \"Executar controis ActiveX e plug-ins\". Pode notar que faltan características e experimentar erros",
+BrowseServerBlocked : "Non se poido abrir o navegador de recursos. Asegúrese de que están desactivados os bloqueadores de xanelas emerxentes",
+DialogBlocked : "Non foi posible abrir a xanela de diálogo. Asegúrese de que están desactivados os bloqueadores de xanelas emerxentes",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancelar",
+DlgBtnClose : "Pechar",
+DlgBtnBrowseServer : "Navegar no Servidor",
+DlgAdvancedTag : "Advanzado",
+DlgOpOther : "<Outro>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Por favor, insira a URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<non definido>",
+DlgGenId : "Id",
+DlgGenLangDir : "Orientación do Idioma",
+DlgGenLangDirLtr : "Esquerda a Dereita (LTR)",
+DlgGenLangDirRtl : "Dereita a Esquerda (RTL)",
+DlgGenLangCode : "Código do Idioma",
+DlgGenAccessKey : "Chave de Acceso",
+DlgGenName : "Nome",
+DlgGenTabIndex : "Índice de Tabulación",
+DlgGenLongDescr : "Descrición Completa da URL",
+DlgGenClass : "Clases da Folla de Estilos",
+DlgGenTitle : "Título",
+DlgGenContType : "Tipo de Contido",
+DlgGenLinkCharset : "Fonte de Caracteres Vinculado",
+DlgGenStyle : "Estilo",
+
+// Image Dialog
+DlgImgTitle : "Propriedades da Imaxe",
+DlgImgInfoTab : "Información da Imaxe",
+DlgImgBtnUpload : "Enviar ó Servidor",
+DlgImgURL : "URL",
+DlgImgUpload : "Carregar",
+DlgImgAlt : "Texto Alternativo",
+DlgImgWidth : "Largura",
+DlgImgHeight : "Altura",
+DlgImgLockRatio : "Proporcional",
+DlgBtnResetSize : "Tamaño Orixinal",
+DlgImgBorder : "Límite",
+DlgImgHSpace : "Esp. Horiz.",
+DlgImgVSpace : "Esp. Vert.",
+DlgImgAlign : "Aliñamento",
+DlgImgAlignLeft : "Esquerda",
+DlgImgAlignAbsBottom: "Abs Inferior",
+DlgImgAlignAbsMiddle: "Abs Centro",
+DlgImgAlignBaseline : "Liña Base",
+DlgImgAlignBottom : "Pé",
+DlgImgAlignMiddle : "Centro",
+DlgImgAlignRight : "Dereita",
+DlgImgAlignTextTop : "Tope do Texto",
+DlgImgAlignTop : "Tope",
+DlgImgPreview : "Vista Previa",
+DlgImgAlertUrl : "Por favor, escriba a URL da imaxe",
+DlgImgLinkTab : "Ligazón",
+
+// Flash Dialog
+DlgFlashTitle : "Propriedades Flash",
+DlgFlashChkPlay : "Auto Execución",
+DlgFlashChkLoop : "Bucle",
+DlgFlashChkMenu : "Activar Menú Flash",
+DlgFlashScale : "Escalar",
+DlgFlashScaleAll : "Amosar Todo",
+DlgFlashScaleNoBorder : "Sen Borde",
+DlgFlashScaleFit : "Encaixar axustando",
+
+// Link Dialog
+DlgLnkWindowTitle : "Ligazón",
+DlgLnkInfoTab : "Información da Ligazón",
+DlgLnkTargetTab : "Referencia a esta páxina",
+
+DlgLnkType : "Tipo de Ligazón",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Referencia nesta páxina",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocolo",
+DlgLnkProtoOther : "<outro>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Seleccionar unha Referencia",
+DlgLnkAnchorByName : "Por Nome de Referencia",
+DlgLnkAnchorById : "Por Element Id",
+DlgLnkNoAnchors : "<Non hai referencias disponibles no documento>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Enderezo de E-Mail",
+DlgLnkEMailSubject : "Asunto do Mensaxe",
+DlgLnkEMailBody : "Corpo do Mensaxe",
+DlgLnkUpload : "Carregar",
+DlgLnkBtnUpload : "Enviar ó servidor",
+
+DlgLnkTarget : "Destino",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<Xanela Emerxente>",
+DlgLnkTargetBlank : "Nova Xanela (_blank)",
+DlgLnkTargetParent : "Xanela Pai (_parent)",
+DlgLnkTargetSelf : "Mesma Xanela (_self)",
+DlgLnkTargetTop : "Xanela Primaria (_top)",
+DlgLnkTargetFrameName : "Nome do Marco Destino",
+DlgLnkPopWinName : "Nome da Xanela Emerxente",
+DlgLnkPopWinFeat : "Características da Xanela Emerxente",
+DlgLnkPopResize : "Axustable",
+DlgLnkPopLocation : "Barra de Localización",
+DlgLnkPopMenu : "Barra de Menú",
+DlgLnkPopScroll : "Barras de Desplazamento",
+DlgLnkPopStatus : "Barra de Estado",
+DlgLnkPopToolbar : "Barra de Ferramentas",
+DlgLnkPopFullScrn : "A Toda Pantalla (IE)",
+DlgLnkPopDependent : "Dependente (Netscape)",
+DlgLnkPopWidth : "Largura",
+DlgLnkPopHeight : "Altura",
+DlgLnkPopLeft : "Posición Esquerda",
+DlgLnkPopTop : "Posición dende Arriba",
+
+DlnLnkMsgNoUrl : "Por favor, escriba a ligazón URL",
+DlnLnkMsgNoEMail : "Por favor, escriba o enderezo de e-mail",
+DlnLnkMsgNoAnchor : "Por favor, seleccione un destino",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Seleccionar Color",
+DlgColorBtnClear : "Nengunha",
+DlgColorHighlight : "Destacado",
+DlgColorSelected : "Seleccionado",
+
+// Smiley Dialog
+DlgSmileyTitle : "Inserte un Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Seleccione Caracter Especial",
+
+// Table Dialog
+DlgTableTitle : "Propiedades da Táboa",
+DlgTableRows : "Filas",
+DlgTableColumns : "Columnas",
+DlgTableBorder : "Tamaño do Borde",
+DlgTableAlign : "Aliñamento",
+DlgTableAlignNotSet : "<Non Definido>",
+DlgTableAlignLeft : "Esquerda",
+DlgTableAlignCenter : "Centro",
+DlgTableAlignRight : "Ereita",
+DlgTableWidth : "Largura",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Altura",
+DlgTableCellSpace : "Marxe entre Celas",
+DlgTableCellPad : "Marxe interior",
+DlgTableCaption : "Título",
+DlgTableSummary : "Sumario",
+
+// Table Cell Dialog
+DlgCellTitle : "Propriedades da Cela",
+DlgCellWidth : "Largura",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Altura",
+DlgCellWordWrap : "Axustar Liñas",
+DlgCellWordWrapNotSet : "<Non Definido>",
+DlgCellWordWrapYes : "Si",
+DlgCellWordWrapNo : "Non",
+DlgCellHorAlign : "Aliñamento Horizontal",
+DlgCellHorAlignNotSet : "<Non definido>",
+DlgCellHorAlignLeft : "Esquerda",
+DlgCellHorAlignCenter : "Centro",
+DlgCellHorAlignRight: "Dereita",
+DlgCellVerAlign : "Aliñamento Vertical",
+DlgCellVerAlignNotSet : "<Non definido>",
+DlgCellVerAlignTop : "Arriba",
+DlgCellVerAlignMiddle : "Medio",
+DlgCellVerAlignBottom : "Abaixo",
+DlgCellVerAlignBaseline : "Liña de Base",
+DlgCellRowSpan : "Ocupar Filas",
+DlgCellCollSpan : "Ocupar Columnas",
+DlgCellBackColor : "Color de Fondo",
+DlgCellBorderColor : "Color de Borde",
+DlgCellBtnSelect : "Seleccionar...",
+
+// Find Dialog
+DlgFindTitle : "Procurar",
+DlgFindFindBtn : "Procurar",
+DlgFindNotFoundMsg : "Non te atopou o texto indicado.",
+
+// Replace Dialog
+DlgReplaceTitle : "Substituir",
+DlgReplaceFindLbl : "Texto a procurar:",
+DlgReplaceReplaceLbl : "Substituir con:",
+DlgReplaceCaseChk : "Coincidir Mai./min.",
+DlgReplaceReplaceBtn : "Substituir",
+DlgReplaceReplAllBtn : "Substitiur Todo",
+DlgReplaceWordChk : "Coincidir con toda a palabra",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Os axustes de seguridade do seu navegador non permiten que o editor realice automáticamente as tarefas de corte. Por favor, use o teclado para iso (Ctrl+X).",
+PasteErrorCopy : "Os axustes de seguridade do seu navegador non permiten que o editor realice automáticamente as tarefas de copia. Por favor, use o teclado para iso (Ctrl+C).",
+
+PasteAsText : "Pegar como texto plano",
+PasteFromWord : "Pegar dende Word",
+
+DlgPasteMsg2 : "Por favor, pegue dentro do seguinte cadro usando o teclado (<STRONG>Ctrl+V</STRONG>) e pulse <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorar as definicións de Tipografía",
+DlgPasteRemoveStyles : "Eliminar as definicións de Estilos",
+DlgPasteCleanBox : "Limpar o Cadro",
+
+// Color Picker
+ColorAutomatic : "Automático",
+ColorMoreColors : "Máis Cores...",
+
+// Document Properties
+DocProps : "Propriedades do Documento",
+
+// Anchor Dialog
+DlgAnchorTitle : "Propriedades da Referencia",
+DlgAnchorName : "Nome da Referencia",
+DlgAnchorErrorName : "Por favor, escriba o nome da referencia",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Non está no diccionario",
+DlgSpellChangeTo : "Cambiar a",
+DlgSpellBtnIgnore : "Ignorar",
+DlgSpellBtnIgnoreAll : "Ignorar Todas",
+DlgSpellBtnReplace : "Substituir",
+DlgSpellBtnReplaceAll : "Substituir Todas",
+DlgSpellBtnUndo : "Desfacer",
+DlgSpellNoSuggestions : "- Sen candidatos -",
+DlgSpellProgress : "Corrección ortográfica en progreso...",
+DlgSpellNoMispell : "Corrección ortográfica rematada: Non se atoparon erros",
+DlgSpellNoChanges : "Corrección ortográfica rematada: Non se substituiu nengunha verba",
+DlgSpellOneChange : "Corrección ortográfica rematada: Unha verba substituida",
+DlgSpellManyChanges : "Corrección ortográfica rematada: %1 verbas substituidas",
+
+IeSpellDownload : "O corrector ortográfico non está instalado. ¿Quere descargalo agora?",
+
+// Button Dialog
+DlgButtonText : "Texto (Valor)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nome",
+DlgCheckboxValue : "Valor",
+DlgCheckboxSelected : "Seleccionado",
+
+// Form Dialog
+DlgFormName : "Nome",
+DlgFormAction : "Acción",
+DlgFormMethod : "Método",
+
+// Select Field Dialog
+DlgSelectName : "Nome",
+DlgSelectValue : "Valor",
+DlgSelectSize : "Tamaño",
+DlgSelectLines : "liñas",
+DlgSelectChkMulti : "Permitir múltiples seleccións",
+DlgSelectOpAvail : "Opcións Disponibles",
+DlgSelectOpText : "Texto",
+DlgSelectOpValue : "Valor",
+DlgSelectBtnAdd : "Engadir",
+DlgSelectBtnModify : "Modificar",
+DlgSelectBtnUp : "Subir",
+DlgSelectBtnDown : "Baixar",
+DlgSelectBtnSetValue : "Definir como valor por defecto",
+DlgSelectBtnDelete : "Borrar",
+
+// Textarea Dialog
+DlgTextareaName : "Nome",
+DlgTextareaCols : "Columnas",
+DlgTextareaRows : "Filas",
+
+// Text Field Dialog
+DlgTextName : "Nome",
+DlgTextValue : "Valor",
+DlgTextCharWidth : "Tamaño do Caracter",
+DlgTextMaxChars : "Máximo de Caracteres",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Texto",
+DlgTextTypePass : "Chave",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nome",
+DlgHiddenValue : "Valor",
+
+// Bulleted List Dialog
+BulletedListProp : "Propriedades das Marcas",
+NumberedListProp : "Propriedades da Lista de Numeración",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Círculo",
+DlgLstTypeDisc : "Disco",
+DlgLstTypeSquare : "Cuadrado",
+DlgLstTypeNumbers : "Números (1, 2, 3)",
+DlgLstTypeLCase : "Letras Minúsculas (a, b, c)",
+DlgLstTypeUCase : "Letras Maiúsculas (A, B, C)",
+DlgLstTypeSRoman : "Números Romanos en minúscula (i, ii, iii)",
+DlgLstTypeLRoman : "Números Romanos en Maiúscula (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Xeral",
+DlgDocBackTab : "Fondo",
+DlgDocColorsTab : "Cores e Marxes",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Título da Páxina",
+DlgDocLangDir : "Orientación do Idioma",
+DlgDocLangDirLTR : "Esquerda a Dereita (LTR)",
+DlgDocLangDirRTL : "Dereita a Esquerda (RTL)",
+DlgDocLangCode : "Código de Idioma",
+DlgDocCharSet : "Codificación do Xogo de Caracteres",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Outra Codificación do Xogo de Caracteres",
+
+DlgDocDocType : "Encabezado do Tipo de Documento",
+DlgDocDocTypeOther : "Outro Encabezado do Tipo de Documento",
+DlgDocIncXHTML : "Incluir Declaracións XHTML",
+DlgDocBgColor : "Cor de Fondo",
+DlgDocBgImage : "URL da Imaxe de Fondo",
+DlgDocBgNoScroll : "Fondo Fixo",
+DlgDocCText : "Texto",
+DlgDocCLink : "Ligazóns",
+DlgDocCVisited : "Ligazón Visitada",
+DlgDocCActive : "Ligazón Activa",
+DlgDocMargins : "Marxes da Páxina",
+DlgDocMaTop : "Arriba",
+DlgDocMaLeft : "Esquerda",
+DlgDocMaRight : "Dereita",
+DlgDocMaBottom : "Abaixo",
+DlgDocMeIndex : "Palabras Chave de Indexación do Documento (separadas por comas)",
+DlgDocMeDescr : "Descripción do Documento",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Vista Previa",
+
+// Templates Dialog
+Templates : "Plantillas",
+DlgTemplatesTitle : "Plantillas de Contido",
+DlgTemplatesSelMsg : "Por favor, seleccione a plantilla a abrir no editor<br>(o contido actual perderase):",
+DlgTemplatesLoading : "Cargando listado de plantillas. Por favor, espere...",
+DlgTemplatesNoTpl : "(Non hai plantillas definidas)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Acerca de",
+DlgAboutBrowserInfoTab : "Información do Navegador",
+DlgAboutLicenseTab : "Licencia",
+DlgAboutVersion : "versión",
+DlgAboutInfo : "Para máis información visitar:"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/he.js b/httemplate/elements/fckeditor/editor/lang/he.js
new file mode 100644
index 000000000..ef2b9792b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/he.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Hebrew language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "rtl",
+
+ToolbarCollapse : "כיווץ סרגל הכלים",
+ToolbarExpand : "פתיחת סרגל הכלים",
+
+// Toolbar Items and Context Menu
+Save : "שמירה",
+NewPage : "דף חדש",
+Preview : "תצוגה מקדימה",
+Cut : "גזירה",
+Copy : "העתקה",
+Paste : "הדבקה",
+PasteText : "הדבקה כטקסט פשוט",
+PasteWord : "הדבקה מ-וורד",
+Print : "הדפסה",
+SelectAll : "בחירת הכל",
+RemoveFormat : "הסרת העיצוב",
+InsertLinkLbl : "קישור",
+InsertLink : "הוספת/עריכת קישור",
+RemoveLink : "הסרת הקישור",
+Anchor : "הוספת/עריכת נקודת עיגון",
+InsertImageLbl : "תמונה",
+InsertImage : "הוספת/עריכת תמונה",
+InsertFlashLbl : "פלאש",
+InsertFlash : "הוסף/ערוך פלאש",
+InsertTableLbl : "טבלה",
+InsertTable : "הוספת/עריכת טבלה",
+InsertLineLbl : "קו",
+InsertLine : "הוספת קו אופקי",
+InsertSpecialCharLbl: "תו מיוחד",
+InsertSpecialChar : "הוספת תו מיוחד",
+InsertSmileyLbl : "סמיילי",
+InsertSmiley : "הוספת סמיילי",
+About : "אודות FCKeditor",
+Bold : "מודגש",
+Italic : "נטוי",
+Underline : "קו תחתון",
+StrikeThrough : "כתיב מחוק",
+Subscript : "כתיב תחתון",
+Superscript : "כתיב עליון",
+LeftJustify : "יישור לשמאל",
+CenterJustify : "מרכוז",
+RightJustify : "יישור לימין",
+BlockJustify : "יישור לשוליים",
+DecreaseIndent : "הקטנת אינדנטציה",
+IncreaseIndent : "הגדלת אינדנטציה",
+Undo : "ביטול צעד אחרון",
+Redo : "חזרה על צעד אחרון",
+NumberedListLbl : "רשימה ממוספרת",
+NumberedList : "הוספת/הסרת רשימה ממוספרת",
+BulletedListLbl : "רשימת נקודות",
+BulletedList : "הוספת/הסרת רשימת נקודות",
+ShowTableBorders : "הצגת מסגרת הטבלה",
+ShowDetails : "הצגת פרטים",
+Style : "סגנון",
+FontFormat : "עיצוב",
+Font : "גופן",
+FontSize : "גודל",
+TextColor : "צבע טקסט",
+BGColor : "צבע רקע",
+Source : "מקור",
+Find : "חיפוש",
+Replace : "החלפה",
+SpellCheck : "בדיקת איות",
+UniversalKeyboard : "מקלדת אוניברסלית",
+PageBreakLbl : "שבירת דף",
+PageBreak : "הוסף שבירת דף",
+
+Form : "טופס",
+Checkbox : "תיבת סימון",
+RadioButton : "לחצן אפשרויות",
+TextField : "שדה טקסט",
+Textarea : "איזור טקסט",
+HiddenField : "שדה חבוי",
+Button : "כפתור",
+SelectionField : "שדה בחירה",
+ImageButton : "כפתור תמונה",
+
+FitWindow : "הגדל את גודל העורך",
+
+// Context Menu
+EditLink : "עריכת קישור",
+CellCM : "תא",
+RowCM : "שורה",
+ColumnCM : "עמודה",
+InsertRow : "הוספת שורה",
+DeleteRows : "מחיקת שורות",
+InsertColumn : "הוספת עמודה",
+DeleteColumns : "מחיקת עמודות",
+InsertCell : "הוספת תא",
+DeleteCells : "מחיקת תאים",
+MergeCells : "מיזוג תאים",
+SplitCell : "פיצול תאים",
+TableDelete : "מחק טבלה",
+CellProperties : "תכונות התא",
+TableProperties : "תכונות הטבלה",
+ImageProperties : "תכונות התמונה",
+FlashProperties : "מאפייני פלאש",
+
+AnchorProp : "מאפייני נקודת עיגון",
+ButtonProp : "מאפייני כפתור",
+CheckboxProp : "מאפייני תיבת סימון",
+HiddenFieldProp : "מאפיני שדה חבוי",
+RadioButtonProp : "מאפייני לחצן אפשרויות",
+ImageButtonProp : "מאפיני כפתור תמונה",
+TextFieldProp : "מאפייני שדה טקסט",
+SelectionFieldProp : "מאפייני שדה בחירה",
+TextareaProp : "מאפיני איזור טקסט",
+FormProp : "מאפיני טופס",
+
+FontFormats : "נורמלי;קוד;כתובת;כותרת;כותרת 2;כותרת 3;כותרת 4;כותרת 5;כותרת 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "מעבד XHTML, נא להמתין...",
+Done : "המשימה הושלמה",
+PasteWordConfirm : "נראה הטקסט שבכוונתך להדביק מקורו בקובץ וורד. האם ברצונך לנקות אותו טרם ההדבקה?",
+NotCompatiblePaste : "פעולה זו זמינה לדפדפן אינטרנט אקספלורר מגירסא 5.5 ומעלה. האם להמשיך בהדבקה ללא הניקוי?",
+UnknownToolbarItem : "פריט לא ידוע בסרגל הכלים \"%1\"",
+UnknownCommand : "שם פעולה לא ידוע \"%1\"",
+NotImplemented : "הפקודה לא מיושמת",
+UnknownToolbarSet : "ערכת סרגל הכלים \"%1\" לא קיימת",
+NoActiveX : "הגדרות אבטחה של הדפדפן עלולות לגביל את אפשרויות העריכה.יש לאפשר את האופציה \"הרץ פקדים פעילים ותוספות\". תוכל לחוות טעויות וחיווים של אפשרויות שחסרים.",
+BrowseServerBlocked : "לא ניתן לגשת לדפדפן משאבים.אנא וודא שחוסם חלונות הקופצים לא פעיל.",
+DialogBlocked : "לא היה ניתן לפתוח חלון דיאלוג. אנא וודא שחוסם חלונות קופצים לא פעיל.",
+
+// Dialogs
+DlgBtnOK : "אישור",
+DlgBtnCancel : "ביטול",
+DlgBtnClose : "סגירה",
+DlgBtnBrowseServer : "סייר השרת",
+DlgAdvancedTag : "אפשרויות מתקדמות",
+DlgOpOther : "<אחר>",
+DlgInfoTab : "מידע",
+DlgAlertUrl : "אנה הזן URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<לא נקבע>",
+DlgGenId : "זיהוי (Id)",
+DlgGenLangDir : "כיוון שפה",
+DlgGenLangDirLtr : "שמאל לימין (LTR)",
+DlgGenLangDirRtl : "ימין לשמאל (RTL)",
+DlgGenLangCode : "קוד שפה",
+DlgGenAccessKey : "מקש גישה",
+DlgGenName : "שם",
+DlgGenTabIndex : "מספר טאב",
+DlgGenLongDescr : "קישור לתיאור מפורט",
+DlgGenClass : "גיליונות עיצוב קבוצות",
+DlgGenTitle : "כותרת מוצעת",
+DlgGenContType : "Content Type מוצע",
+DlgGenLinkCharset : "קידוד המשאב המקושר",
+DlgGenStyle : "סגנון",
+
+// Image Dialog
+DlgImgTitle : "תכונות התמונה",
+DlgImgInfoTab : "מידע על התמונה",
+DlgImgBtnUpload : "שליחה לשרת",
+DlgImgURL : "כתובת (URL)",
+DlgImgUpload : "העלאה",
+DlgImgAlt : "טקסט חלופי",
+DlgImgWidth : "רוחב",
+DlgImgHeight : "גובה",
+DlgImgLockRatio : "נעילת היחס",
+DlgBtnResetSize : "איפוס הגודל",
+DlgImgBorder : "מסגרת",
+DlgImgHSpace : "מרווח אופקי",
+DlgImgVSpace : "מרווח אנכי",
+DlgImgAlign : "יישור",
+DlgImgAlignLeft : "לשמאל",
+DlgImgAlignAbsBottom: "לתחתית האבסולוטית",
+DlgImgAlignAbsMiddle: "מרכוז אבסולוטי",
+DlgImgAlignBaseline : "לקו התחתית",
+DlgImgAlignBottom : "לתחתית",
+DlgImgAlignMiddle : "לאמצע",
+DlgImgAlignRight : "לימין",
+DlgImgAlignTextTop : "לראש הטקסט",
+DlgImgAlignTop : "למעלה",
+DlgImgPreview : "תצוגה מקדימה",
+DlgImgAlertUrl : "נא להקליד את כתובת התמונה",
+DlgImgLinkTab : "קישור",
+
+// Flash Dialog
+DlgFlashTitle : "מאפיני פלאש",
+DlgFlashChkPlay : "נגן אוטומטי",
+DlgFlashChkLoop : "לולאה",
+DlgFlashChkMenu : "אפשר תפריט פלאש",
+DlgFlashScale : "גודל",
+DlgFlashScaleAll : "הצג הכל",
+DlgFlashScaleNoBorder : "ללא גבולות",
+DlgFlashScaleFit : "התאמה מושלמת",
+
+// Link Dialog
+DlgLnkWindowTitle : "קישור",
+DlgLnkInfoTab : "מידע על הקישור",
+DlgLnkTargetTab : "מטרה",
+
+DlgLnkType : "סוג קישור",
+DlgLnkTypeURL : "כתובת (URL)",
+DlgLnkTypeAnchor : "עוגן בעמוד זה",
+DlgLnkTypeEMail : "דוא''ל",
+DlgLnkProto : "פרוטוקול",
+DlgLnkProtoOther : "<אחר>",
+DlgLnkURL : "כתובת (URL)",
+DlgLnkAnchorSel : "בחירת עוגן",
+DlgLnkAnchorByName : "עפ''י שם העוגן",
+DlgLnkAnchorById : "עפ''י זיהוי (Id) הרכיב",
+DlgLnkNoAnchors : "(אין עוגנים זמינים בדף)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "כתובת הדוא''ל",
+DlgLnkEMailSubject : "נושא ההודעה",
+DlgLnkEMailBody : "גוף ההודעה",
+DlgLnkUpload : "העלאה",
+DlgLnkBtnUpload : "שליחה לשרת",
+
+DlgLnkTarget : "מטרה",
+DlgLnkTargetFrame : "<מסגרת>",
+DlgLnkTargetPopup : "<חלון קופץ>",
+DlgLnkTargetBlank : "חלון חדש (_blank)",
+DlgLnkTargetParent : "חלון האב (_parent)",
+DlgLnkTargetSelf : "באותו החלון (_self)",
+DlgLnkTargetTop : "חלון ראשי (_top)",
+DlgLnkTargetFrameName : "שם מסגרת היעד",
+DlgLnkPopWinName : "שם החלון הקופץ",
+DlgLnkPopWinFeat : "תכונות החלון הקופץ",
+DlgLnkPopResize : "בעל גודל ניתן לשינוי",
+DlgLnkPopLocation : "סרגל כתובת",
+DlgLnkPopMenu : "סרגל תפריט",
+DlgLnkPopScroll : "ניתן לגלילה",
+DlgLnkPopStatus : "סרגל חיווי",
+DlgLnkPopToolbar : "סרגל הכלים",
+DlgLnkPopFullScrn : "מסך מלא (IE)",
+DlgLnkPopDependent : "תלוי (Netscape)",
+DlgLnkPopWidth : "רוחב",
+DlgLnkPopHeight : "גובה",
+DlgLnkPopLeft : "מיקום צד שמאל",
+DlgLnkPopTop : "מיקום צד עליון",
+
+DlnLnkMsgNoUrl : "נא להקליד את כתובת הקישור (URL)",
+DlnLnkMsgNoEMail : "נא להקליד את כתובת הדוא''ל",
+DlnLnkMsgNoAnchor : "נא לבחור עוגן במסמך",
+DlnLnkMsgInvPopName : "שם החלון הקופץ חייב להתחיל באותיות ואסור לכלול רווחים",
+
+// Color Dialog
+DlgColorTitle : "בחירת צבע",
+DlgColorBtnClear : "איפוס",
+DlgColorHighlight : "נוכחי",
+DlgColorSelected : "נבחר",
+
+// Smiley Dialog
+DlgSmileyTitle : "הוספת סמיילי",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "בחירת תו מיוחד",
+
+// Table Dialog
+DlgTableTitle : "תכונות טבלה",
+DlgTableRows : "שורות",
+DlgTableColumns : "עמודות",
+DlgTableBorder : "גודל מסגרת",
+DlgTableAlign : "יישור",
+DlgTableAlignNotSet : "<לא נקבע>",
+DlgTableAlignLeft : "שמאל",
+DlgTableAlignCenter : "מרכז",
+DlgTableAlignRight : "ימין",
+DlgTableWidth : "רוחב",
+DlgTableWidthPx : "פיקסלים",
+DlgTableWidthPc : "אחוז",
+DlgTableHeight : "גובה",
+DlgTableCellSpace : "מרווח תא",
+DlgTableCellPad : "ריפוד תא",
+DlgTableCaption : "כיתוב",
+DlgTableSummary : "סיכום",
+
+// Table Cell Dialog
+DlgCellTitle : "תכונות תא",
+DlgCellWidth : "רוחב",
+DlgCellWidthPx : "פיקסלים",
+DlgCellWidthPc : "אחוז",
+DlgCellHeight : "גובה",
+DlgCellWordWrap : "גלילת שורות",
+DlgCellWordWrapNotSet : "<לא נקבע>",
+DlgCellWordWrapYes : "כן",
+DlgCellWordWrapNo : "לא",
+DlgCellHorAlign : "יישור אופקי",
+DlgCellHorAlignNotSet : "<לא נקבע>",
+DlgCellHorAlignLeft : "שמאל",
+DlgCellHorAlignCenter : "מרכז",
+DlgCellHorAlignRight: "ימין",
+DlgCellVerAlign : "יישור אנכי",
+DlgCellVerAlignNotSet : "<לא נקבע>",
+DlgCellVerAlignTop : "למעלה",
+DlgCellVerAlignMiddle : "לאמצע",
+DlgCellVerAlignBottom : "לתחתית",
+DlgCellVerAlignBaseline : "קו תחתית",
+DlgCellRowSpan : "טווח שורות",
+DlgCellCollSpan : "טווח עמודות",
+DlgCellBackColor : "צבע רקע",
+DlgCellBorderColor : "צבע מסגרת",
+DlgCellBtnSelect : "בחירה...",
+
+// Find Dialog
+DlgFindTitle : "חיפוש",
+DlgFindFindBtn : "חיפוש",
+DlgFindNotFoundMsg : "הטקסט המבוקש לא נמצא.",
+
+// Replace Dialog
+DlgReplaceTitle : "החלפה",
+DlgReplaceFindLbl : "חיפוש מחרוזת:",
+DlgReplaceReplaceLbl : "החלפה במחרוזת:",
+DlgReplaceCaseChk : "התאמת סוג אותיות (Case)",
+DlgReplaceReplaceBtn : "החלפה",
+DlgReplaceReplAllBtn : "החלפה בכל העמוד",
+DlgReplaceWordChk : "התאמה למילה המלאה",
+
+// Paste Operations / Dialog
+PasteErrorCut : "הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות גזירה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl+X).",
+PasteErrorCopy : "הגדרות האבטחה בדפדפן שלך לא מאפשרות לעורך לבצע פעולות העתקה אוטומטיות. יש להשתמש במקלדת לשם כך (Ctrl+C).",
+
+PasteAsText : "הדבקה כטקסט פשוט",
+PasteFromWord : "הדבקה מ-וורד",
+
+DlgPasteMsg2 : "אנא הדבק בתוך הקופסה באמצעות (<STRONG>Ctrl+V</STRONG>) ולחץ על <STRONG>אישור</STRONG>.",
+DlgPasteSec : "עקב הגדרות אבטחה בדפדפן, לא ניתן לגשת אל לוח הגזירים (clipboard) בצורה ישירה.אנא בצע הדבק שוב בחלון זה.",
+DlgPasteIgnoreFont : "התעלם מהגדרות סוג פונט",
+DlgPasteRemoveStyles : "הסר הגדרות סגנון",
+DlgPasteCleanBox : "ניקוי קופסה",
+
+// Color Picker
+ColorAutomatic : "אוטומטי",
+ColorMoreColors : "צבעים נוספים...",
+
+// Document Properties
+DocProps : "מאפיני מסמך",
+
+// Anchor Dialog
+DlgAnchorTitle : "מאפיני נקודת עיגון",
+DlgAnchorName : "שם לנקודת עיגון",
+DlgAnchorErrorName : "אנא הזן שם לנקודת עיגון",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "לא נמצא במילון",
+DlgSpellChangeTo : "שנה ל",
+DlgSpellBtnIgnore : "התעלם",
+DlgSpellBtnIgnoreAll : "התעלם מהכל",
+DlgSpellBtnReplace : "החלף",
+DlgSpellBtnReplaceAll : "החלף הכל",
+DlgSpellBtnUndo : "החזר",
+DlgSpellNoSuggestions : "- אין הצעות -",
+DlgSpellProgress : "בדיקות איות בתהליך ....",
+DlgSpellNoMispell : "בדיקות איות הסתיימה: לא נמצאו שגיעות כתיב",
+DlgSpellNoChanges : "בדיקות איות הסתיימה: לא שונתה אף מילה",
+DlgSpellOneChange : "בדיקות איות הסתיימה: שונתה מילה אחת",
+DlgSpellManyChanges : "בדיקות איות הסתיימה: %1 מילים שונו",
+
+IeSpellDownload : "בודק האיות לא מותקן, האם אתה מעוניין להוריד?",
+
+// Button Dialog
+DlgButtonText : "טקסט (ערך)",
+DlgButtonType : "סוג",
+DlgButtonTypeBtn : "כפתור",
+DlgButtonTypeSbm : "שלח",
+DlgButtonTypeRst : "אפס",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "שם",
+DlgCheckboxValue : "ערך",
+DlgCheckboxSelected : "בחור",
+
+// Form Dialog
+DlgFormName : "שם",
+DlgFormAction : "שלח אל",
+DlgFormMethod : "סוג שליחה",
+
+// Select Field Dialog
+DlgSelectName : "שם",
+DlgSelectValue : "ערך",
+DlgSelectSize : "גודל",
+DlgSelectLines : "שורות",
+DlgSelectChkMulti : "אפשר בחירות מרובות",
+DlgSelectOpAvail : "אפשרויות זמינות",
+DlgSelectOpText : "טקסט",
+DlgSelectOpValue : "ערך",
+DlgSelectBtnAdd : "הוסף",
+DlgSelectBtnModify : "שנה",
+DlgSelectBtnUp : "למעלה",
+DlgSelectBtnDown : "למטה",
+DlgSelectBtnSetValue : "קבע כברירת מחדל",
+DlgSelectBtnDelete : "מחק",
+
+// Textarea Dialog
+DlgTextareaName : "שם",
+DlgTextareaCols : "עמודות",
+DlgTextareaRows : "שורות",
+
+// Text Field Dialog
+DlgTextName : "שם",
+DlgTextValue : "ערך",
+DlgTextCharWidth : "רוחב באותיות",
+DlgTextMaxChars : "מקסימות אותיות",
+DlgTextType : "סוג",
+DlgTextTypeText : "טקסט",
+DlgTextTypePass : "סיסמה",
+
+// Hidden Field Dialog
+DlgHiddenName : "שם",
+DlgHiddenValue : "ערך",
+
+// Bulleted List Dialog
+BulletedListProp : "מאפייני רשימה",
+NumberedListProp : "מאפייני רשימה ממוספרת",
+DlgLstStart : "התחלה",
+DlgLstType : "סוג",
+DlgLstTypeCircle : "עיגול",
+DlgLstTypeDisc : "דיסק",
+DlgLstTypeSquare : "מרובע",
+DlgLstTypeNumbers : "מספרים (1, 2, 3)",
+DlgLstTypeLCase : "אותיות קטנות (a, b, c)",
+DlgLstTypeUCase : "אותיות גדולות (A, B, C)",
+DlgLstTypeSRoman : "ספרות רומאיות קטנות (i, ii, iii)",
+DlgLstTypeLRoman : "ספרות רומאיות גדולות (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "כללי",
+DlgDocBackTab : "רקע",
+DlgDocColorsTab : "צבעים וגבולות",
+DlgDocMetaTab : "נתוני META",
+
+DlgDocPageTitle : "כותרת דף",
+DlgDocLangDir : "כיוון שפה",
+DlgDocLangDirLTR : "שמאל לימין (LTR)",
+DlgDocLangDirRTL : "ימין לשמאל (RTL)",
+DlgDocLangCode : "קוד שפה",
+DlgDocCharSet : "קידוד אותיות",
+DlgDocCharSetCE : "מרכז אירופה",
+DlgDocCharSetCT : "סיני מסורתי (Big5)",
+DlgDocCharSetCR : "קירילי",
+DlgDocCharSetGR : "יוונית",
+DlgDocCharSetJP : "יפנית",
+DlgDocCharSetKR : "קוראנית",
+DlgDocCharSetTR : "טורקית",
+DlgDocCharSetUN : "יוני קוד (UTF-8)",
+DlgDocCharSetWE : "מערב אירופה",
+DlgDocCharSetOther : "קידוד אותיות אחר",
+
+DlgDocDocType : "הגדרות סוג מסמך",
+DlgDocDocTypeOther : "הגדרות סוג מסמך אחרות",
+DlgDocIncXHTML : "כלול הגדרות XHTML",
+DlgDocBgColor : "צבע רקע",
+DlgDocBgImage : "URL לתמונת רקע",
+DlgDocBgNoScroll : "רגע ללא גלילה",
+DlgDocCText : "טקסט",
+DlgDocCLink : "קישור",
+DlgDocCVisited : "קישור שבוקר",
+DlgDocCActive : " קישור פעיל",
+DlgDocMargins : "גבולות דף",
+DlgDocMaTop : "למעלה",
+DlgDocMaLeft : "שמאלה",
+DlgDocMaRight : "ימינה",
+DlgDocMaBottom : "למטה",
+DlgDocMeIndex : "מפתח עניינים של המסמך )מופרד בפסיק(",
+DlgDocMeDescr : "תאור מסמך",
+DlgDocMeAuthor : "מחבר",
+DlgDocMeCopy : "זכויות יוצרים",
+DlgDocPreview : "תצוגה מקדימה",
+
+// Templates Dialog
+Templates : "תבניות",
+DlgTemplatesTitle : "תביות תוכן",
+DlgTemplatesSelMsg : "אנא בחר תבנית לפתיחה בעורך <BR>התוכן המקורי ימחק:",
+DlgTemplatesLoading : "מעלה רשימת תבניות אנא המתן",
+DlgTemplatesNoTpl : "(לא הוגדרו תבניות)",
+DlgTemplatesReplace : "החלפת תוכן ממשי",
+
+// About Dialog
+DlgAboutAboutTab : "אודות",
+DlgAboutBrowserInfoTab : "גירסת דפדפן",
+DlgAboutLicenseTab : "רשיון",
+DlgAboutVersion : "גירסא",
+DlgAboutInfo : "מידע נוסף ניתן למצוא כאן:"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/hi.js b/httemplate/elements/fckeditor/editor/lang/hi.js
new file mode 100644
index 000000000..fdc5e39e5
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/hi.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Hindi language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "टूलबार सिमटायें",
+ToolbarExpand : "टूलबार का विस्तार करें",
+
+// Toolbar Items and Context Menu
+Save : "सेव",
+NewPage : "नया पेज",
+Preview : "प्रीव्यू",
+Cut : "कट",
+Copy : "कॉपी",
+Paste : "पेस्ट",
+PasteText : "पेस्ट (सादा टॅक्स्ट)",
+PasteWord : "पेस्ट (वर्ड से)",
+Print : "प्रिन्ट",
+SelectAll : "सब सॅलॅक्ट करें",
+RemoveFormat : "फ़ॉर्मैट हटायें",
+InsertLinkLbl : "लिंक",
+InsertLink : "लिंक इन्सर्ट/संपादन",
+RemoveLink : "लिंक हटायें",
+Anchor : "ऐंकर इन्सर्ट/संपादन",
+InsertImageLbl : "तस्वीर",
+InsertImage : "तस्वीर इन्सर्ट/संपादन",
+InsertFlashLbl : "फ़्लैश",
+InsertFlash : "फ़्लैश इन्सर्ट/संपादन",
+InsertTableLbl : "टेबल",
+InsertTable : "टेबल इन्सर्ट/संपादन",
+InsertLineLbl : "रेखा",
+InsertLine : "हॉरिज़ॉन्टल रेखा इन्सर्ट करें",
+InsertSpecialCharLbl: "विशेष करॅक्टर",
+InsertSpecialChar : "विशेष करॅक्टर इन्सर्ट करें",
+InsertSmileyLbl : "स्माइली",
+InsertSmiley : "स्माइली इन्सर्ट करें",
+About : "FCKeditor के बारे में",
+Bold : "बोल्ड",
+Italic : "इटैलिक",
+Underline : "रेखांकण",
+StrikeThrough : "स्ट्राइक थ्रू",
+Subscript : "अधोलेख",
+Superscript : "अभिलेख",
+LeftJustify : "बायीं तरफ",
+CenterJustify : "बीच में",
+RightJustify : "दायीं तरफ",
+BlockJustify : "ब्लॉक जस्टीफ़ाई",
+DecreaseIndent : "इन्डॅन्ट कम करें",
+IncreaseIndent : "इन्डॅन्ट बढ़ायें",
+Undo : "अन्डू",
+Redo : "रीडू",
+NumberedListLbl : "अंकीय सूची",
+NumberedList : "अंकीय सूची इन्सर्ट/संपादन",
+BulletedListLbl : "बुलॅट सूची",
+BulletedList : "बुलॅट सूची इन्सर्ट/संपादन",
+ShowTableBorders : "टेबल बॉर्डरयें दिखायें",
+ShowDetails : "ज्यादा दिखायें",
+Style : "स्टाइल",
+FontFormat : "फ़ॉर्मैट",
+Font : "फ़ॉन्ट",
+FontSize : "साइज़",
+TextColor : "टेक्स्ट रंग",
+BGColor : "बैक्ग्राउन्ड रंग",
+Source : "सोर्स",
+Find : "खोजें",
+Replace : "रीप्लेस",
+SpellCheck : "वर्तनी (स्पेलिंग) जाँच",
+UniversalKeyboard : "यूनीवर्सल कीबोर्ड",
+PageBreakLbl : "पेज ब्रेक",
+PageBreak : "पेज ब्रेक इन्सर्ट् करें",
+
+Form : "फ़ॉर्म",
+Checkbox : "चॅक बॉक्स",
+RadioButton : "रेडिओ बटन",
+TextField : "टेक्स्ट फ़ील्ड",
+Textarea : "टेक्स्ट एरिया",
+HiddenField : "गुप्त फ़ील्ड",
+Button : "बटन",
+SelectionField : "चुनाव फ़ील्ड",
+ImageButton : "तस्वीर बटन",
+
+FitWindow : "एडिटर साइज़ को चरम सीमा तक बढ़ायें",
+
+// Context Menu
+EditLink : "लिंक संपादन",
+CellCM : "खाना",
+RowCM : "पंक्ति",
+ColumnCM : "कालम",
+InsertRow : "पंक्ति इन्सर्ट करें",
+DeleteRows : "पंक्तियाँ डिलीट करें",
+InsertColumn : "कॉलम इन्सर्ट करें",
+DeleteColumns : "कॉलम डिलीट करें",
+InsertCell : "सॅल इन्सर्ट करें",
+DeleteCells : "सॅल डिलीट करें",
+MergeCells : "सॅल मिलायें",
+SplitCell : "सॅल अलग करें",
+TableDelete : "टेबल डिलीट करें",
+CellProperties : "सॅल प्रॉपर्टीज़",
+TableProperties : "टेबल प्रॉपर्टीज़",
+ImageProperties : "तस्वीर प्रॉपर्टीज़",
+FlashProperties : "फ़्लैश प्रॉपर्टीज़",
+
+AnchorProp : "ऐंकर प्रॉपर्टीज़",
+ButtonProp : "बटन प्रॉपर्टीज़",
+CheckboxProp : "चॅक बॉक्स प्रॉपर्टीज़",
+HiddenFieldProp : "गुप्त फ़ील्ड प्रॉपर्टीज़",
+RadioButtonProp : "रेडिओ बटन प्रॉपर्टीज़",
+ImageButtonProp : "तस्वीर बटन प्रॉपर्टीज़",
+TextFieldProp : "टेक्स्ट फ़ील्ड प्रॉपर्टीज़",
+SelectionFieldProp : "चुनाव फ़ील्ड प्रॉपर्टीज़",
+TextareaProp : "टेक्स्त एरिया प्रॉपर्टीज़",
+FormProp : "फ़ॉर्म प्रॉपर्टीज़",
+
+FontFormats : "साधारण;फ़ॉर्मैटॅड;पता;शीर्षक 1;शीर्षक 2;शीर्षक 3;शीर्षक 4;शीर्षक 5;शीर्षक 6;शीर्षक (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML प्रोसॅस हो रहा है। ज़रा ठहरें...",
+Done : "पूरा हुआ",
+PasteWordConfirm : "आप जो टेक्स्ट पेस्ट करना चाहते हैं, वह वर्ड से कॉपी किया हुआ लग रहा है। क्या पेस्ट करने से पहले आप इसे साफ़ करना चाहेंगे?",
+NotCompatiblePaste : "यह कमांड इन्टरनॅट एक्स्प्लोरर(Internet Explorer) 5.5 या उसके बाद के वर्ज़न के लिए ही उपलब्ध है। क्या आप बिना साफ़ किए पेस्ट करना चाहेंगे?",
+UnknownToolbarItem : "अनजान टूलबार आइटम \"%1\"",
+UnknownCommand : "अनजान कमान्ड \"%1\"",
+NotImplemented : "कमान्ड इम्प्लीमॅन्ट नहीं किया गया है",
+UnknownToolbarSet : "टूलबार सॅट \"%1\" उपलब्ध नहीं है",
+NoActiveX : "आपके ब्राउज़र् की सुरक्शा सेटिंग्स् एडिटर की कुछ् फ़ीचरों को सीमित कर् सकती हैं। क्रिपया \"Run ActiveX controls and plug-ins\" विकल्प को एनेबल करें. आपको एरर्स् और गायब फ़ीचर्स् का अनुभव हो सकता है।",
+BrowseServerBlocked : "रिसोर्सेज़ ब्राउज़र् नहीं खोला जा सका। क्रिपया सभी पॉप्-अप् ब्लॉकर्स् को डिसेबल करें।",
+DialogBlocked : "डायलग विन्डो नहीं खोला जा सका। क्रिपया सभी पॉप्-अप् ब्लॉकर्स् को डिसेबल करें।",
+
+// Dialogs
+DlgBtnOK : "ठीक है",
+DlgBtnCancel : "रद्द करें",
+DlgBtnClose : "बन्द करें",
+DlgBtnBrowseServer : "सर्वर ब्राउज़ करें",
+DlgAdvancedTag : "ऍड्वान्स्ड",
+DlgOpOther : "<अन्य>",
+DlgInfoTab : "सूचना",
+DlgAlertUrl : "URL इन्सर्ट करें",
+
+// General Dialogs Labels
+DlgGenNotSet : "<सॅट नहीं>",
+DlgGenId : "Id",
+DlgGenLangDir : "भाषा लिखने की दिशा",
+DlgGenLangDirLtr : "बायें से दायें (LTR)",
+DlgGenLangDirRtl : "दायें से बायें (RTL)",
+DlgGenLangCode : "भाषा कोड",
+DlgGenAccessKey : "ऍक्सॅस की",
+DlgGenName : "नाम",
+DlgGenTabIndex : "टैब इन्डॅक्स",
+DlgGenLongDescr : "अधिक विवरण के लिए URL",
+DlgGenClass : "स्टाइल-शीट क्लास",
+DlgGenTitle : "परामर्श शीर्शक",
+DlgGenContType : "परामर्श कन्टॅन्ट प्रकार",
+DlgGenLinkCharset : "लिंक रिसोर्स करॅक्टर सॅट",
+DlgGenStyle : "स्टाइल",
+
+// Image Dialog
+DlgImgTitle : "तस्वीर प्रॉपर्टीज़",
+DlgImgInfoTab : "तस्वीर की जानकारी",
+DlgImgBtnUpload : "इसे सर्वर को भेजें",
+DlgImgURL : "URL",
+DlgImgUpload : "अपलोड",
+DlgImgAlt : "वैकल्पिक टेक्स्ट",
+DlgImgWidth : "चौड़ाई",
+DlgImgHeight : "ऊँचाई",
+DlgImgLockRatio : "लॉक अनुपात",
+DlgBtnResetSize : "रीसॅट साइज़",
+DlgImgBorder : "बॉर्डर",
+DlgImgHSpace : "हॉरिज़ॉन्टल स्पेस",
+DlgImgVSpace : "वर्टिकल स्पेस",
+DlgImgAlign : "ऍलाइन",
+DlgImgAlignLeft : "दायें",
+DlgImgAlignAbsBottom: "Abs नीचे",
+DlgImgAlignAbsMiddle: "Abs ऊपर",
+DlgImgAlignBaseline : "मूल रेखा",
+DlgImgAlignBottom : "नीचे",
+DlgImgAlignMiddle : "मध्य",
+DlgImgAlignRight : "दायें",
+DlgImgAlignTextTop : "टेक्स्ट ऊपर",
+DlgImgAlignTop : "ऊपर",
+DlgImgPreview : "प्रीव्यू",
+DlgImgAlertUrl : "तस्वीर का URL टाइप करें ",
+DlgImgLinkTab : "लिंक",
+
+// Flash Dialog
+DlgFlashTitle : "फ़्लैश प्रॉपर्टीज़",
+DlgFlashChkPlay : "ऑटो प्ले",
+DlgFlashChkLoop : "लूप",
+DlgFlashChkMenu : "फ़्लैश मॅन्यू का प्रयोग करें",
+DlgFlashScale : "स्केल",
+DlgFlashScaleAll : "सभी दिखायें",
+DlgFlashScaleNoBorder : "कोई बॉर्डर नहीं",
+DlgFlashScaleFit : "बिल्कुल फ़िट",
+
+// Link Dialog
+DlgLnkWindowTitle : "लिंक",
+DlgLnkInfoTab : "लिंक ",
+DlgLnkTargetTab : "टार्गेट",
+
+DlgLnkType : "लिंक प्रकार",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "इस पेज का ऐंकर",
+DlgLnkTypeEMail : "ई-मेल",
+DlgLnkProto : "प्रोटोकॉल",
+DlgLnkProtoOther : "<अन्य>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "ऐंकर चुनें",
+DlgLnkAnchorByName : "ऐंकर नाम से",
+DlgLnkAnchorById : "ऍलीमॅन्ट Id से",
+DlgLnkNoAnchors : "<डॉक्यूमॅन्ट में ऐंकर्स की संख्या>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "ई-मेल पता",
+DlgLnkEMailSubject : "संदेश विषय",
+DlgLnkEMailBody : "संदेश",
+DlgLnkUpload : "अपलोड",
+DlgLnkBtnUpload : "इसे सर्वर को भेजें",
+
+DlgLnkTarget : "टार्गेट",
+DlgLnkTargetFrame : "<फ़्रेम>",
+DlgLnkTargetPopup : "<पॉप-अप विन्डो>",
+DlgLnkTargetBlank : "नया विन्डो (_blank)",
+DlgLnkTargetParent : "मूल विन्डो (_parent)",
+DlgLnkTargetSelf : "इसी विन्डो (_self)",
+DlgLnkTargetTop : "शीर्ष विन्डो (_top)",
+DlgLnkTargetFrameName : "टार्गेट फ़्रेम का नाम",
+DlgLnkPopWinName : "पॉप-अप विन्डो का नाम",
+DlgLnkPopWinFeat : "पॉप-अप विन्डो फ़ीचर्स",
+DlgLnkPopResize : "साइज़ बदला जा सकता है",
+DlgLnkPopLocation : "लोकेशन बार",
+DlgLnkPopMenu : "मॅन्यू बार",
+DlgLnkPopScroll : "स्क्रॉल बार",
+DlgLnkPopStatus : "स्टेटस बार",
+DlgLnkPopToolbar : "टूल बार",
+DlgLnkPopFullScrn : "फ़ुल स्क्रीन (IE)",
+DlgLnkPopDependent : "डिपेन्डॅन्ट (Netscape)",
+DlgLnkPopWidth : "चौड़ाई",
+DlgLnkPopHeight : "ऊँचाई",
+DlgLnkPopLeft : "बायीं तरफ",
+DlgLnkPopTop : "दायीं तरफ",
+
+DlnLnkMsgNoUrl : "लिंक URL टाइप करें",
+DlnLnkMsgNoEMail : "ई-मेल पता टाइप करें",
+DlnLnkMsgNoAnchor : "ऐंकर चुनें",
+DlnLnkMsgInvPopName : "पॉप-अप का नाम अल्फाबेट से शुरू होना चाहिये और उसमें स्पेस नहीं होने चाहिए",
+
+// Color Dialog
+DlgColorTitle : "रंग चुनें",
+DlgColorBtnClear : "साफ़ करें",
+DlgColorHighlight : "हाइलाइट",
+DlgColorSelected : "सॅलॅक्टॅड",
+
+// Smiley Dialog
+DlgSmileyTitle : "स्माइली इन्सर्ट करें",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "विशेष करॅक्टर चुनें",
+
+// Table Dialog
+DlgTableTitle : "टेबल प्रॉपर्टीज़",
+DlgTableRows : "पंक्तियाँ",
+DlgTableColumns : "कॉलम",
+DlgTableBorder : "बॉर्डर साइज़",
+DlgTableAlign : "ऍलाइन्मॅन्ट",
+DlgTableAlignNotSet : "<सॅट नहीं>",
+DlgTableAlignLeft : "दायें",
+DlgTableAlignCenter : "बीच में",
+DlgTableAlignRight : "बायें",
+DlgTableWidth : "चौड़ाई",
+DlgTableWidthPx : "पिक्सॅल",
+DlgTableWidthPc : "प्रतिशत",
+DlgTableHeight : "ऊँचाई",
+DlgTableCellSpace : "सॅल अंतर",
+DlgTableCellPad : "सॅल पैडिंग",
+DlgTableCaption : "शीर्षक",
+DlgTableSummary : "सारांश",
+
+// Table Cell Dialog
+DlgCellTitle : "सॅल प्रॉपर्टीज़",
+DlgCellWidth : "चौड़ाई",
+DlgCellWidthPx : "पिक्सॅल",
+DlgCellWidthPc : "प्रतिशत",
+DlgCellHeight : "ऊँचाई",
+DlgCellWordWrap : "वर्ड रैप",
+DlgCellWordWrapNotSet : "<सॅट नहीं>",
+DlgCellWordWrapYes : "हाँ",
+DlgCellWordWrapNo : "नहीं",
+DlgCellHorAlign : "हॉरिज़ॉन्टल ऍलाइन्मॅन्ट",
+DlgCellHorAlignNotSet : "<सॅट नहीं>",
+DlgCellHorAlignLeft : "दायें",
+DlgCellHorAlignCenter : "बीच में",
+DlgCellHorAlignRight: "बायें",
+DlgCellVerAlign : "वर्टिकल ऍलाइन्मॅन्ट",
+DlgCellVerAlignNotSet : "<सॅट नहीं>",
+DlgCellVerAlignTop : "ऊपर",
+DlgCellVerAlignMiddle : "मध्य",
+DlgCellVerAlignBottom : "नीचे",
+DlgCellVerAlignBaseline : "मूलरेखा",
+DlgCellRowSpan : "पंक्ति स्पैन",
+DlgCellCollSpan : "कॉलम स्पैन",
+DlgCellBackColor : "बैक्ग्राउन्ड रंग",
+DlgCellBorderColor : "बॉर्डर का रंग",
+DlgCellBtnSelect : "चुनें...",
+
+// Find Dialog
+DlgFindTitle : "खोजें",
+DlgFindFindBtn : "खोजें",
+DlgFindNotFoundMsg : "आपके द्वारा दिया गया टेक्स्ट नहीं मिला",
+
+// Replace Dialog
+DlgReplaceTitle : "रिप्लेस",
+DlgReplaceFindLbl : "यह खोजें:",
+DlgReplaceReplaceLbl : "इससे रिप्लेस करें:",
+DlgReplaceCaseChk : "केस मिलायें",
+DlgReplaceReplaceBtn : "रिप्लेस",
+DlgReplaceReplAllBtn : "सभी रिप्लेस करें",
+DlgReplaceWordChk : "पूरा शब्द मिलायें",
+
+// Paste Operations / Dialog
+PasteErrorCut : "आपके ब्राउज़र की सुरक्षा सॅटिन्ग्स ने कट करने की अनुमति नहीं प्रदान की है। (Ctrl+X) का प्रयोग करें।",
+PasteErrorCopy : "आपके ब्राआउज़र की सुरक्षा सॅटिन्ग्स ने कॉपी करने की अनुमति नहीं प्रदान की है। (Ctrl+C) का प्रयोग करें।",
+
+PasteAsText : "पेस्ट (सादा टॅक्स्ट)",
+PasteFromWord : "पेस्ट (वर्ड से)",
+
+DlgPasteMsg2 : "Ctrl+V का प्रयोग करके पेस्ट करें और ठीक है करें.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "फ़ॉन्ट परिभाषा निकालें",
+DlgPasteRemoveStyles : "स्टाइल परिभाषा निकालें",
+DlgPasteCleanBox : "बॉक्स साफ़ करें",
+
+// Color Picker
+ColorAutomatic : "ऑटोमैटिक",
+ColorMoreColors : "और रंग...",
+
+// Document Properties
+DocProps : "डॉक्यूमॅन्ट प्रॉपर्टीज़",
+
+// Anchor Dialog
+DlgAnchorTitle : "ऐंकर प्रॉपर्टीज़",
+DlgAnchorName : "ऐंकर का नाम",
+DlgAnchorErrorName : "ऐंकर का नाम टाइप करें",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "शब्दकोश में नहीं",
+DlgSpellChangeTo : "इसमें बदलें",
+DlgSpellBtnIgnore : "इग्नोर",
+DlgSpellBtnIgnoreAll : "सभी इग्नोर करें",
+DlgSpellBtnReplace : "रिप्लेस",
+DlgSpellBtnReplaceAll : "सभी रिप्लेस करें",
+DlgSpellBtnUndo : "अन्डू",
+DlgSpellNoSuggestions : "- कोई सुझाव नहीं -",
+DlgSpellProgress : "वर्तनी की जाँच (स्पॅल-चॅक) जारी है...",
+DlgSpellNoMispell : "वर्तनी की जाँच : कोई गलत वर्तनी (स्पॅलिंग) नहीं पाई गई",
+DlgSpellNoChanges : "वर्तनी की जाँच :कोई शब्द नहीं बदला गया",
+DlgSpellOneChange : "वर्तनी की जाँच : एक शब्द बदला गया",
+DlgSpellManyChanges : "वर्तनी की जाँच : %1 शब्द बदले गये",
+
+IeSpellDownload : "स्पॅल-चॅकर इन्स्टाल नहीं किया गया है। क्या आप इसे डा‌उनलोड करना चाहेंगे?",
+
+// Button Dialog
+DlgButtonText : "टेक्स्ट (वैल्यू)",
+DlgButtonType : "प्रकार",
+DlgButtonTypeBtn : "बटन",
+DlgButtonTypeSbm : "सब्मिट",
+DlgButtonTypeRst : "रिसेट",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "नाम",
+DlgCheckboxValue : "वैल्यू",
+DlgCheckboxSelected : "सॅलॅक्टॅड",
+
+// Form Dialog
+DlgFormName : "नाम",
+DlgFormAction : "ऍक्शन",
+DlgFormMethod : "तरीका",
+
+// Select Field Dialog
+DlgSelectName : "नाम",
+DlgSelectValue : "वैल्यू",
+DlgSelectSize : "साइज़",
+DlgSelectLines : "पंक्तियाँ",
+DlgSelectChkMulti : "एक से ज्यादा विकल्प चुनने दें",
+DlgSelectOpAvail : "उपलब्ध विकल्प",
+DlgSelectOpText : "टेक्स्ट",
+DlgSelectOpValue : "वैल्यू",
+DlgSelectBtnAdd : "जोड़ें",
+DlgSelectBtnModify : "बदलें",
+DlgSelectBtnUp : "ऊपर",
+DlgSelectBtnDown : "नीचे",
+DlgSelectBtnSetValue : "चुनी गई वैल्यू सॅट करें",
+DlgSelectBtnDelete : "डिलीट",
+
+// Textarea Dialog
+DlgTextareaName : "नाम",
+DlgTextareaCols : "कॉलम",
+DlgTextareaRows : "पंक्तियां",
+
+// Text Field Dialog
+DlgTextName : "नाम",
+DlgTextValue : "वैल्यू",
+DlgTextCharWidth : "करॅक्टर की चौढ़ाई",
+DlgTextMaxChars : "अधिकतम करॅक्टर",
+DlgTextType : "टाइप",
+DlgTextTypeText : "टेक्स्ट",
+DlgTextTypePass : "पास्वर्ड",
+
+// Hidden Field Dialog
+DlgHiddenName : "नाम",
+DlgHiddenValue : "वैल्यू",
+
+// Bulleted List Dialog
+BulletedListProp : "बुलॅट सूची प्रॉपर्टीज़",
+NumberedListProp : "अंकीय सूची प्रॉपर्टीज़",
+DlgLstStart : "प्रारम्भ",
+DlgLstType : "प्रकार",
+DlgLstTypeCircle : "गोल",
+DlgLstTypeDisc : "डिस्क",
+DlgLstTypeSquare : "चौकॊण",
+DlgLstTypeNumbers : "अंक (1, 2, 3)",
+DlgLstTypeLCase : "छोटे अक्षर (a, b, c)",
+DlgLstTypeUCase : "बड़े अक्षर (A, B, C)",
+DlgLstTypeSRoman : "छोटे रोमन अंक (i, ii, iii)",
+DlgLstTypeLRoman : "बड़े रोमन अंक (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "आम",
+DlgDocBackTab : "बैक्ग्राउन्ड",
+DlgDocColorsTab : "रंग और मार्जिन",
+DlgDocMetaTab : "मॅटाडेटा",
+
+DlgDocPageTitle : "पेज शीर्षक",
+DlgDocLangDir : "भाषा लिखने की दिशा",
+DlgDocLangDirLTR : "बायें से दायें (LTR)",
+DlgDocLangDirRTL : "दायें से बायें (RTL)",
+DlgDocLangCode : "भाषा कोड",
+DlgDocCharSet : "करेक्टर सॅट ऍन्कोडिंग",
+DlgDocCharSetCE : "मध्य यूरोपीय (Central European)",
+DlgDocCharSetCT : "चीनी (Chinese Traditional Big5)",
+DlgDocCharSetCR : "सिरीलिक (Cyrillic)",
+DlgDocCharSetGR : "यवन (Greek)",
+DlgDocCharSetJP : "जापानी (Japanese)",
+DlgDocCharSetKR : "कोरीयन (Korean)",
+DlgDocCharSetTR : "तुर्की (Turkish)",
+DlgDocCharSetUN : "यूनीकोड (UTF-8)",
+DlgDocCharSetWE : "पश्चिम यूरोपीय (Western European)",
+DlgDocCharSetOther : "अन्य करेक्टर सॅट ऍन्कोडिंग",
+
+DlgDocDocType : "डॉक्यूमॅन्ट प्रकार शीर्षक",
+DlgDocDocTypeOther : "अन्य डॉक्यूमॅन्ट प्रकार शीर्षक",
+DlgDocIncXHTML : "XHTML सूचना सम्मिलित करें",
+DlgDocBgColor : "बैक्ग्राउन्ड रंग",
+DlgDocBgImage : "बैक्ग्राउन्ड तस्वीर URL",
+DlgDocBgNoScroll : "स्क्रॉल न करने वाला बैक्ग्राउन्ड",
+DlgDocCText : "टेक्स्ट",
+DlgDocCLink : "लिंक",
+DlgDocCVisited : "विज़िट किया गया लिंक",
+DlgDocCActive : "सक्रिय लिंक",
+DlgDocMargins : "पेज मार्जिन",
+DlgDocMaTop : "ऊपर",
+DlgDocMaLeft : "बायें",
+DlgDocMaRight : "दायें",
+DlgDocMaBottom : "नीचे",
+DlgDocMeIndex : "डॉक्युमॅन्ट इन्डेक्स संकेतशब्द (अल्पविराम से अलग करें)",
+DlgDocMeDescr : "डॉक्यूमॅन्ट करॅक्टरन",
+DlgDocMeAuthor : "लेखक",
+DlgDocMeCopy : "कॉपीराइट",
+DlgDocPreview : "प्रीव्यू",
+
+// Templates Dialog
+Templates : "टॅम्प्लेट",
+DlgTemplatesTitle : "कन्टेन्ट टॅम्प्लेट",
+DlgTemplatesSelMsg : "ऍडिटर में ओपन करने हेतु टॅम्प्लेट चुनें(वर्तमान कन्टॅन्ट सेव नहीं होंगे):",
+DlgTemplatesLoading : "टॅम्प्लेट सूची लोड की जा रही है। ज़रा ठहरें...",
+DlgTemplatesNoTpl : "(कोई टॅम्प्लेट डिफ़ाइन नहीं किया गया है)",
+DlgTemplatesReplace : "मूल शब्दों को बदलें",
+
+// About Dialog
+DlgAboutAboutTab : "FCKEditor के बारे में",
+DlgAboutBrowserInfoTab : "ब्राउज़र के बारे में",
+DlgAboutLicenseTab : "लाइसैन्स",
+DlgAboutVersion : "वर्ज़न",
+DlgAboutInfo : "अधिक जानकारी के लिये यहाँ जायें:"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/hr.js b/httemplate/elements/fckeditor/editor/lang/hr.js
new file mode 100644
index 000000000..f088b1063
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/hr.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Croatian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Smanji trake s alatima",
+ToolbarExpand : "Proširi trake s alatima",
+
+// Toolbar Items and Context Menu
+Save : "Snimi",
+NewPage : "Nova stranica",
+Preview : "Pregledaj",
+Cut : "Izreži",
+Copy : "Kopiraj",
+Paste : "Zalijepi",
+PasteText : "Zalijepi kao čisti tekst",
+PasteWord : "Zalijepi iz Worda",
+Print : "Ispiši",
+SelectAll : "Odaberi sve",
+RemoveFormat : "Ukloni formatiranje",
+InsertLinkLbl : "Link",
+InsertLink : "Ubaci/promijeni link",
+RemoveLink : "Ukloni link",
+Anchor : "Ubaci/promijeni sidro",
+InsertImageLbl : "Slika",
+InsertImage : "Ubaci/promijeni sliku",
+InsertFlashLbl : "Flash",
+InsertFlash : "Ubaci/promijeni Flash",
+InsertTableLbl : "Tablica",
+InsertTable : "Ubaci/promijeni tablicu",
+InsertLineLbl : "Linija",
+InsertLine : "Ubaci vodoravnu liniju",
+InsertSpecialCharLbl: "Posebni karakteri",
+InsertSpecialChar : "Ubaci posebne znakove",
+InsertSmileyLbl : "Smješko",
+InsertSmiley : "Ubaci smješka",
+About : "O FCKeditoru",
+Bold : "Podebljaj",
+Italic : "Ukosi",
+Underline : "Potcrtano",
+StrikeThrough : "Precrtano",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Lijevo poravnanje",
+CenterJustify : "Središnje poravnanje",
+RightJustify : "Desno poravnanje",
+BlockJustify : "Blok poravnanje",
+DecreaseIndent : "Pomakni ulijevo",
+IncreaseIndent : "Pomakni udesno",
+Undo : "Poništi",
+Redo : "Ponovi",
+NumberedListLbl : "Brojčana lista",
+NumberedList : "Ubaci/ukloni brojčanu listu",
+BulletedListLbl : "Obična lista",
+BulletedList : "Ubaci/ukloni običnu listu",
+ShowTableBorders : "Prikaži okvir tablice",
+ShowDetails : "Prikaži detalje",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Veličina",
+TextColor : "Boja teksta",
+BGColor : "Boja pozadine",
+Source : "Kôd",
+Find : "Pronađi",
+Replace : "Zamijeni",
+SpellCheck : "Provjeri pravopis",
+UniversalKeyboard : "Univerzalna tipkovnica",
+PageBreakLbl : "Prijelom stranice",
+PageBreak : "Ubaci prijelom stranice",
+
+Form : "Form",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Hidden Field",
+Button : "Button",
+SelectionField : "Selection Field",
+ImageButton : "Image Button",
+
+FitWindow : "Povećaj veličinu editora",
+
+// Context Menu
+EditLink : "Promijeni link",
+CellCM : "Ćelija",
+RowCM : "Red",
+ColumnCM : "Kolona",
+InsertRow : "Ubaci red",
+DeleteRows : "Izbriši redove",
+InsertColumn : "Ubaci kolonu",
+DeleteColumns : "Izbriši kolone",
+InsertCell : "Ubaci ćelije",
+DeleteCells : "Izbriši ćelije",
+MergeCells : "Spoji ćelije",
+SplitCell : "Razdvoji ćelije",
+TableDelete : "Izbriši tablicu",
+CellProperties : "Svojstva ćelije",
+TableProperties : "Svojstva tablice",
+ImageProperties : "Svojstva slike",
+FlashProperties : "Flash svojstva",
+
+AnchorProp : "Svojstva sidra",
+ButtonProp : "Image Button svojstva",
+CheckboxProp : "Checkbox svojstva",
+HiddenFieldProp : "Hidden Field svojstva",
+RadioButtonProp : "Radio Button svojstva",
+ImageButtonProp : "Image Button svojstva",
+TextFieldProp : "Text Field svojstva",
+SelectionFieldProp : "Selection svojstva",
+TextareaProp : "Textarea svojstva",
+FormProp : "Form svojstva",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Obrađujem XHTML. Molimo pričekajte...",
+Done : "Završio",
+PasteWordConfirm : "Tekst koji želite zalijepiti čini se da je kopiran iz Worda. Želite li prije očistiti tekst?",
+NotCompatiblePaste : "Ova naredba je dostupna samo u Internet Exploreru 5.5 ili novijem. Želite li nastaviti bez čišćenja?",
+UnknownToolbarItem : "Nepoznati član trake s alatima \"%1\"",
+UnknownCommand : "Nepoznata naredba \"%1\"",
+NotImplemented : "Naredba nije implementirana",
+UnknownToolbarSet : "Traka s alatima \"%1\" ne postoji",
+NoActiveX : "Vaše postavke pretraživača mogle bi ograničiti neke od mogućnosti editora. Morate uključiti opciju \"Run ActiveX controls and plug-ins\" u postavkama. Ukoliko to ne učinite, moguće su razliite greške tijekom rada.",
+BrowseServerBlocked : "Pretraivač nije moguće otvoriti. Provjerite da li je uključeno blokiranje pop-up prozora.",
+DialogBlocked : "Nije moguće otvoriti novi prozor. Provjerite da li je uključeno blokiranje pop-up prozora.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Poništi",
+DlgBtnClose : "Zatvori",
+DlgBtnBrowseServer : "Pretraži server",
+DlgAdvancedTag : "Napredno",
+DlgOpOther : "<Drugo>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Molimo unesite URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nije postavljeno>",
+DlgGenId : "Id",
+DlgGenLangDir : "Smjer jezika",
+DlgGenLangDirLtr : "S lijeva na desno (LTR)",
+DlgGenLangDirRtl : "S desna na lijevo (RTL)",
+DlgGenLangCode : "Kôd jezika",
+DlgGenAccessKey : "Pristupna tipka",
+DlgGenName : "Naziv",
+DlgGenTabIndex : "Tab Indeks",
+DlgGenLongDescr : "Dugački opis URL",
+DlgGenClass : "Stylesheet klase",
+DlgGenTitle : "Advisory naslov",
+DlgGenContType : "Advisory vrsta sadržaja",
+DlgGenLinkCharset : "Kodna stranica povezanih resursa",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Svojstva slika",
+DlgImgInfoTab : "Info slike",
+DlgImgBtnUpload : "Pošalji na server",
+DlgImgURL : "URL",
+DlgImgUpload : "Pošalji",
+DlgImgAlt : "Alternativni tekst",
+DlgImgWidth : "Širina",
+DlgImgHeight : "Visina",
+DlgImgLockRatio : "Zaključaj odnos",
+DlgBtnResetSize : "Obriši veličinu",
+DlgImgBorder : "Okvir",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Poravnaj",
+DlgImgAlignLeft : "Lijevo",
+DlgImgAlignAbsBottom: "Abs dolje",
+DlgImgAlignAbsMiddle: "Abs sredina",
+DlgImgAlignBaseline : "Bazno",
+DlgImgAlignBottom : "Dolje",
+DlgImgAlignMiddle : "Sredina",
+DlgImgAlignRight : "Desno",
+DlgImgAlignTextTop : "Vrh teksta",
+DlgImgAlignTop : "Vrh",
+DlgImgPreview : "Pregledaj",
+DlgImgAlertUrl : "Unesite URL slike",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Flash svojstva",
+DlgFlashChkPlay : "Auto Play",
+DlgFlashChkLoop : "Ponavljaj",
+DlgFlashChkMenu : "Omogući Flash izbornik",
+DlgFlashScale : "Omjer",
+DlgFlashScaleAll : "Prikaži sve",
+DlgFlashScaleNoBorder : "Bez okvira",
+DlgFlashScaleFit : "Točna veličina",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Meta",
+
+DlgLnkType : "Link vrsta",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Sidro na ovoj stranici",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<drugo>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Odaberi sidro",
+DlgLnkAnchorByName : "Po nazivu sidra",
+DlgLnkAnchorById : "Po Id elementa",
+DlgLnkNoAnchors : "<Nema dostupnih sidra>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail adresa",
+DlgLnkEMailSubject : "Naslov",
+DlgLnkEMailBody : "Sadržaj poruke",
+DlgLnkUpload : "Pošalji",
+DlgLnkBtnUpload : "Pošalji na server",
+
+DlgLnkTarget : "Meta",
+DlgLnkTargetFrame : "<okvir>",
+DlgLnkTargetPopup : "<popup prozor>",
+DlgLnkTargetBlank : "Novi prozor (_blank)",
+DlgLnkTargetParent : "Roditeljski prozor (_parent)",
+DlgLnkTargetSelf : "Isti prozor (_self)",
+DlgLnkTargetTop : "Vršni prozor (_top)",
+DlgLnkTargetFrameName : "Ime ciljnog okvira",
+DlgLnkPopWinName : "Naziv popup prozora",
+DlgLnkPopWinFeat : "Mogućnosti popup prozora",
+DlgLnkPopResize : "Promjenljive veličine",
+DlgLnkPopLocation : "Traka za lokaciju",
+DlgLnkPopMenu : "Izborna traka",
+DlgLnkPopScroll : "Scroll traka",
+DlgLnkPopStatus : "Statusna traka",
+DlgLnkPopToolbar : "Traka s alatima",
+DlgLnkPopFullScrn : "Cijeli ekran (IE)",
+DlgLnkPopDependent : "Ovisno (Netscape)",
+DlgLnkPopWidth : "Širina",
+DlgLnkPopHeight : "Visina",
+DlgLnkPopLeft : "Lijeva pozicija",
+DlgLnkPopTop : "Gornja pozicija",
+
+DlnLnkMsgNoUrl : "Molimo upišite URL link",
+DlnLnkMsgNoEMail : "Molimo upišite e-mail adresu",
+DlnLnkMsgNoAnchor : "Molimo odaberite sidro",
+DlnLnkMsgInvPopName : "Ime popup prozora mora početi sa slovom i ne smije sadržavati razmake",
+
+// Color Dialog
+DlgColorTitle : "Odaberite boju",
+DlgColorBtnClear : "Obriši",
+DlgColorHighlight : "Osvijetli",
+DlgColorSelected : "Odaberi",
+
+// Smiley Dialog
+DlgSmileyTitle : "Ubaci smješka",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Odaberite posebni karakter",
+
+// Table Dialog
+DlgTableTitle : "Svojstva tablice",
+DlgTableRows : "Redova",
+DlgTableColumns : "Kolona",
+DlgTableBorder : "Veličina okvira",
+DlgTableAlign : "Poravnanje",
+DlgTableAlignNotSet : "<nije postavljeno>",
+DlgTableAlignLeft : "Lijevo",
+DlgTableAlignCenter : "Središnje",
+DlgTableAlignRight : "Desno",
+DlgTableWidth : "Širina",
+DlgTableWidthPx : "piksela",
+DlgTableWidthPc : "postotaka",
+DlgTableHeight : "Visina",
+DlgTableCellSpace : "Prostornost ćelija",
+DlgTableCellPad : "Razmak ćelija",
+DlgTableCaption : "Naslov",
+DlgTableSummary : "Sažetak",
+
+// Table Cell Dialog
+DlgCellTitle : "Svojstva ćelije",
+DlgCellWidth : "Širina",
+DlgCellWidthPx : "piksela",
+DlgCellWidthPc : "postotaka",
+DlgCellHeight : "Visina",
+DlgCellWordWrap : "Word Wrap",
+DlgCellWordWrapNotSet : "<nije postavljeno>",
+DlgCellWordWrapYes : "Da",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Vodoravno poravnanje",
+DlgCellHorAlignNotSet : "<nije postavljeno>",
+DlgCellHorAlignLeft : "Lijevo",
+DlgCellHorAlignCenter : "Središnje",
+DlgCellHorAlignRight: "Desno",
+DlgCellVerAlign : "Okomito poravnanje",
+DlgCellVerAlignNotSet : "<nije postavljeno>",
+DlgCellVerAlignTop : "Gornje",
+DlgCellVerAlignMiddle : "Srednišnje",
+DlgCellVerAlignBottom : "Donje",
+DlgCellVerAlignBaseline : "Bazno",
+DlgCellRowSpan : "Spajanje redova",
+DlgCellCollSpan : "Spajanje kolona",
+DlgCellBackColor : "Boja pozadine",
+DlgCellBorderColor : "Boja okvira",
+DlgCellBtnSelect : "Odaberi...",
+
+// Find Dialog
+DlgFindTitle : "Pronađi",
+DlgFindFindBtn : "Pronađi",
+DlgFindNotFoundMsg : "Traženi tekst nije pronađen.",
+
+// Replace Dialog
+DlgReplaceTitle : "Zamijeni",
+DlgReplaceFindLbl : "Pronađi:",
+DlgReplaceReplaceLbl : "Zamijeni s:",
+DlgReplaceCaseChk : "Usporedi mala/velika slova",
+DlgReplaceReplaceBtn : "Zamijeni",
+DlgReplaceReplAllBtn : "Zamijeni sve",
+DlgReplaceWordChk : "Usporedi cijele riječi",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog izrezivanja. Molimo koristite kraticu na tipkovnici (Ctrl+X).",
+PasteErrorCopy : "Sigurnosne postavke Vašeg pretraživača ne dozvoljavaju operacije automatskog kopiranja. Molimo koristite kraticu na tipkovnici (Ctrl+C).",
+
+PasteAsText : "Zalijepi kao čisti tekst",
+PasteFromWord : "Zalijepi iz Worda",
+
+DlgPasteMsg2 : "Molimo zaljepite unutar doljnjeg okvira koristeći tipkovnicu (<STRONG>Ctrl+V</STRONG>) i kliknite <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Zanemari definiciju vrste fonta",
+DlgPasteRemoveStyles : "Ukloni definicije stilova",
+DlgPasteCleanBox : "Očisti okvir",
+
+// Color Picker
+ColorAutomatic : "Automatski",
+ColorMoreColors : "Više boja...",
+
+// Document Properties
+DocProps : "Svojstva dokumenta",
+
+// Anchor Dialog
+DlgAnchorTitle : "Svojstva sidra",
+DlgAnchorName : "Ime sidra",
+DlgAnchorErrorName : "Molimo unesite ime sidra",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nije u rječniku",
+DlgSpellChangeTo : "Promijeni u",
+DlgSpellBtnIgnore : "Zanemari",
+DlgSpellBtnIgnoreAll : "Zanemari sve",
+DlgSpellBtnReplace : "Zamijeni",
+DlgSpellBtnReplaceAll : "Zamijeni sve",
+DlgSpellBtnUndo : "Vrati",
+DlgSpellNoSuggestions : "-Nema preporuke-",
+DlgSpellProgress : "Provjera u tijeku...",
+DlgSpellNoMispell : "Provjera završena: Nema grešaka",
+DlgSpellNoChanges : "Provjera završena: Nije napravljena promjena",
+DlgSpellOneChange : "Provjera završena: Jedna riječ promjenjena",
+DlgSpellManyChanges : "Provjera završena: Promijenjeno %1 riječi",
+
+IeSpellDownload : "Provjera pravopisa nije instalirana. Želite li skinuti provjeru pravopisa?",
+
+// Button Dialog
+DlgButtonText : "Tekst (vrijednost)",
+DlgButtonType : "Vrsta",
+DlgButtonTypeBtn : "Gumb",
+DlgButtonTypeSbm : "Pošalji",
+DlgButtonTypeRst : "Poništi",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Ime",
+DlgCheckboxValue : "Vrijednost",
+DlgCheckboxSelected : "Odabrano",
+
+// Form Dialog
+DlgFormName : "Ime",
+DlgFormAction : "Akcija",
+DlgFormMethod : "Metoda",
+
+// Select Field Dialog
+DlgSelectName : "Ime",
+DlgSelectValue : "Vrijednost",
+DlgSelectSize : "Veličina",
+DlgSelectLines : "linija",
+DlgSelectChkMulti : "Dozvoli višestruki odabir",
+DlgSelectOpAvail : "Dostupne opcije",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Vrijednost",
+DlgSelectBtnAdd : "Dodaj",
+DlgSelectBtnModify : "Promijeni",
+DlgSelectBtnUp : "Gore",
+DlgSelectBtnDown : "Dolje",
+DlgSelectBtnSetValue : "Postavi kao odabranu vrijednost",
+DlgSelectBtnDelete : "Obriši",
+
+// Textarea Dialog
+DlgTextareaName : "Ime",
+DlgTextareaCols : "Kolona",
+DlgTextareaRows : "Redova",
+
+// Text Field Dialog
+DlgTextName : "Ime",
+DlgTextValue : "Vrijednost",
+DlgTextCharWidth : "Širina",
+DlgTextMaxChars : "Najviše karaktera",
+DlgTextType : "Vrsta",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Šifra",
+
+// Hidden Field Dialog
+DlgHiddenName : "Ime",
+DlgHiddenValue : "Vrijednost",
+
+// Bulleted List Dialog
+BulletedListProp : "Svojstva liste",
+NumberedListProp : "Svojstva brojčane liste",
+DlgLstStart : "Početak",
+DlgLstType : "Vrsta",
+DlgLstTypeCircle : "Krug",
+DlgLstTypeDisc : "Disk",
+DlgLstTypeSquare : "Kvadrat",
+DlgLstTypeNumbers : "Brojevi (1, 2, 3)",
+DlgLstTypeLCase : "Mala slova (a, b, c)",
+DlgLstTypeUCase : "Velika slova (A, B, C)",
+DlgLstTypeSRoman : "Male rimske brojke (i, ii, iii)",
+DlgLstTypeLRoman : "Velike rimske brojke (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Općenito",
+DlgDocBackTab : "Pozadina",
+DlgDocColorsTab : "Boje i margine",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Naslov stranice",
+DlgDocLangDir : "Smjer jezika",
+DlgDocLangDirLTR : "S lijeva na desno",
+DlgDocLangDirRTL : "S desna na lijevo",
+DlgDocLangCode : "Kôd jezika",
+DlgDocCharSet : "Enkodiranje znakova",
+DlgDocCharSetCE : "Središnja Europa",
+DlgDocCharSetCT : "Tradicionalna kineska (Big5)",
+DlgDocCharSetCR : "Ćirilica",
+DlgDocCharSetGR : "Grčka",
+DlgDocCharSetJP : "Japanska",
+DlgDocCharSetKR : "Koreanska",
+DlgDocCharSetTR : "Turska",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Zapadna Europa",
+DlgDocCharSetOther : "Ostalo enkodiranje znakova",
+
+DlgDocDocType : "Zaglavlje vrste dokumenta",
+DlgDocDocTypeOther : "Ostalo zaglavlje vrste dokumenta",
+DlgDocIncXHTML : "Ubaci XHTML deklaracije",
+DlgDocBgColor : "Boja pozadine",
+DlgDocBgImage : "URL slike pozadine",
+DlgDocBgNoScroll : "Pozadine se ne pomiče",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Posjećeni link",
+DlgDocCActive : "Aktivni link",
+DlgDocMargins : "Margine stranice",
+DlgDocMaTop : "Vrh",
+DlgDocMaLeft : "Lijevo",
+DlgDocMaRight : "Desno",
+DlgDocMaBottom : "Dolje",
+DlgDocMeIndex : "Ključne riječi dokumenta (odvojene zarezom)",
+DlgDocMeDescr : "Opis dokumenta",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Autorska prava",
+DlgDocPreview : "Pregledaj",
+
+// Templates Dialog
+Templates : "Predlošci",
+DlgTemplatesTitle : "Predlošci sadržaja",
+DlgTemplatesSelMsg : "Molimo odaberite predložak koji želite otvoriti<br>(stvarni sadržaj će biti izgubljen):",
+DlgTemplatesLoading : "Učitavam listu predložaka. Molimo pričekajte...",
+DlgTemplatesNoTpl : "(Nema definiranih predložaka)",
+DlgTemplatesReplace : "Zamijeni trenutne sadržaje",
+
+// About Dialog
+DlgAboutAboutTab : "O FCKEditoru",
+DlgAboutBrowserInfoTab : "Podaci o pretraživaču",
+DlgAboutLicenseTab : "Licenca",
+DlgAboutVersion : "inačica",
+DlgAboutInfo : "Za više informacija posjetite"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/hu.js b/httemplate/elements/fckeditor/editor/lang/hu.js
new file mode 100644
index 000000000..73b912c82
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/hu.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Hungarian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Eszköztár elrejtése",
+ToolbarExpand : "Eszköztár megjelenítése",
+
+// Toolbar Items and Context Menu
+Save : "Mentés",
+NewPage : "Új oldal",
+Preview : "Előnézet",
+Cut : "Kivágás",
+Copy : "Másolás",
+Paste : "Beillesztés",
+PasteText : "Beillesztés formázás nélkül",
+PasteWord : "Beillesztés Word-ből",
+Print : "Nyomtatás",
+SelectAll : "Mindent kijelöl",
+RemoveFormat : "Formázás eltávolítása",
+InsertLinkLbl : "Hivatkozás",
+InsertLink : "Hivatkozás beillesztése/módosítása",
+RemoveLink : "Hivatkozás törlése",
+Anchor : "Horgony beillesztése/szerkesztése",
+InsertImageLbl : "Kép",
+InsertImage : "Kép beillesztése/módosítása",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash beillesztése, módosítása",
+InsertTableLbl : "Táblázat",
+InsertTable : "Táblázat beillesztése/módosítása",
+InsertLineLbl : "Vonal",
+InsertLine : "Elválasztóvonal beillesztése",
+InsertSpecialCharLbl: "Speciális karakter",
+InsertSpecialChar : "Speciális karakter beillesztése",
+InsertSmileyLbl : "Hangulatjelek",
+InsertSmiley : "Hangulatjelek beillesztése",
+About : "FCKeditor névjegy",
+Bold : "Félkövér",
+Italic : "Dőlt",
+Underline : "Aláhúzott",
+StrikeThrough : "Áthúzott",
+Subscript : "Alsó index",
+Superscript : "Felső index",
+LeftJustify : "Balra",
+CenterJustify : "Középre",
+RightJustify : "Jobbra",
+BlockJustify : "Sorkizárt",
+DecreaseIndent : "Behúzás csökkentése",
+IncreaseIndent : "Behúzás növelése",
+Undo : "Visszavonás",
+Redo : "Ismétlés",
+NumberedListLbl : "Számozás",
+NumberedList : "Számozás beillesztése/törlése",
+BulletedListLbl : "Felsorolás",
+BulletedList : "Felsorolás beillesztése/törlése",
+ShowTableBorders : "Táblázat szegély mutatása",
+ShowDetails : "Részletek mutatása",
+Style : "Stílus",
+FontFormat : "Formátum",
+Font : "Betűtípus",
+FontSize : "Méret",
+TextColor : "Betűszín",
+BGColor : "Háttérszín",
+Source : "Forráskód",
+Find : "Keresés",
+Replace : "Csere",
+SpellCheck : "Helyesírás-ellenőrzés",
+UniversalKeyboard : "Univerzális billentyűzet",
+PageBreakLbl : "Oldaltörés",
+PageBreak : "Oldaltörés beillesztése",
+
+Form : "Űrlap",
+Checkbox : "Jelölőnégyzet",
+RadioButton : "Választógomb",
+TextField : "Szövegmező",
+Textarea : "Szövegterület",
+HiddenField : "Rejtettmező",
+Button : "Gomb",
+SelectionField : "Legördülő lista",
+ImageButton : "Képgomb",
+
+FitWindow : "Maximalizálás",
+
+// Context Menu
+EditLink : "Hivatkozás módosítása",
+CellCM : "Cella",
+RowCM : "Sor",
+ColumnCM : "Oszlop",
+InsertRow : "Sor beszúrása",
+DeleteRows : "Sorok törlése",
+InsertColumn : "Oszlop beszúrása",
+DeleteColumns : "Oszlopok törlése",
+InsertCell : "Cella beszúrása",
+DeleteCells : "Cellák törlése",
+MergeCells : "Cellák egyesítése",
+SplitCell : "Cella szétválasztása",
+TableDelete : "Táblázat törlése",
+CellProperties : "Cella tulajdonságai",
+TableProperties : "Táblázat tulajdonságai",
+ImageProperties : "Kép tulajdonságai",
+FlashProperties : "Flash tulajdonságai",
+
+AnchorProp : "Horgony tulajdonságai",
+ButtonProp : "Gomb tulajdonságai",
+CheckboxProp : "Jelölőnégyzet tulajdonságai",
+HiddenFieldProp : "Rejtett mező tulajdonságai",
+RadioButtonProp : "Választógomb tulajdonságai",
+ImageButtonProp : "Képgomb tulajdonságai",
+TextFieldProp : "Szövegmező tulajdonságai",
+SelectionFieldProp : "Legördülő lista tulajdonságai",
+TextareaProp : "Szövegterület tulajdonságai",
+FormProp : "Űrlap tulajdonságai",
+
+FontFormats : "Normál;Formázott;Címsor;Fejléc 1;Fejléc 2;Fejléc 3;Fejléc 4;Fejléc 5;Fejléc 6;Bekezdés (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML feldolgozása. Kérem várjon...",
+Done : "Kész",
+PasteWordConfirm : "A beilleszteni kívánt szöveg Word-ből van másolva. El kívánja távolítani a formázást a beillesztés előtt?",
+NotCompatiblePaste : "Ez a parancs csak Internet Explorer 5.5 verziótól használható. Megpróbálja beilleszteni a szöveget az eredeti formázással?",
+UnknownToolbarItem : "Ismeretlen eszköztár elem \"%1\"",
+UnknownCommand : "Ismeretlen parancs \"%1\"",
+NotImplemented : "A parancs nem hajtható végre",
+UnknownToolbarSet : "Az eszközkészlet \"%1\" nem létezik",
+NoActiveX : "A böngésző biztonsági beállításai korlátozzák a szerkesztő lehetőségeit. Engedélyezni kell ezt az opciót: \"Run ActiveX controls and plug-ins\". Ettől függetlenül előfordulhatnak hibaüzenetek ill. bizonyos funkciók hiányozhatnak.",
+BrowseServerBlocked : "Nem lehet megnyitni a fájlböngészőt. Bizonyosodjon meg róla, hogy a felbukkanó ablakok engedélyezve vannak.",
+DialogBlocked : "Nem lehet megnyitni a párbeszédablakot. Bizonyosodjon meg róla, hogy a felbukkanó ablakok engedélyezve vannak.",
+
+// Dialogs
+DlgBtnOK : "Rendben",
+DlgBtnCancel : "Mégsem",
+DlgBtnClose : "Bezárás",
+DlgBtnBrowseServer : "Böngészés a szerveren",
+DlgAdvancedTag : "További opciók",
+DlgOpOther : "Egyéb",
+DlgInfoTab : "Alaptulajdonságok",
+DlgAlertUrl : "Illessze be a webcímet",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nincs beállítva>",
+DlgGenId : "Azonosító",
+DlgGenLangDir : "Írás iránya",
+DlgGenLangDirLtr : "Balról jobbra",
+DlgGenLangDirRtl : "Jobbról balra",
+DlgGenLangCode : "Nyelv kódja",
+DlgGenAccessKey : "Billentyűkombináció",
+DlgGenName : "Név",
+DlgGenTabIndex : "Tabulátor index",
+DlgGenLongDescr : "Részletes leírás webcíme",
+DlgGenClass : "Stíluskészlet",
+DlgGenTitle : "Súgócimke",
+DlgGenContType : "Súgó tartalomtípusa",
+DlgGenLinkCharset : "Hivatkozott tartalom kódlapja",
+DlgGenStyle : "Stílus",
+
+// Image Dialog
+DlgImgTitle : "Kép tulajdonságai",
+DlgImgInfoTab : "Alaptulajdonságok",
+DlgImgBtnUpload : "Küldés a szerverre",
+DlgImgURL : "Hivatkozás",
+DlgImgUpload : "Feltöltés",
+DlgImgAlt : "Buborék szöveg",
+DlgImgWidth : "Szélesség",
+DlgImgHeight : "Magasság",
+DlgImgLockRatio : "Arány megtartása",
+DlgBtnResetSize : "Eredeti méret",
+DlgImgBorder : "Keret",
+DlgImgHSpace : "Vízsz. táv",
+DlgImgVSpace : "Függ. táv",
+DlgImgAlign : "Igazítás",
+DlgImgAlignLeft : "Bal",
+DlgImgAlignAbsBottom: "Legaljára",
+DlgImgAlignAbsMiddle: "Közepére",
+DlgImgAlignBaseline : "Alapvonalhoz",
+DlgImgAlignBottom : "Aljára",
+DlgImgAlignMiddle : "Középre",
+DlgImgAlignRight : "Jobbra",
+DlgImgAlignTextTop : "Szöveg tetejére",
+DlgImgAlignTop : "Tetejére",
+DlgImgPreview : "Előnézet",
+DlgImgAlertUrl : "Töltse ki a kép webcímét",
+DlgImgLinkTab : "Hivatkozás",
+
+// Flash Dialog
+DlgFlashTitle : "Flash tulajdonságai",
+DlgFlashChkPlay : "Automata lejátszás",
+DlgFlashChkLoop : "Folyamatosan",
+DlgFlashChkMenu : "Flash menü engedélyezése",
+DlgFlashScale : "Méretezés",
+DlgFlashScaleAll : "Mindent mutat",
+DlgFlashScaleNoBorder : "Keret nélkül",
+DlgFlashScaleFit : "Teljes kitöltés",
+
+// Link Dialog
+DlgLnkWindowTitle : "Hivatkozás tulajdonságai",
+DlgLnkInfoTab : "Alaptulajdonságok",
+DlgLnkTargetTab : "Megjelenítés",
+
+DlgLnkType : "Hivatkozás típusa",
+DlgLnkTypeURL : "Webcím",
+DlgLnkTypeAnchor : "Horgony az oldalon",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<más>",
+DlgLnkURL : "Webcím",
+DlgLnkAnchorSel : "Horgony választása",
+DlgLnkAnchorByName : "Horgony név szerint",
+DlgLnkAnchorById : "Azonosító szerint",
+DlgLnkNoAnchors : "<Nincs horgony a dokumentumban>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail cím",
+DlgLnkEMailSubject : "Üzenet tárgya",
+DlgLnkEMailBody : "Üzenet",
+DlgLnkUpload : "Feltöltés",
+DlgLnkBtnUpload : "Küldés a szerverre",
+
+DlgLnkTarget : "Tartalom megjelenítése",
+DlgLnkTargetFrame : "<keretben>",
+DlgLnkTargetPopup : "<felugró ablakban>",
+DlgLnkTargetBlank : "Új ablakban (_blank)",
+DlgLnkTargetParent : "Szülő ablakban (_parent)",
+DlgLnkTargetSelf : "Azonos ablakban (_self)",
+DlgLnkTargetTop : "Legfelső ablakban (_top)",
+DlgLnkTargetFrameName : "Keret neve",
+DlgLnkPopWinName : "Felugró ablak neve",
+DlgLnkPopWinFeat : "Felugró ablak jellemzői",
+DlgLnkPopResize : "Méretezhető",
+DlgLnkPopLocation : "Címsor",
+DlgLnkPopMenu : "Menü sor",
+DlgLnkPopScroll : "Gördítősáv",
+DlgLnkPopStatus : "Állapotsor",
+DlgLnkPopToolbar : "Eszköztár",
+DlgLnkPopFullScrn : "Teljes képernyő (csak IE)",
+DlgLnkPopDependent : "Szülőhöz kapcsolt (csak Netscape)",
+DlgLnkPopWidth : "Szélesség",
+DlgLnkPopHeight : "Magasság",
+DlgLnkPopLeft : "Bal pozíció",
+DlgLnkPopTop : "Felső pozíció",
+
+DlnLnkMsgNoUrl : "Adja meg a hivatkozás webcímét",
+DlnLnkMsgNoEMail : "Adja meg az E-Mail címet",
+DlnLnkMsgNoAnchor : "Válasszon egy horgonyt",
+DlnLnkMsgInvPopName : "A felbukkanó ablak neve alfanumerikus karakterrel kezdôdjön, valamint ne tartalmazzon szóközt",
+
+// Color Dialog
+DlgColorTitle : "Színválasztás",
+DlgColorBtnClear : "Törlés",
+DlgColorHighlight : "Előnézet",
+DlgColorSelected : "Kiválasztott",
+
+// Smiley Dialog
+DlgSmileyTitle : "Hangulatjel beszúrása",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Speciális karakter választása",
+
+// Table Dialog
+DlgTableTitle : "Táblázat tulajdonságai",
+DlgTableRows : "Sorok",
+DlgTableColumns : "Oszlopok",
+DlgTableBorder : "Szegélyméret",
+DlgTableAlign : "Igazítás",
+DlgTableAlignNotSet : "<Nincs beállítva>",
+DlgTableAlignLeft : "Balra",
+DlgTableAlignCenter : "Középre",
+DlgTableAlignRight : "Jobbra",
+DlgTableWidth : "Szélesség",
+DlgTableWidthPx : "képpont",
+DlgTableWidthPc : "százalék",
+DlgTableHeight : "Magasság",
+DlgTableCellSpace : "Cella térköz",
+DlgTableCellPad : "Cella belső margó",
+DlgTableCaption : "Felirat",
+DlgTableSummary : "Leírás",
+
+// Table Cell Dialog
+DlgCellTitle : "Cella tulajdonságai",
+DlgCellWidth : "Szélesség",
+DlgCellWidthPx : "képpont",
+DlgCellWidthPc : "százalék",
+DlgCellHeight : "Magasság",
+DlgCellWordWrap : "Sortörés",
+DlgCellWordWrapNotSet : "<Nincs beállítva>",
+DlgCellWordWrapYes : "Igen",
+DlgCellWordWrapNo : "Nem",
+DlgCellHorAlign : "Vízsz. igazítás",
+DlgCellHorAlignNotSet : "<Nincs beállítva>",
+DlgCellHorAlignLeft : "Balra",
+DlgCellHorAlignCenter : "Középre",
+DlgCellHorAlignRight: "Jobbra",
+DlgCellVerAlign : "Függ. igazítás",
+DlgCellVerAlignNotSet : "<Nincs beállítva>",
+DlgCellVerAlignTop : "Tetejére",
+DlgCellVerAlignMiddle : "Középre",
+DlgCellVerAlignBottom : "Aljára",
+DlgCellVerAlignBaseline : "Egyvonalba",
+DlgCellRowSpan : "Sorok egyesítése",
+DlgCellCollSpan : "Oszlopok egyesítése",
+DlgCellBackColor : "Háttérszín",
+DlgCellBorderColor : "Szegélyszín",
+DlgCellBtnSelect : "Kiválasztás...",
+
+// Find Dialog
+DlgFindTitle : "Keresés",
+DlgFindFindBtn : "Keresés",
+DlgFindNotFoundMsg : "A keresett szöveg nem található.",
+
+// Replace Dialog
+DlgReplaceTitle : "Csere",
+DlgReplaceFindLbl : "Keresett szöveg:",
+DlgReplaceReplaceLbl : "Csere erre:",
+DlgReplaceCaseChk : "kis- és nagybetű megkülönböztetése",
+DlgReplaceReplaceBtn : "Csere",
+DlgReplaceReplAllBtn : "Az összes cseréje",
+DlgReplaceWordChk : "csak ha ez a teljes szó",
+
+// Paste Operations / Dialog
+PasteErrorCut : "A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a kivágás műveletet. Használja az alábbi billentyűkombinációt (Ctrl+X).",
+PasteErrorCopy : "A böngésző biztonsági beállításai nem engedélyezik a szerkesztőnek, hogy végrehajtsa a másolás műveletet. Használja az alábbi billentyűkombinációt (Ctrl+X).",
+
+PasteAsText : "Beillesztés formázatlan szövegként",
+PasteFromWord : "Beillesztés Word-ből",
+
+DlgPasteMsg2 : "Másolja be az alábbi mezőbe a <STRONG>Ctrl+V</STRONG> billentyűk lenyomásával, majd nyomjon <STRONG>Rendben</STRONG>-t.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Betű formázások megszüntetése",
+DlgPasteRemoveStyles : "Stílusok eltávolítása",
+DlgPasteCleanBox : "Törlés",
+
+// Color Picker
+ColorAutomatic : "Automatikus",
+ColorMoreColors : "További színek...",
+
+// Document Properties
+DocProps : "Dokumentum tulajdonságai",
+
+// Anchor Dialog
+DlgAnchorTitle : "Horgony tulajdonságai",
+DlgAnchorName : "Horgony neve",
+DlgAnchorErrorName : "Kérem adja meg a horgony nevét",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nincs a szótárban",
+DlgSpellChangeTo : "Módosítás",
+DlgSpellBtnIgnore : "Kihagyja",
+DlgSpellBtnIgnoreAll : "Mindet kihagyja",
+DlgSpellBtnReplace : "Csere",
+DlgSpellBtnReplaceAll : "Összes cseréje",
+DlgSpellBtnUndo : "Visszavonás",
+DlgSpellNoSuggestions : "Nincs javaslat",
+DlgSpellProgress : "Helyesírás-ellenőrzés folyamatban...",
+DlgSpellNoMispell : "Helyesírás-ellenőrzés kész: Nem találtam hibát",
+DlgSpellNoChanges : "Helyesírás-ellenőrzés kész: Nincs változtatott szó",
+DlgSpellOneChange : "Helyesírás-ellenőrzés kész: Egy szó cserélve",
+DlgSpellManyChanges : "Helyesírás-ellenőrzés kész: %1 szó cserélve",
+
+IeSpellDownload : "A helyesírás-ellenőrző nincs telepítve. Szeretné letölteni most?",
+
+// Button Dialog
+DlgButtonText : "Szöveg (Érték)",
+DlgButtonType : "Típus",
+DlgButtonTypeBtn : "Gomb",
+DlgButtonTypeSbm : "Küldés",
+DlgButtonTypeRst : "Alaphelyzet",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Név",
+DlgCheckboxValue : "Érték",
+DlgCheckboxSelected : "Kiválasztott",
+
+// Form Dialog
+DlgFormName : "Név",
+DlgFormAction : "Adatfeldolgozást végző hivatkozás",
+DlgFormMethod : "Adatküldés módja",
+
+// Select Field Dialog
+DlgSelectName : "Név",
+DlgSelectValue : "Érték",
+DlgSelectSize : "Méret",
+DlgSelectLines : "sor",
+DlgSelectChkMulti : "több sor is kiválasztható",
+DlgSelectOpAvail : "Elérhető opciók",
+DlgSelectOpText : "Szöveg",
+DlgSelectOpValue : "Érték",
+DlgSelectBtnAdd : "Hozzáad",
+DlgSelectBtnModify : "Módosít",
+DlgSelectBtnUp : "Fel",
+DlgSelectBtnDown : "Le",
+DlgSelectBtnSetValue : "Legyen az alapértelmezett érték",
+DlgSelectBtnDelete : "Töröl",
+
+// Textarea Dialog
+DlgTextareaName : "Név",
+DlgTextareaCols : "Karakterek száma egy sorban",
+DlgTextareaRows : "Sorok száma",
+
+// Text Field Dialog
+DlgTextName : "Név",
+DlgTextValue : "Érték",
+DlgTextCharWidth : "Megjelenített karakterek száma",
+DlgTextMaxChars : "Maximális karakterszám",
+DlgTextType : "Típus",
+DlgTextTypeText : "Szöveg",
+DlgTextTypePass : "Jelszó",
+
+// Hidden Field Dialog
+DlgHiddenName : "Név",
+DlgHiddenValue : "Érték",
+
+// Bulleted List Dialog
+BulletedListProp : "Felsorolás tulajdonságai",
+NumberedListProp : "Számozás tulajdonságai",
+DlgLstStart : "Start",
+DlgLstType : "Formátum",
+DlgLstTypeCircle : "Kör",
+DlgLstTypeDisc : "Lemez",
+DlgLstTypeSquare : "Négyzet",
+DlgLstTypeNumbers : "Számok (1, 2, 3)",
+DlgLstTypeLCase : "Kisbetűk (a, b, c)",
+DlgLstTypeUCase : "Nagybetűk (A, B, C)",
+DlgLstTypeSRoman : "Kis római számok (i, ii, iii)",
+DlgLstTypeLRoman : "Nagy római számok (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Általános",
+DlgDocBackTab : "Háttér",
+DlgDocColorsTab : "Színek és margók",
+DlgDocMetaTab : "Meta adatok",
+
+DlgDocPageTitle : "Oldalcím",
+DlgDocLangDir : "Írás iránya",
+DlgDocLangDirLTR : "Balról jobbra",
+DlgDocLangDirRTL : "Jobbról balra",
+DlgDocLangCode : "Nyelv kód",
+DlgDocCharSet : "Karakterkódolás",
+DlgDocCharSetCE : "Közép-Európai",
+DlgDocCharSetCT : "Kínai Tradicionális (Big5)",
+DlgDocCharSetCR : "Cyrill",
+DlgDocCharSetGR : "Görög",
+DlgDocCharSetJP : "Japán",
+DlgDocCharSetKR : "Koreai",
+DlgDocCharSetTR : "Török",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Nyugat-Európai",
+DlgDocCharSetOther : "Más karakterkódolás",
+
+DlgDocDocType : "Dokumentum típus fejléc",
+DlgDocDocTypeOther : "Más dokumentum típus fejléc",
+DlgDocIncXHTML : "XHTML deklarációk beillesztése",
+DlgDocBgColor : "Háttérszín",
+DlgDocBgImage : "Háttérkép cím",
+DlgDocBgNoScroll : "Nem gördíthető háttér",
+DlgDocCText : "Szöveg",
+DlgDocCLink : "Cím",
+DlgDocCVisited : "Látogatott cím",
+DlgDocCActive : "Aktív cím",
+DlgDocMargins : "Oldal margók",
+DlgDocMaTop : "Felső",
+DlgDocMaLeft : "Bal",
+DlgDocMaRight : "Jobb",
+DlgDocMaBottom : "Alsó",
+DlgDocMeIndex : "Dokumentum keresőszavak (vesszővel elválasztva)",
+DlgDocMeDescr : "Dokumentum leírás",
+DlgDocMeAuthor : "Szerző",
+DlgDocMeCopy : "Szerzői jog",
+DlgDocPreview : "Előnézet",
+
+// Templates Dialog
+Templates : "Sablonok",
+DlgTemplatesTitle : "Elérhető sablonok",
+DlgTemplatesSelMsg : "Válassza ki melyik sablon nyíljon meg a szerkesztőben<br>(a jelenlegi tartalom elveszik):",
+DlgTemplatesLoading : "Sablon lista betöltése. Kis türelmet...",
+DlgTemplatesNoTpl : "(Nincs sablon megadva)",
+DlgTemplatesReplace : "Kicseréli a jelenlegi tartalmat",
+
+// About Dialog
+DlgAboutAboutTab : "Névjegy",
+DlgAboutBrowserInfoTab : "Böngésző információ",
+DlgAboutLicenseTab : "Licensz",
+DlgAboutVersion : "verzió",
+DlgAboutInfo : "További információkért látogasson el ide:"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/it.js b/httemplate/elements/fckeditor/editor/lang/it.js
new file mode 100644
index 000000000..a3dee1ba5
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/it.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Italian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Nascondi la barra degli strumenti",
+ToolbarExpand : "Mostra la barra degli strumenti",
+
+// Toolbar Items and Context Menu
+Save : "Salva",
+NewPage : "Nuova pagina vuota",
+Preview : "Anteprima",
+Cut : "Taglia",
+Copy : "Copia",
+Paste : "Incolla",
+PasteText : "Incolla come testo semplice",
+PasteWord : "Incolla da Word",
+Print : "Stampa",
+SelectAll : "Seleziona tutto",
+RemoveFormat : "Elimina formattazione",
+InsertLinkLbl : "Collegamento",
+InsertLink : "Inserisci/Modifica collegamento",
+RemoveLink : "Elimina collegamento",
+Anchor : "Inserisci/Modifica Ancora",
+InsertImageLbl : "Immagine",
+InsertImage : "Inserisci/Modifica immagine",
+InsertFlashLbl : "Oggetto Flash",
+InsertFlash : "Inserisci/Modifica Oggetto Flash",
+InsertTableLbl : "Tabella",
+InsertTable : "Inserisci/Modifica tabella",
+InsertLineLbl : "Riga orizzontale",
+InsertLine : "Inserisci riga orizzontale",
+InsertSpecialCharLbl: "Caratteri speciali",
+InsertSpecialChar : "Inserisci carattere speciale",
+InsertSmileyLbl : "Emoticon",
+InsertSmiley : "Inserisci emoticon",
+About : "Informazioni su FCKeditor",
+Bold : "Grassetto",
+Italic : "Corsivo",
+Underline : "Sottolineato",
+StrikeThrough : "Barrato",
+Subscript : "Pedice",
+Superscript : "Apice",
+LeftJustify : "Allinea a sinistra",
+CenterJustify : "Centra",
+RightJustify : "Allinea a destra",
+BlockJustify : "Giustifica",
+DecreaseIndent : "Riduci rientro",
+IncreaseIndent : "Aumenta rientro",
+Undo : "Annulla",
+Redo : "Ripristina",
+NumberedListLbl : "Elenco numerato",
+NumberedList : "Inserisci/Modifica elenco numerato",
+BulletedListLbl : "Elenco puntato",
+BulletedList : "Inserisci/Modifica elenco puntato",
+ShowTableBorders : "Mostra bordi tabelle",
+ShowDetails : "Mostra dettagli",
+Style : "Stile",
+FontFormat : "Formato",
+Font : "Font",
+FontSize : "Dimensione",
+TextColor : "Colore testo",
+BGColor : "Colore sfondo",
+Source : "Codice Sorgente",
+Find : "Trova",
+Replace : "Sostituisci",
+SpellCheck : "Correttore ortografico",
+UniversalKeyboard : "Tastiera universale",
+PageBreakLbl : "Interruzione di pagina",
+PageBreak : "Inserisci interruzione di pagina",
+
+Form : "Modulo",
+Checkbox : "Checkbox",
+RadioButton : "Radio Button",
+TextField : "Campo di testo",
+Textarea : "Area di testo",
+HiddenField : "Campo nascosto",
+Button : "Bottone",
+SelectionField : "Menu di selezione",
+ImageButton : "Bottone immagine",
+
+FitWindow : "Massimizza l'area dell'editor",
+
+// Context Menu
+EditLink : "Modifica collegamento",
+CellCM : "Cella",
+RowCM : "Riga",
+ColumnCM : "Colonna",
+InsertRow : "Inserisci riga",
+DeleteRows : "Elimina righe",
+InsertColumn : "Inserisci colonna",
+DeleteColumns : "Elimina colonne",
+InsertCell : "Inserisci cella",
+DeleteCells : "Elimina celle",
+MergeCells : "Unisce celle",
+SplitCell : "Dividi celle",
+TableDelete : "Cancella Tabella",
+CellProperties : "Proprietà cella",
+TableProperties : "Proprietà tabella",
+ImageProperties : "Proprietà immagine",
+FlashProperties : "Proprietà Oggetto Flash",
+
+AnchorProp : "Proprietà ancora",
+ButtonProp : "Proprietà bottone",
+CheckboxProp : "Proprietà checkbox",
+HiddenFieldProp : "Proprietà campo nascosto",
+RadioButtonProp : "Proprietà radio button",
+ImageButtonProp : "Proprietà bottone immagine",
+TextFieldProp : "Proprietà campo di testo",
+SelectionFieldProp : "Proprietà menu di selezione",
+TextareaProp : "Proprietà area di testo",
+FormProp : "Proprietà modulo",
+
+FontFormats : "Normale;Formattato;Indirizzo;Titolo 1;Titolo 2;Titolo 3;Titolo 4;Titolo 5;Titolo 6;Paragrafo (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Elaborazione XHTML in corso. Attendere prego...",
+Done : "Completato",
+PasteWordConfirm : "Il testo da incollare sembra provenire da Word. Desideri pulirlo prima di incollare?",
+NotCompatiblePaste : "Questa funzione è disponibile solo per Internet Explorer 5.5 o superiore. Desideri incollare il testo senza pulirlo?",
+UnknownToolbarItem : "Elemento della barra strumenti sconosciuto \"%1\"",
+UnknownCommand : "Comando sconosciuto \"%1\"",
+NotImplemented : "Comando non implementato",
+UnknownToolbarSet : "La barra di strumenti \"%1\" non esiste",
+NoActiveX : "Le impostazioni di sicurezza del tuo browser potrebbero limitare alcune funzionalità dell'editor. Devi abilitare l'opzione \"Esegui controlli e plug-in ActiveX\". Potresti avere errori e notare funzionalità mancanti.",
+BrowseServerBlocked : "Non è possibile aprire la finestra di espolorazione risorse. Verifica che tutti i blocca popup siano bloccati.",
+DialogBlocked : "Non è possibile aprire la finestra di dialogo. Verifica che tutti i blocca popup siano bloccati.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Annulla",
+DlgBtnClose : "Chiudi",
+DlgBtnBrowseServer : "Cerca sul server",
+DlgAdvancedTag : "Avanzate",
+DlgOpOther : "<Altro>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Devi inserire l'URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<non impostato>",
+DlgGenId : "Id",
+DlgGenLangDir : "Direzione scrittura",
+DlgGenLangDirLtr : "Da Sinistra a Destra (LTR)",
+DlgGenLangDirRtl : "Da Destra a Sinistra (RTL)",
+DlgGenLangCode : "Codice Lingua",
+DlgGenAccessKey : "Scorciatoia<br />da tastiera",
+DlgGenName : "Nome",
+DlgGenTabIndex : "Ordine di tabulazione",
+DlgGenLongDescr : "URL descrizione estesa",
+DlgGenClass : "Nome classe CSS",
+DlgGenTitle : "Titolo",
+DlgGenContType : "Tipo della risorsa collegata",
+DlgGenLinkCharset : "Set di caretteri della risorsa collegata",
+DlgGenStyle : "Stile",
+
+// Image Dialog
+DlgImgTitle : "Proprietà immagine",
+DlgImgInfoTab : "Informazioni immagine",
+DlgImgBtnUpload : "Invia al server",
+DlgImgURL : "URL",
+DlgImgUpload : "Carica",
+DlgImgAlt : "Testo alternativo",
+DlgImgWidth : "Larghezza",
+DlgImgHeight : "Altezza",
+DlgImgLockRatio : "Blocca rapporto",
+DlgBtnResetSize : "Reimposta dimensione",
+DlgImgBorder : "Bordo",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Allineamento",
+DlgImgAlignLeft : "Sinistra",
+DlgImgAlignAbsBottom: "In basso assoluto",
+DlgImgAlignAbsMiddle: "Centrato assoluto",
+DlgImgAlignBaseline : "Linea base",
+DlgImgAlignBottom : "In Basso",
+DlgImgAlignMiddle : "Centrato",
+DlgImgAlignRight : "Destra",
+DlgImgAlignTextTop : "In alto al testo",
+DlgImgAlignTop : "In Alto",
+DlgImgPreview : "Anteprima",
+DlgImgAlertUrl : "Devi inserire l'URL per l'immagine",
+DlgImgLinkTab : "Collegamento",
+
+// Flash Dialog
+DlgFlashTitle : "Proprietà Oggetto Flash",
+DlgFlashChkPlay : "Avvio Automatico",
+DlgFlashChkLoop : "Cicla",
+DlgFlashChkMenu : "Abilita Menu di Flash",
+DlgFlashScale : "Ridimensiona",
+DlgFlashScaleAll : "Mostra Tutto",
+DlgFlashScaleNoBorder : "Senza Bordo",
+DlgFlashScaleFit : "Dimensione Esatta",
+
+// Link Dialog
+DlgLnkWindowTitle : "Collegamento",
+DlgLnkInfoTab : "Informazioni collegamento",
+DlgLnkTargetTab : "Destinazione",
+
+DlgLnkType : "Tipo di Collegamento",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ancora nella pagina",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocollo",
+DlgLnkProtoOther : "<altro>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Scegli Ancora",
+DlgLnkAnchorByName : "Per Nome",
+DlgLnkAnchorById : "Per id elemento",
+DlgLnkNoAnchors : "<Nessuna ancora disponibile nel documento>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Indirizzo E-Mail",
+DlgLnkEMailSubject : "Oggetto del messaggio",
+DlgLnkEMailBody : "Corpo del messaggio",
+DlgLnkUpload : "Carica",
+DlgLnkBtnUpload : "Invia al Server",
+
+DlgLnkTarget : "Destinazione",
+DlgLnkTargetFrame : "<riquadro>",
+DlgLnkTargetPopup : "<finestra popup>",
+DlgLnkTargetBlank : "Nuova finestra (_blank)",
+DlgLnkTargetParent : "Finestra padre (_parent)",
+DlgLnkTargetSelf : "Stessa finestra (_self)",
+DlgLnkTargetTop : "Finestra superiore (_top)",
+DlgLnkTargetFrameName : "Nome del riquadro di destinazione",
+DlgLnkPopWinName : "Nome finestra popup",
+DlgLnkPopWinFeat : "Caratteristiche finestra popup",
+DlgLnkPopResize : "Ridimensionabile",
+DlgLnkPopLocation : "Barra degli indirizzi",
+DlgLnkPopMenu : "Barra del menu",
+DlgLnkPopScroll : "Barre di scorrimento",
+DlgLnkPopStatus : "Barra di stato",
+DlgLnkPopToolbar : "Barra degli strumenti",
+DlgLnkPopFullScrn : "A tutto schermo (IE)",
+DlgLnkPopDependent : "Dipendente (Netscape)",
+DlgLnkPopWidth : "Larghezza",
+DlgLnkPopHeight : "Altezza",
+DlgLnkPopLeft : "Posizione da sinistra",
+DlgLnkPopTop : "Posizione dall'alto",
+
+DlnLnkMsgNoUrl : "Devi inserire l'URL del collegamento",
+DlnLnkMsgNoEMail : "Devi inserire un'indirizzo e-mail",
+DlnLnkMsgNoAnchor : "Devi selezionare un'ancora",
+DlnLnkMsgInvPopName : "Il nome del popup deve iniziare con una lettera, e non può contenere spazi",
+
+// Color Dialog
+DlgColorTitle : "Seleziona colore",
+DlgColorBtnClear : "Vuota",
+DlgColorHighlight : "Evidenziato",
+DlgColorSelected : "Selezionato",
+
+// Smiley Dialog
+DlgSmileyTitle : "Inserisci emoticon",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Seleziona carattere speciale",
+
+// Table Dialog
+DlgTableTitle : "Proprietà tabella",
+DlgTableRows : "Righe",
+DlgTableColumns : "Colonne",
+DlgTableBorder : "Dimensione bordo",
+DlgTableAlign : "Allineamento",
+DlgTableAlignNotSet : "<non impostato>",
+DlgTableAlignLeft : "Sinistra",
+DlgTableAlignCenter : "Centrato",
+DlgTableAlignRight : "Destra",
+DlgTableWidth : "Larghezza",
+DlgTableWidthPx : "pixel",
+DlgTableWidthPc : "percento",
+DlgTableHeight : "Altezza",
+DlgTableCellSpace : "Spaziatura celle",
+DlgTableCellPad : "Padding celle",
+DlgTableCaption : "Intestazione",
+DlgTableSummary : "Indice",
+
+// Table Cell Dialog
+DlgCellTitle : "Proprietà cella",
+DlgCellWidth : "Larghezza",
+DlgCellWidthPx : "pixel",
+DlgCellWidthPc : "percento",
+DlgCellHeight : "Altezza",
+DlgCellWordWrap : "A capo automatico",
+DlgCellWordWrapNotSet : "<non impostato>",
+DlgCellWordWrapYes : "Si",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "Allineamento orizzontale",
+DlgCellHorAlignNotSet : "<non impostato>",
+DlgCellHorAlignLeft : "Sinistra",
+DlgCellHorAlignCenter : "Centrato",
+DlgCellHorAlignRight: "Destra",
+DlgCellVerAlign : "Allineamento verticale",
+DlgCellVerAlignNotSet : "<non impostato>",
+DlgCellVerAlignTop : "In Alto",
+DlgCellVerAlignMiddle : "Centrato",
+DlgCellVerAlignBottom : "In Basso",
+DlgCellVerAlignBaseline : "Linea base",
+DlgCellRowSpan : "Righe occupate",
+DlgCellCollSpan : "Colonne occupate",
+DlgCellBackColor : "Colore sfondo",
+DlgCellBorderColor : "Colore bordo",
+DlgCellBtnSelect : "Scegli...",
+
+// Find Dialog
+DlgFindTitle : "Trova",
+DlgFindFindBtn : "Trova",
+DlgFindNotFoundMsg : "L'elemento cercato non è stato trovato.",
+
+// Replace Dialog
+DlgReplaceTitle : "Sostituisci",
+DlgReplaceFindLbl : "Trova:",
+DlgReplaceReplaceLbl : "Sostituisci con:",
+DlgReplaceCaseChk : "Maiuscole/minuscole",
+DlgReplaceReplaceBtn : "Sostituisci",
+DlgReplaceReplAllBtn : "Sostituisci tutto",
+DlgReplaceWordChk : "Solo parole intere",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl+X).",
+PasteErrorCopy : "Le impostazioni di sicurezza del browser non permettono di copiare automaticamente il testo. Usa la tastiera (Ctrl+C).",
+
+PasteAsText : "Incolla come testo semplice",
+PasteFromWord : "Incolla da Word",
+
+DlgPasteMsg2 : "Incolla il testo all'interno dell'area sottostante usando la scorciatoia di tastiere (<STRONG>Ctrl+V</STRONG>) e premi <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignora le definizioni di Font",
+DlgPasteRemoveStyles : "Rimuovi le definizioni di Stile",
+DlgPasteCleanBox : "Svuota area di testo",
+
+// Color Picker
+ColorAutomatic : "Automatico",
+ColorMoreColors : "Altri colori...",
+
+// Document Properties
+DocProps : "Proprietà del Documento",
+
+// Anchor Dialog
+DlgAnchorTitle : "Proprietà ancora",
+DlgAnchorName : "Nome ancora",
+DlgAnchorErrorName : "Inserici il nome dell'ancora",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Non nel dizionario",
+DlgSpellChangeTo : "Cambia in",
+DlgSpellBtnIgnore : "Ignora",
+DlgSpellBtnIgnoreAll : "Ignora tutto",
+DlgSpellBtnReplace : "Cambia",
+DlgSpellBtnReplaceAll : "Cambia tutto",
+DlgSpellBtnUndo : "Annulla",
+DlgSpellNoSuggestions : "- Nessun suggerimento -",
+DlgSpellProgress : "Controllo ortografico in corso",
+DlgSpellNoMispell : "Controllo ortografico completato: nessun errore trovato",
+DlgSpellNoChanges : "Controllo ortografico completato: nessuna parola cambiata",
+DlgSpellOneChange : "Controllo ortografico completato: 1 parola cambiata",
+DlgSpellManyChanges : "Controllo ortografico completato: %1 parole cambiate",
+
+IeSpellDownload : "Contollo ortografico non installato. Lo vuoi scaricare ora?",
+
+// Button Dialog
+DlgButtonText : "Testo (Value)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Bottone",
+DlgButtonTypeSbm : "Invio",
+DlgButtonTypeRst : "Annulla",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nome",
+DlgCheckboxValue : "Valore",
+DlgCheckboxSelected : "Selezionato",
+
+// Form Dialog
+DlgFormName : "Nome",
+DlgFormAction : "Azione",
+DlgFormMethod : "Metodo",
+
+// Select Field Dialog
+DlgSelectName : "Nome",
+DlgSelectValue : "Valore",
+DlgSelectSize : "Dimensione",
+DlgSelectLines : "righe",
+DlgSelectChkMulti : "Permetti selezione multipla",
+DlgSelectOpAvail : "Opzioni disponibili",
+DlgSelectOpText : "Testo",
+DlgSelectOpValue : "Valore",
+DlgSelectBtnAdd : "Aggiungi",
+DlgSelectBtnModify : "Modifica",
+DlgSelectBtnUp : "Su",
+DlgSelectBtnDown : "Gi",
+DlgSelectBtnSetValue : "Imposta come predefinito",
+DlgSelectBtnDelete : "Rimuovi",
+
+// Textarea Dialog
+DlgTextareaName : "Nome",
+DlgTextareaCols : "Colonne",
+DlgTextareaRows : "Righe",
+
+// Text Field Dialog
+DlgTextName : "Nome",
+DlgTextValue : "Valore",
+DlgTextCharWidth : "Larghezza",
+DlgTextMaxChars : "Numero massimo di caratteri",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Testo",
+DlgTextTypePass : "Password",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nome",
+DlgHiddenValue : "Valore",
+
+// Bulleted List Dialog
+BulletedListProp : "Proprietà lista puntata",
+NumberedListProp : "Proprietà lista numerata",
+DlgLstStart : "Inizio",
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Tondo",
+DlgLstTypeDisc : "Disco",
+DlgLstTypeSquare : "Quadrato",
+DlgLstTypeNumbers : "Numeri (1, 2, 3)",
+DlgLstTypeLCase : "Caratteri minuscoli (a, b, c)",
+DlgLstTypeUCase : "Caratteri maiuscoli (A, B, C)",
+DlgLstTypeSRoman : "Numeri Romani minuscoli (i, ii, iii)",
+DlgLstTypeLRoman : "Numeri Romani maiuscoli (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Genarale",
+DlgDocBackTab : "Sfondo",
+DlgDocColorsTab : "Colori e margini",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Titolo pagina",
+DlgDocLangDir : "Direzione scrittura",
+DlgDocLangDirLTR : "Da Sinistra a Destra (LTR)",
+DlgDocLangDirRTL : "Da Destra a Sinistra (RTL)",
+DlgDocLangCode : "Codice Lingua",
+DlgDocCharSet : "Set di caretteri",
+DlgDocCharSetCE : "Europa Centrale",
+DlgDocCharSetCT : "Cinese Tradizionale (Big5)",
+DlgDocCharSetCR : "Cirillico",
+DlgDocCharSetGR : "Greco",
+DlgDocCharSetJP : "Giapponese",
+DlgDocCharSetKR : "Coreano",
+DlgDocCharSetTR : "Turco",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Europa Occidentale",
+DlgDocCharSetOther : "Altro set di caretteri",
+
+DlgDocDocType : "Intestazione DocType",
+DlgDocDocTypeOther : "Altra intestazione DocType",
+DlgDocIncXHTML : "Includi dichiarazione XHTML",
+DlgDocBgColor : "Colore di sfondo",
+DlgDocBgImage : "Immagine di sfondo",
+DlgDocBgNoScroll : "Sfondo fissato",
+DlgDocCText : "Testo",
+DlgDocCLink : "Collegamento",
+DlgDocCVisited : "Collegamento visitato",
+DlgDocCActive : "Collegamento attivo",
+DlgDocMargins : "Margini",
+DlgDocMaTop : "In Alto",
+DlgDocMaLeft : "A Sinistra",
+DlgDocMaRight : "A Destra",
+DlgDocMaBottom : "In Basso",
+DlgDocMeIndex : "Chiavi di indicizzazione documento (separate da virgola)",
+DlgDocMeDescr : "Descrizione documento",
+DlgDocMeAuthor : "Autore",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Anteprima",
+
+// Templates Dialog
+Templates : "Modelli",
+DlgTemplatesTitle : "Contenuto dei modelli",
+DlgTemplatesSelMsg : "Seleziona il modello da aprire nell'editor<br />(il contenuto attuale verrà eliminato):",
+DlgTemplatesLoading : "Caricamento modelli in corso. Attendere prego...",
+DlgTemplatesNoTpl : "(Nessun modello definito)",
+DlgTemplatesReplace : "Cancella il contenuto corrente",
+
+// About Dialog
+DlgAboutAboutTab : "Informazioni",
+DlgAboutBrowserInfoTab : "Informazioni Browser",
+DlgAboutLicenseTab : "Licenza",
+DlgAboutVersion : "versione",
+DlgAboutInfo : "Per maggiori informazioni visitare"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ja.js b/httemplate/elements/fckeditor/editor/lang/ja.js
new file mode 100644
index 000000000..c567d2187
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ja.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Japanese language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "ツールバーを隠す",
+ToolbarExpand : "ツールバーを表示",
+
+// Toolbar Items and Context Menu
+Save : "保存",
+NewPage : "新しいページ",
+Preview : "プレビュー",
+Cut : "切り取り",
+Copy : "コピー",
+Paste : "貼り付け",
+PasteText : "プレーンテキスト貼り付け",
+PasteWord : "ワード文章から貼り付け",
+Print : "印刷",
+SelectAll : "すべて選択",
+RemoveFormat : "フォーマット削除",
+InsertLinkLbl : "リンク",
+InsertLink : "リンク挿入/編集",
+RemoveLink : "リンク削除",
+Anchor : "アンカー挿入/編集",
+InsertImageLbl : "イメージ",
+InsertImage : "イメージ挿入/編集",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash挿入/編集",
+InsertTableLbl : "テーブル",
+InsertTable : "テーブル挿入/編集",
+InsertLineLbl : "ライン",
+InsertLine : "横罫線",
+InsertSpecialCharLbl: "特殊文字",
+InsertSpecialChar : "特殊文字挿入",
+InsertSmileyLbl : "絵文字",
+InsertSmiley : "絵文字挿入",
+About : "FCKeditorヘルプ",
+Bold : "太字",
+Italic : "斜体",
+Underline : "下線",
+StrikeThrough : "打ち消し線",
+Subscript : "添え字",
+Superscript : "上付き文字",
+LeftJustify : "左揃え",
+CenterJustify : "中央揃え",
+RightJustify : "右揃え",
+BlockJustify : "両端揃え",
+DecreaseIndent : "インデント解除",
+IncreaseIndent : "インデント",
+Undo : "元に戻す",
+Redo : "やり直し",
+NumberedListLbl : "段落番号",
+NumberedList : "段落番号の追加/削除",
+BulletedListLbl : "箇条書き",
+BulletedList : "箇条書きの追加/削除",
+ShowTableBorders : "テーブルボーダー表示",
+ShowDetails : "詳細表示",
+Style : "スタイル",
+FontFormat : "フォーマット",
+Font : "フォント",
+FontSize : "サイズ",
+TextColor : "テキスト色",
+BGColor : "背景色",
+Source : "ソース",
+Find : "検索",
+Replace : "置き換え",
+SpellCheck : "スペルチェック",
+UniversalKeyboard : "ユニバーサル・キーボード",
+PageBreakLbl : "改ページ",
+PageBreak : "改ページ挿入",
+
+Form : "フォーム",
+Checkbox : "チェックボックス",
+RadioButton : "ラジオボタン",
+TextField : "1行テキスト",
+Textarea : "テキストエリア",
+HiddenField : "不可視フィールド",
+Button : "ボタン",
+SelectionField : "選択フィールド",
+ImageButton : "画像ボタン",
+
+FitWindow : "エディタサイズを最大にします",
+
+// Context Menu
+EditLink : "リンク編集",
+CellCM : "セル",
+RowCM : "行",
+ColumnCM : "カラム",
+InsertRow : "行挿入",
+DeleteRows : "行削除",
+InsertColumn : "列挿入",
+DeleteColumns : "列削除",
+InsertCell : "セル挿入",
+DeleteCells : "セル削除",
+MergeCells : "セル結合",
+SplitCell : "セル分割",
+TableDelete : "テーブル削除",
+CellProperties : "セル プロパティ",
+TableProperties : "テーブル プロパティ",
+ImageProperties : "イメージ プロパティ",
+FlashProperties : "Flash プロパティ",
+
+AnchorProp : "アンカー プロパティ",
+ButtonProp : "ボタン プロパティ",
+CheckboxProp : "チェックボックス プロパティ",
+HiddenFieldProp : "不可視フィールド プロパティ",
+RadioButtonProp : "ラジオボタン プロパティ",
+ImageButtonProp : "画像ボタン プロパティ",
+TextFieldProp : "1行テキスト プロパティ",
+SelectionFieldProp : "選択フィールド プロパティ",
+TextareaProp : "テキストエリア プロパティ",
+FormProp : "フォーム プロパティ",
+
+FontFormats : "標準;書式付き;アドレス;見出し 1;見出し 2;見出し 3;見出し 4;見出し 5;見出し 6;標準 (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML処理中. しばらくお待ちください...",
+Done : "完了",
+PasteWordConfirm : "貼り付けを行うテキストは、ワード文章からコピーされようとしています。貼り付ける前にクリーニングを行いますか?",
+NotCompatiblePaste : "このコマンドはインターネット・エクスプローラーバージョン5.5以上で利用可能です。クリーニングしないで貼り付けを行いますか?",
+UnknownToolbarItem : "未知のツールバー項目 \"%1\"",
+UnknownCommand : "未知のコマンド名 \"%1\"",
+NotImplemented : "コマンドはインプリメントされませんでした。",
+UnknownToolbarSet : "ツールバー設定 \"%1\" 存在しません。",
+NoActiveX : "エラー、警告メッセージなどが発生した場合、ブラウザーのセキュリティ設定によりエディタのいくつかの機能が制限されている可能性があります。セキュリティ設定のオプションで\"ActiveXコントロールとプラグインの実行\"を有効にするにしてください。",
+BrowseServerBlocked : "サーバーブラウザーを開くことができませんでした。ポップアップ・ブロック機能が無効になっているか確認してください。",
+DialogBlocked : "ダイアログウィンドウを開くことができませんでした。ポップアップ・ブロック機能が無効になっているか確認してください。",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "キャンセル",
+DlgBtnClose : "閉じる",
+DlgBtnBrowseServer : "サーバーブラウザー",
+DlgAdvancedTag : "高度な設定",
+DlgOpOther : "<その他>",
+DlgInfoTab : "情報",
+DlgAlertUrl : "URLを挿入してください",
+
+// General Dialogs Labels
+DlgGenNotSet : "<なし>",
+DlgGenId : "Id",
+DlgGenLangDir : "文字表記の方向",
+DlgGenLangDirLtr : "左から右 (LTR)",
+DlgGenLangDirRtl : "右から左 (RTL)",
+DlgGenLangCode : "言語コード",
+DlgGenAccessKey : "アクセスキー",
+DlgGenName : "Name属性",
+DlgGenTabIndex : "タブインデックス",
+DlgGenLongDescr : "longdesc属性(長文説明)",
+DlgGenClass : "スタイルシートクラス",
+DlgGenTitle : "Title属性",
+DlgGenContType : "Content Type属性",
+DlgGenLinkCharset : "リンクcharset属性",
+DlgGenStyle : "スタイルシート",
+
+// Image Dialog
+DlgImgTitle : "イメージ プロパティ",
+DlgImgInfoTab : "イメージ 情報",
+DlgImgBtnUpload : "サーバーに送信",
+DlgImgURL : "URL",
+DlgImgUpload : "アップロード",
+DlgImgAlt : "代替テキスト",
+DlgImgWidth : "幅",
+DlgImgHeight : "高さ",
+DlgImgLockRatio : "ロック比率",
+DlgBtnResetSize : "サイズリセット",
+DlgImgBorder : "ボーダー",
+DlgImgHSpace : "横間隔",
+DlgImgVSpace : "縦間隔",
+DlgImgAlign : "行揃え",
+DlgImgAlignLeft : "左",
+DlgImgAlignAbsBottom: "下部(絶対的)",
+DlgImgAlignAbsMiddle: "中央(絶対的)",
+DlgImgAlignBaseline : "ベースライン",
+DlgImgAlignBottom : "下",
+DlgImgAlignMiddle : "中央",
+DlgImgAlignRight : "右",
+DlgImgAlignTextTop : "テキスト上部",
+DlgImgAlignTop : "上",
+DlgImgPreview : "プレビュー",
+DlgImgAlertUrl : "イメージのURLを入力してください。",
+DlgImgLinkTab : "リンク",
+
+// Flash Dialog
+DlgFlashTitle : "Flash プロパティ",
+DlgFlashChkPlay : "再生",
+DlgFlashChkLoop : "ループ再生",
+DlgFlashChkMenu : "Flashメニュー可能",
+DlgFlashScale : "拡大縮小設定",
+DlgFlashScaleAll : "すべて表示",
+DlgFlashScaleNoBorder : "外が見えない様に拡大",
+DlgFlashScaleFit : "上下左右にフィット",
+
+// Link Dialog
+DlgLnkWindowTitle : "ハイパーリンク",
+DlgLnkInfoTab : "ハイパーリンク 情報",
+DlgLnkTargetTab : "ターゲット",
+
+DlgLnkType : "リンクタイプ",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "このページのアンカー",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "プロトコル",
+DlgLnkProtoOther : "<その他>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "アンカーを選択",
+DlgLnkAnchorByName : "アンカー名",
+DlgLnkAnchorById : "エレメントID",
+DlgLnkNoAnchors : "<ドキュメントにおいて利用可能なアンカーはありません。>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail アドレス",
+DlgLnkEMailSubject : "件名",
+DlgLnkEMailBody : "本文",
+DlgLnkUpload : "アップロード",
+DlgLnkBtnUpload : "サーバーに送信",
+
+DlgLnkTarget : "ターゲット",
+DlgLnkTargetFrame : "<フレーム>",
+DlgLnkTargetPopup : "<ポップアップウィンドウ>",
+DlgLnkTargetBlank : "新しいウィンドウ (_blank)",
+DlgLnkTargetParent : "親ウィンドウ (_parent)",
+DlgLnkTargetSelf : "同じウィンドウ (_self)",
+DlgLnkTargetTop : "最上位ウィンドウ (_top)",
+DlgLnkTargetFrameName : "目的のフレーム名",
+DlgLnkPopWinName : "ポップアップウィンドウ名",
+DlgLnkPopWinFeat : "ポップアップウィンドウ特徴",
+DlgLnkPopResize : "リサイズ可能",
+DlgLnkPopLocation : "ロケーションバー",
+DlgLnkPopMenu : "メニューバー",
+DlgLnkPopScroll : "スクロールバー",
+DlgLnkPopStatus : "ステータスバー",
+DlgLnkPopToolbar : "ツールバー",
+DlgLnkPopFullScrn : "全画面モード(IE)",
+DlgLnkPopDependent : "開いたウィンドウに連動して閉じる (Netscape)",
+DlgLnkPopWidth : "幅",
+DlgLnkPopHeight : "高さ",
+DlgLnkPopLeft : "左端からの座標で指定",
+DlgLnkPopTop : "上端からの座標で指定",
+
+DlnLnkMsgNoUrl : "リンクURLを入力してください。",
+DlnLnkMsgNoEMail : "メールアドレスを入力してください。",
+DlnLnkMsgNoAnchor : "アンカーを選択してください。",
+DlnLnkMsgInvPopName : "ポップ・アップ名は英字で始まる文字で指定してくだい。ポップ・アップ名にスペースは含めません",
+
+// Color Dialog
+DlgColorTitle : "色選択",
+DlgColorBtnClear : "クリア",
+DlgColorHighlight : "ハイライト",
+DlgColorSelected : "選択色",
+
+// Smiley Dialog
+DlgSmileyTitle : "顔文字挿入",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "特殊文字選択",
+
+// Table Dialog
+DlgTableTitle : "テーブル プロパティ",
+DlgTableRows : "行",
+DlgTableColumns : "列",
+DlgTableBorder : "ボーダーサイズ",
+DlgTableAlign : "キャプションの整列",
+DlgTableAlignNotSet : "<なし>",
+DlgTableAlignLeft : "左",
+DlgTableAlignCenter : "中央",
+DlgTableAlignRight : "右",
+DlgTableWidth : "テーブル幅",
+DlgTableWidthPx : "ピクセル",
+DlgTableWidthPc : "パーセント",
+DlgTableHeight : "テーブル高さ",
+DlgTableCellSpace : "セル内余白",
+DlgTableCellPad : "セル内間隔",
+DlgTableCaption : "キャプション",
+DlgTableSummary : "テーブル目的/構造",
+
+// Table Cell Dialog
+DlgCellTitle : "セル プロパティ",
+DlgCellWidth : "幅",
+DlgCellWidthPx : "ピクセル",
+DlgCellWidthPc : "パーセント",
+DlgCellHeight : "高さ",
+DlgCellWordWrap : "折り返し",
+DlgCellWordWrapNotSet : "<なし>",
+DlgCellWordWrapYes : "Yes",
+DlgCellWordWrapNo : "No",
+DlgCellHorAlign : "セル横の整列",
+DlgCellHorAlignNotSet : "<なし>",
+DlgCellHorAlignLeft : "左",
+DlgCellHorAlignCenter : "中央",
+DlgCellHorAlignRight: "右",
+DlgCellVerAlign : "セル縦の整列",
+DlgCellVerAlignNotSet : "<なし>",
+DlgCellVerAlignTop : "上",
+DlgCellVerAlignMiddle : "中央",
+DlgCellVerAlignBottom : "下",
+DlgCellVerAlignBaseline : "ベースライン",
+DlgCellRowSpan : "縦幅(行数)",
+DlgCellCollSpan : "横幅(列数)",
+DlgCellBackColor : "背景色",
+DlgCellBorderColor : "ボーダーカラー",
+DlgCellBtnSelect : "選択...",
+
+// Find Dialog
+DlgFindTitle : "検索",
+DlgFindFindBtn : "検索",
+DlgFindNotFoundMsg : "指定された文字列は見つかりませんでした。",
+
+// Replace Dialog
+DlgReplaceTitle : "置き換え",
+DlgReplaceFindLbl : "検索する文字列:",
+DlgReplaceReplaceLbl : "置換えする文字列:",
+DlgReplaceCaseChk : "部分一致",
+DlgReplaceReplaceBtn : "置換え",
+DlgReplaceReplAllBtn : "すべて置換え",
+DlgReplaceWordChk : "単語単位で一致",
+
+// Paste Operations / Dialog
+PasteErrorCut : "ブラウザーのセキュリティ設定によりエディタの切り取り操作が自動で実行することができません。実行するには手動でキーボードの(Ctrl+X)を使用してください。",
+PasteErrorCopy : "ブラウザーのセキュリティ設定によりエディタのコピー操作が自動で実行することができません。実行するには手動でキーボードの(Ctrl+C)を使用してください。",
+
+PasteAsText : "プレーンテキスト貼り付け",
+PasteFromWord : "ワード文章から貼り付け",
+
+DlgPasteMsg2 : "キーボード(<STRONG>Ctrl+V</STRONG>)を使用して、次の入力エリア内で貼って、<STRONG>OK</STRONG>を押してください。",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "FontタグのFace属性を無視します。",
+DlgPasteRemoveStyles : "スタイル定義を削除します。",
+DlgPasteCleanBox : "入力エリアクリア",
+
+// Color Picker
+ColorAutomatic : "自動",
+ColorMoreColors : "その他の色...",
+
+// Document Properties
+DocProps : "文書 プロパティ",
+
+// Anchor Dialog
+DlgAnchorTitle : "アンカー プロパティ",
+DlgAnchorName : "アンカー名",
+DlgAnchorErrorName : "アンカー名を必ず入力してください。",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "辞書にありません",
+DlgSpellChangeTo : "変更",
+DlgSpellBtnIgnore : "無視",
+DlgSpellBtnIgnoreAll : "すべて無視",
+DlgSpellBtnReplace : "置換",
+DlgSpellBtnReplaceAll : "すべて置換",
+DlgSpellBtnUndo : "やり直し",
+DlgSpellNoSuggestions : "- 該当なし -",
+DlgSpellProgress : "スペルチェック処理中...",
+DlgSpellNoMispell : "スペルチェック完了: スペルの誤りはありませんでした",
+DlgSpellNoChanges : "スペルチェック完了: 語句は変更されませんでした",
+DlgSpellOneChange : "スペルチェック完了: 1語句変更されました",
+DlgSpellManyChanges : "スペルチェック完了: %1 語句変更されました",
+
+IeSpellDownload : "スペルチェッカーがインストールされていません。今すぐダウンロードしますか?",
+
+// Button Dialog
+DlgButtonText : "テキスト (値)",
+DlgButtonType : "タイプ",
+DlgButtonTypeBtn : "ボタン",
+DlgButtonTypeSbm : "送信",
+DlgButtonTypeRst : "リセット",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "名前",
+DlgCheckboxValue : "値",
+DlgCheckboxSelected : "選択済み",
+
+// Form Dialog
+DlgFormName : "フォーム名",
+DlgFormAction : "アクション",
+DlgFormMethod : "メソッド",
+
+// Select Field Dialog
+DlgSelectName : "名前",
+DlgSelectValue : "値",
+DlgSelectSize : "サイズ",
+DlgSelectLines : "行",
+DlgSelectChkMulti : "複数項目選択を許可",
+DlgSelectOpAvail : "利用可能なオプション",
+DlgSelectOpText : "選択項目名",
+DlgSelectOpValue : "選択項目値",
+DlgSelectBtnAdd : "追加",
+DlgSelectBtnModify : "編集",
+DlgSelectBtnUp : "上へ",
+DlgSelectBtnDown : "下へ",
+DlgSelectBtnSetValue : "選択した値を設定",
+DlgSelectBtnDelete : "削除",
+
+// Textarea Dialog
+DlgTextareaName : "名前",
+DlgTextareaCols : "列",
+DlgTextareaRows : "行",
+
+// Text Field Dialog
+DlgTextName : "名前",
+DlgTextValue : "値",
+DlgTextCharWidth : "サイズ",
+DlgTextMaxChars : "最大長",
+DlgTextType : "タイプ",
+DlgTextTypeText : "テキスト",
+DlgTextTypePass : "パスワード入力",
+
+// Hidden Field Dialog
+DlgHiddenName : "名前",
+DlgHiddenValue : "値",
+
+// Bulleted List Dialog
+BulletedListProp : "箇条書き プロパティ",
+NumberedListProp : "段落番号 プロパティ",
+DlgLstStart : "開始文字",
+DlgLstType : "タイプ",
+DlgLstTypeCircle : "白丸",
+DlgLstTypeDisc : "黒丸",
+DlgLstTypeSquare : "四角",
+DlgLstTypeNumbers : "アラビア数字 (1, 2, 3)",
+DlgLstTypeLCase : "英字小文字 (a, b, c)",
+DlgLstTypeUCase : "英字大文字 (A, B, C)",
+DlgLstTypeSRoman : "ローマ数字小文字 (i, ii, iii)",
+DlgLstTypeLRoman : "ローマ数字大文字 (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "全般",
+DlgDocBackTab : "背景",
+DlgDocColorsTab : "色とマージン",
+DlgDocMetaTab : "メタデータ",
+
+DlgDocPageTitle : "ページタイトル",
+DlgDocLangDir : "言語文字表記の方向",
+DlgDocLangDirLTR : "左から右に表記(LTR)",
+DlgDocLangDirRTL : "右から左に表記(RTL)",
+DlgDocLangCode : "言語コード",
+DlgDocCharSet : "文字セット符号化",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "他の文字セット符号化",
+
+DlgDocDocType : "文書タイプヘッダー",
+DlgDocDocTypeOther : "その他文書タイプヘッダー",
+DlgDocIncXHTML : "XHTML宣言をインクルード",
+DlgDocBgColor : "背景色",
+DlgDocBgImage : "背景画像 URL",
+DlgDocBgNoScroll : "スクロールしない背景",
+DlgDocCText : "テキスト",
+DlgDocCLink : "リンク",
+DlgDocCVisited : "アクセス済みリンク",
+DlgDocCActive : "アクセス中リンク",
+DlgDocMargins : "ページ・マージン",
+DlgDocMaTop : "上部",
+DlgDocMaLeft : "左",
+DlgDocMaRight : "右",
+DlgDocMaBottom : "下部",
+DlgDocMeIndex : "文書のキーワード(カンマ区切り)",
+DlgDocMeDescr : "文書の概要",
+DlgDocMeAuthor : "文書の作者",
+DlgDocMeCopy : "文書の著作権",
+DlgDocPreview : "プレビュー",
+
+// Templates Dialog
+Templates : "テンプレート(雛形)",
+DlgTemplatesTitle : "テンプレート内容",
+DlgTemplatesSelMsg : "エディターで使用するテンプレートを選択してください。<br>(現在のエディタの内容は失われます):",
+DlgTemplatesLoading : "テンプレート一覧読み込み中. しばらくお待ちください...",
+DlgTemplatesNoTpl : "(テンプレートが定義されていません)",
+DlgTemplatesReplace : "現在のエディタの内容と置換えをします",
+
+// About Dialog
+DlgAboutAboutTab : "バージョン情報",
+DlgAboutBrowserInfoTab : "ブラウザ情報",
+DlgAboutLicenseTab : "ライセンス",
+DlgAboutVersion : "バージョン",
+DlgAboutInfo : "より詳しい情報はこちらで"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/km.js b/httemplate/elements/fckeditor/editor/lang/km.js
new file mode 100644
index 000000000..e90291f71
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/km.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Khmer language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "បង្រួមរបាឧបរកណ៍",
+ToolbarExpand : "ពង្រីករបាឧបរណ៍",
+
+// Toolbar Items and Context Menu
+Save : "រក្សាទុក",
+NewPage : "ទំព័រថ្មី",
+Preview : "មើលសាកល្បង",
+Cut : "កាត់យក",
+Copy : "ចំលងយក",
+Paste : "ចំលងដាក់",
+PasteText : "ចំលងដាក់ជាអត្ថបទធម្មតា",
+PasteWord : "ចំលងដាក់ពី Word",
+Print : "បោះពុម្ភ",
+SelectAll : "ជ្រើសរើសទាំងអស់",
+RemoveFormat : "លប់ចោល ការរចនា",
+InsertLinkLbl : "ឈ្នាប់",
+InsertLink : "បន្ថែម/កែប្រែ ឈ្នាប់",
+RemoveLink : "លប់ឈ្នាប់",
+Anchor : "បន្ថែម/កែប្រែ យុថ្កា",
+InsertImageLbl : "រូបភាព",
+InsertImage : "បន្ថែម/កែប្រែ រូបភាព",
+InsertFlashLbl : "Flash",
+InsertFlash : "បន្ថែម/កែប្រែ Flash",
+InsertTableLbl : "តារាង",
+InsertTable : "បន្ថែម/កែប្រែ តារាង",
+InsertLineLbl : "បន្ទាត់",
+InsertLine : "បន្ថែមបន្ទាត់ផ្តេក",
+InsertSpecialCharLbl: "អក្សរពិសេស",
+InsertSpecialChar : "បន្ថែមអក្សរពិសេស",
+InsertSmileyLbl : "រូបភាព",
+InsertSmiley : "បន្ថែម រូបភាព",
+About : "អំពី FCKeditor",
+Bold : "អក្សរដិតធំ",
+Italic : "អក្សរផ្តេក",
+Underline : "ដិតបន្ទាត់ពីក្រោមអក្សរ",
+StrikeThrough : "ដិតបន្ទាត់ពាក់កណ្តាលអក្សរ",
+Subscript : "អក្សរតូចក្រោម",
+Superscript : "អក្សរតូចលើ",
+LeftJustify : "តំរឹមឆ្វេង",
+CenterJustify : "តំរឹមកណ្តាល",
+RightJustify : "តំរឹមស្តាំ",
+BlockJustify : "តំរឹមសងខាង",
+DecreaseIndent : "បន្ថយការចូលបន្ទាត់",
+IncreaseIndent : "បន្ថែមការចូលបន្ទាត់",
+Undo : "សារឡើងវិញ",
+Redo : "ធ្វើឡើងវិញ",
+NumberedListLbl : "បញ្ជីជាអក្សរ",
+NumberedList : "បន្ថែម/លប់ បញ្ជីជាអក្សរ",
+BulletedListLbl : "បញ្ជីជារង្វង់មូល",
+BulletedList : "បន្ថែម/លប់ បញ្ជីជារង្វង់មូល",
+ShowTableBorders : "បង្ហាញស៊ុមតារាង",
+ShowDetails : "បង្ហាញពិស្តារ",
+Style : "ម៉ូត",
+FontFormat : "រចនា",
+Font : "ហ្វុង",
+FontSize : "ទំហំ",
+TextColor : "ពណ៌អក្សរ",
+BGColor : "ពណ៌ផ្ទៃខាងក្រោយ",
+Source : "កូត",
+Find : "ស្វែងរក",
+Replace : "ជំនួស",
+SpellCheck : "ពិនិត្យអក្ខរាវិរុទ្ធ",
+UniversalKeyboard : "ក្តារពុម្ភអក្សរសកល",
+PageBreakLbl : "ការផ្តាច់ទំព័រ",
+PageBreak : "បន្ថែម ការផ្តាច់ទំព័រ",
+
+Form : "បែបបទ",
+Checkbox : "ប្រអប់ជ្រើសរើស",
+RadioButton : "ប៉ូតុនរង្វង់មូល",
+TextField : "ជួរសរសេរអត្ថបទ",
+Textarea : "តំបន់សរសេរអត្ថបទ",
+HiddenField : "ជួរលាក់",
+Button : "ប៉ូតុន",
+SelectionField : "ជួរជ្រើសរើស",
+ImageButton : "ប៉ូតុនរូបភាព",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "កែប្រែឈ្នាប់",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "បន្ថែមជួរផ្តេក",
+DeleteRows : "លប់ជួរផ្តេក",
+InsertColumn : "បន្ថែមជួរឈរ",
+DeleteColumns : "លប់ជួរឈរ",
+InsertCell : "បន្ថែម សែល",
+DeleteCells : "លប់សែល",
+MergeCells : "បញ្ជូលសែល",
+SplitCell : "ផ្តាច់សែល",
+TableDelete : "លប់តារាង",
+CellProperties : "ការកំណត់សែល",
+TableProperties : "ការកំណត់តារាង",
+ImageProperties : "ការកំណត់រូបភាព",
+FlashProperties : "ការកំណត់ Flash",
+
+AnchorProp : "ការកំណត់យុថ្កា",
+ButtonProp : "ការកំណត់ ប៉ូតុន",
+CheckboxProp : "ការកំណត់ប្រអប់ជ្រើសរើស",
+HiddenFieldProp : "ការកំណត់ជួរលាក់",
+RadioButtonProp : "ការកំណត់ប៉ូតុនរង្វង់",
+ImageButtonProp : "ការកំណត់ប៉ូតុនរូបភាព",
+TextFieldProp : "ការកំណត់ជួរអត្ថបទ",
+SelectionFieldProp : "ការកំណត់ជួរជ្រើសរើស",
+TextareaProp : "ការកំណត់កន្លែងសរសេរអត្ថបទ",
+FormProp : "ការកំណត់បែបបទ",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "កំពុងដំណើរការ XHTML ។ សូមរងចាំ...",
+Done : "ចប់រួចរាល់",
+PasteWordConfirm : "អត្ថបទដែលលោកអ្នកបំរុងចំលងដាក់ ហាក់បីដូចជាត្រូវចំលងមកពីកម្មវិធី​Word​។ តើលោកអ្នកចង់សំអាតមុនចំលងអត្ថបទដាក់ទេ?",
+NotCompatiblePaste : "ពាក្យបញ្ជានេះប្រើបានតែជាមួយ Internet Explorer កំរិត 5.5 រឺ លើសនេះ ។ តើលោកអ្នកចង់ចំលងដាក់ដោយមិនចាំបាច់សំអាតទេ?",
+UnknownToolbarItem : "វត្ថុលើរបាឧបរកណ៍ មិនស្គាល់ \"%1\"",
+UnknownCommand : "ឈ្មោះពាក្យបញ្ជា មិនស្គាល់ \"%1\"",
+NotImplemented : "ពាក្យបញ្ជា មិនបានអនុវត្ត",
+UnknownToolbarSet : "របាឧបរកណ៍ \"%1\" ពុំមាន ។",
+NoActiveX : "ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​អាចធ្វើអោយលោកអ្នកមិនអាចប្រើមុខងារខ្លះរបស់កម្មវិធីតាក់តែងអត្ថបទនេះ ។ លោកអ្នកត្រូវកំណត់អោយ \"ActiveX និង​កម្មវិធីជំនួយក្នុង (plug-ins)\" អោយដំណើរការ ។ លោកអ្នកអាចជួបប្រទះនឹង បញ្ហា ព្រមជាមួយនឹងការបាត់បង់មុខងារណាមួយរបស់កម្មវិធីតាក់តែងអត្ថបទនេះ ។",
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "វីនដូវមិនអាចបើកបានទេ ។ សូមពិនិត្យចំពោះកម្មវិធីបិទ វីនដូវលោត (popup) ថាតើវាដំណើរការរឺទេ ។",
+
+// Dialogs
+DlgBtnOK : "យល់ព្រម",
+DlgBtnCancel : "មិនយល់ព្រម",
+DlgBtnClose : "បិទ",
+DlgBtnBrowseServer : "មើល",
+DlgAdvancedTag : "កំរិតខ្ពស់",
+DlgOpOther : "<ផ្សេងទៅត>",
+DlgInfoTab : "ពត៌មាន",
+DlgAlertUrl : "សូមសរសេរ URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<មិនមែន>",
+DlgGenId : "Id",
+DlgGenLangDir : "ទិសដៅភាសា",
+DlgGenLangDirLtr : "ពីឆ្វេងទៅស្តាំ(LTR)",
+DlgGenLangDirRtl : "ពីស្តាំទៅឆ្វេង(RTL)",
+DlgGenLangCode : "លេខកូតភាសា",
+DlgGenAccessKey : "ឃី សំរាប់ចូល",
+DlgGenName : "ឈ្មោះ",
+DlgGenTabIndex : "លេខ Tab",
+DlgGenLongDescr : "អធិប្បាយ URL វែង",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "ចំណងជើង ប្រឹក្សា",
+DlgGenContType : "ប្រភេទអត្ថបទ ប្រឹក្សា",
+DlgGenLinkCharset : "លេខកូតអក្សររបស់ឈ្នាប់",
+DlgGenStyle : "ម៉ូត",
+
+// Image Dialog
+DlgImgTitle : "ការកំណត់រូបភាព",
+DlgImgInfoTab : "ពត៌មានអំពីរូបភាព",
+DlgImgBtnUpload : "បញ្ជូនទៅកាន់ម៉ាស៊ីនផ្តល់សេវា",
+DlgImgURL : "URL",
+DlgImgUpload : "ទាញយក",
+DlgImgAlt : "អត្ថបទជំនួស",
+DlgImgWidth : "ទទឹង",
+DlgImgHeight : "កំពស់",
+DlgImgLockRatio : "អត្រាឡុក",
+DlgBtnResetSize : "កំណត់ទំហំឡើងវិញ",
+DlgImgBorder : "ស៊ុម",
+DlgImgHSpace : "គំលាតទទឹង",
+DlgImgVSpace : "គំលាតបណ្តោយ",
+DlgImgAlign : "កំណត់ទីតាំង",
+DlgImgAlignLeft : "ខាងឆ្វង",
+DlgImgAlignAbsBottom: "Abs Bottom", //MISSING
+DlgImgAlignAbsMiddle: "Abs Middle", //MISSING
+DlgImgAlignBaseline : "បន្ទាត់ជាមូលដ្ឋាន",
+DlgImgAlignBottom : "ខាងក្រោម",
+DlgImgAlignMiddle : "កណ្តាល",
+DlgImgAlignRight : "ខាងស្តាំ",
+DlgImgAlignTextTop : "លើអត្ថបទ",
+DlgImgAlignTop : "ខាងលើ",
+DlgImgPreview : "មើលសាកល្បង",
+DlgImgAlertUrl : "សូមសរសេរងាស័យដ្ឋានរបស់រូបភាព",
+DlgImgLinkTab : "ឈ្នាប់",
+
+// Flash Dialog
+DlgFlashTitle : "ការកំណត់ Flash",
+DlgFlashChkPlay : "លេងដោយស្វ័យប្រវត្ត",
+DlgFlashChkLoop : "ចំនួនដង",
+DlgFlashChkMenu : "បង្ហាញ មឺនុយរបស់ Flash",
+DlgFlashScale : "ទំហំ",
+DlgFlashScaleAll : "បង្ហាញទាំងអស់",
+DlgFlashScaleNoBorder : "មិនបង្ហាញស៊ុម",
+DlgFlashScaleFit : "ត្រូវល្មម",
+
+// Link Dialog
+DlgLnkWindowTitle : "ឈ្នាប់",
+DlgLnkInfoTab : "ពត៌មានអំពីឈ្នាប់",
+DlgLnkTargetTab : "គោលដៅ",
+
+DlgLnkType : "ប្រភេទឈ្នាប់",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "យុថ្កានៅក្នុងទំព័រនេះ",
+DlgLnkTypeEMail : "អ៊ីមែល",
+DlgLnkProto : "ប្រូតូកូល",
+DlgLnkProtoOther : "<ផ្សេងទៀត>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "ជ្រើសរើសយុថ្កា",
+DlgLnkAnchorByName : "តាមឈ្មោះរបស់យុថ្កា",
+DlgLnkAnchorById : "តាម Id",
+DlgLnkNoAnchors : "<ពុំមានយុថ្កានៅក្នុងឯកសារនេះទេ>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "អ៊ីមែល",
+DlgLnkEMailSubject : "ចំណងជើងអត្ថបទ",
+DlgLnkEMailBody : "អត្ថបទ",
+DlgLnkUpload : "ទាញយក",
+DlgLnkBtnUpload : "ទាញយក",
+
+DlgLnkTarget : "គោលដៅ",
+DlgLnkTargetFrame : "<ហ្វ្រេម>",
+DlgLnkTargetPopup : "<វីនដូវ លោត>",
+DlgLnkTargetBlank : "វីនដូវថ្មី (_blank)",
+DlgLnkTargetParent : "វីនដូវមេ (_parent)",
+DlgLnkTargetSelf : "វីនដូវដដែល (_self)",
+DlgLnkTargetTop : "វីនដូវនៅលើគេ(_top)",
+DlgLnkTargetFrameName : "ឈ្មោះហ្រ្វេមដែលជាគោលដៅ",
+DlgLnkPopWinName : "ឈ្មោះវីនដូវលោត",
+DlgLnkPopWinFeat : "លក្ខណះរបស់វីនដូលលោត",
+DlgLnkPopResize : "ទំហំអាចផ្លាស់ប្តូរ",
+DlgLnkPopLocation : "របា ទីតាំង",
+DlgLnkPopMenu : "របា មឺនុយ",
+DlgLnkPopScroll : "របា ទាញ",
+DlgLnkPopStatus : "របា ពត៌មាន",
+DlgLnkPopToolbar : "របា ឩបករណ៍",
+DlgLnkPopFullScrn : "អេក្រុងពេញ(IE)",
+DlgLnkPopDependent : "អាស្រ័យលើ (Netscape)",
+DlgLnkPopWidth : "ទទឹង",
+DlgLnkPopHeight : "កំពស់",
+DlgLnkPopLeft : "ទីតាំងខាងឆ្វេង",
+DlgLnkPopTop : "ទីតាំងខាងលើ",
+
+DlnLnkMsgNoUrl : "សូមសរសេរ អាស័យដ្ឋាន URL",
+DlnLnkMsgNoEMail : "សូមសរសេរ អាស័យដ្ឋាន អ៊ីមែល",
+DlnLnkMsgNoAnchor : "សូមជ្រើសរើស យុថ្កា",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "ជ្រើសរើស ពណ៌",
+DlgColorBtnClear : "លប់",
+DlgColorHighlight : "ផាត់ពណ៌",
+DlgColorSelected : "បានជ្រើសរើស",
+
+// Smiley Dialog
+DlgSmileyTitle : "បញ្ជូលរូបភាព",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "តូអក្សរពិសេស",
+
+// Table Dialog
+DlgTableTitle : "ការកំណត់ តារាង",
+DlgTableRows : "ជួរផ្តេក",
+DlgTableColumns : "ជួរឈរ",
+DlgTableBorder : "ទំហំស៊ុម",
+DlgTableAlign : "ការកំណត់ទីតាំង",
+DlgTableAlignNotSet : "<មិនកំណត់>",
+DlgTableAlignLeft : "ខាងឆ្វេង",
+DlgTableAlignCenter : "កណ្តាល",
+DlgTableAlignRight : "ខាងស្តាំ",
+DlgTableWidth : "ទទឹង",
+DlgTableWidthPx : "ភីកសែល",
+DlgTableWidthPc : "ភាគរយ",
+DlgTableHeight : "កំពស់",
+DlgTableCellSpace : "គំលាតសែល",
+DlgTableCellPad : "គែមសែល",
+DlgTableCaption : "ចំណងជើង",
+DlgTableSummary : "សេចក្តីសង្ខេប",
+
+// Table Cell Dialog
+DlgCellTitle : "ការកំណត់ សែល",
+DlgCellWidth : "ទទឹង",
+DlgCellWidthPx : "ភីកសែល",
+DlgCellWidthPc : "ភាគរយ",
+DlgCellHeight : "កំពស់",
+DlgCellWordWrap : "បង្ហាញអត្ថបទទាំងអស់",
+DlgCellWordWrapNotSet : "<មិនកំណត់>",
+DlgCellWordWrapYes : "បាទ(ចា)",
+DlgCellWordWrapNo : "ទេ",
+DlgCellHorAlign : "តំរឹមផ្តេក",
+DlgCellHorAlignNotSet : "<មិនកំណត់>",
+DlgCellHorAlignLeft : "ខាងឆ្វេង",
+DlgCellHorAlignCenter : "កណ្តាល",
+DlgCellHorAlignRight: "Right", //MISSING
+DlgCellVerAlign : "តំរឹមឈរ",
+DlgCellVerAlignNotSet : "<មិនកណត់>",
+DlgCellVerAlignTop : "ខាងលើ",
+DlgCellVerAlignMiddle : "កណ្តាល",
+DlgCellVerAlignBottom : "ខាងក្រោម",
+DlgCellVerAlignBaseline : "បន្ទាត់ជាមូលដ្ឋាន",
+DlgCellRowSpan : "បញ្ជូលជួរផ្តេក",
+DlgCellCollSpan : "បញ្ជូលជួរឈរ",
+DlgCellBackColor : "ពណ៌ផ្នែកខាងក្រោម",
+DlgCellBorderColor : "ពណ៌ស៊ុម",
+DlgCellBtnSelect : "ជ្រើសរើស...",
+
+// Find Dialog
+DlgFindTitle : "ស្វែងរក",
+DlgFindFindBtn : "ស្វែងរក",
+DlgFindNotFoundMsg : "ពាក្យនេះ រកមិនឃើញទេ ។",
+
+// Replace Dialog
+DlgReplaceTitle : "ជំនួស",
+DlgReplaceFindLbl : "ស្វែងរកអ្វី:",
+DlgReplaceReplaceLbl : "ជំនួសជាមួយ:",
+DlgReplaceCaseChk : "ករណ៉ត្រូវរក",
+DlgReplaceReplaceBtn : "ជំនួស",
+DlgReplaceReplAllBtn : "ជំនួសទាំងអស់",
+DlgReplaceWordChk : "ត្រូវពាក្យទាំងអស់",
+
+// Paste Operations / Dialog
+PasteErrorCut : "ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ កាត់អត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl+X) ។",
+PasteErrorCopy : "ការកំណត់សុវត្ថភាពរបស់កម្មវិធីរុករករបស់លោកអ្នក នេះ​មិនអាចធ្វើកម្មវិធីតាក់តែងអត្ថបទ ចំលងអត្ថបទយកដោយស្វ័យប្រវត្តបានឡើយ ។ សូមប្រើប្រាស់បន្សំ ឃីដូចនេះ (Ctrl+C)។",
+
+PasteAsText : "ចំលងដាក់អត្ថបទធម្មតា",
+PasteFromWord : "ចំលងពាក្យពីកម្មវិធី Word",
+
+DlgPasteMsg2 : "សូមចំលងអត្ថបទទៅដាក់ក្នុងប្រអប់ដូចខាងក្រោមដោយប្រើប្រាស់ ឃី ​(<STRONG>Ctrl+V</STRONG>) ហើយចុច <STRONG>OK</STRONG> ។",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "មិនគិតអំពីប្រភេទពុម្ភអក្សរ",
+DlgPasteRemoveStyles : "លប់ម៉ូត",
+DlgPasteCleanBox : "លប់អត្ថបទចេញពីប្រអប់",
+
+// Color Picker
+ColorAutomatic : "ស្វ័យប្រវត្ត",
+ColorMoreColors : "ពណ៌ផ្សេងទៀត..",
+
+// Document Properties
+DocProps : "ការកំណត់ ឯកសារ",
+
+// Anchor Dialog
+DlgAnchorTitle : "ការកំណត់ចំណងជើងយុទ្ធថ្កា",
+DlgAnchorName : "ឈ្មោះយុទ្ធថ្កា",
+DlgAnchorErrorName : "សូមសរសេរ ឈ្មោះយុទ្ធថ្កា",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "គ្មានក្នុងវចនានុក្រម",
+DlgSpellChangeTo : "ផ្លាស់ប្តូរទៅ",
+DlgSpellBtnIgnore : "មិនផ្លាស់ប្តូរ",
+DlgSpellBtnIgnoreAll : "មិនផ្លាស់ប្តូរ ទាំងអស់",
+DlgSpellBtnReplace : "ជំនួស",
+DlgSpellBtnReplaceAll : "ជំនួសទាំងអស់",
+DlgSpellBtnUndo : "សារឡើងវិញ",
+DlgSpellNoSuggestions : "- គ្មានសំណើរ -",
+DlgSpellProgress : "កំពុងពិនិត្យអក្ខរាវិរុទ្ធ...",
+DlgSpellNoMispell : "ការពិនិត្យអក្ខរាវិរុទ្ធបានចប់: គ្មានកំហុស",
+DlgSpellNoChanges : "ការពិនិត្យអក្ខរាវិរុទ្ធបានចប់: ពុំមានផ្លាស់ប្តូរ",
+DlgSpellOneChange : "ការពិនិត្យអក្ខរាវិរុទ្ធបានចប់: ពាក្យមួយត្រូចបានផ្លាស់ប្តូរ",
+DlgSpellManyChanges : "ការពិនិត្យអក្ខរាវិរុទ្ធបានចប់: %1 ពាក្យបានផ្លាស់ប្តូរ",
+
+IeSpellDownload : "ពុំមានកម្មវិធីពិនិត្យអក្ខរាវិរុទ្ធ ។ តើចង់ទាញយកពីណា?",
+
+// Button Dialog
+DlgButtonText : "អត្ថបទ(តំលៃ)",
+DlgButtonType : "ប្រភេទ",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "ឈ្មោះ",
+DlgCheckboxValue : "តំលៃ",
+DlgCheckboxSelected : "បានជ្រើសរើស",
+
+// Form Dialog
+DlgFormName : "ឈ្មោះ",
+DlgFormAction : "សកម្មភាព",
+DlgFormMethod : "វិធី",
+
+// Select Field Dialog
+DlgSelectName : "ឈ្មោះ",
+DlgSelectValue : "តំលៃ",
+DlgSelectSize : "ទំហំ",
+DlgSelectLines : "បន្ទាត់",
+DlgSelectChkMulti : "អនុញ្ញាតអោយជ្រើសរើសច្រើន",
+DlgSelectOpAvail : "ការកំណត់ជ្រើសរើស ដែលអាចកំណត់បាន",
+DlgSelectOpText : "ពាក្យ",
+DlgSelectOpValue : "តំលៃ",
+DlgSelectBtnAdd : "បន្ថែម",
+DlgSelectBtnModify : "ផ្លាស់ប្តូរ",
+DlgSelectBtnUp : "លើ",
+DlgSelectBtnDown : "ក្រោម",
+DlgSelectBtnSetValue : "Set as selected value", //MISSING
+DlgSelectBtnDelete : "លប់",
+
+// Textarea Dialog
+DlgTextareaName : "ឈ្មោះ",
+DlgTextareaCols : "ជូរឈរ",
+DlgTextareaRows : "ជូរផ្តេក",
+
+// Text Field Dialog
+DlgTextName : "ឈ្មោះ",
+DlgTextValue : "តំលៃ",
+DlgTextCharWidth : "ទទឹង អក្សរ",
+DlgTextMaxChars : "អក្សរអតិបរិមា",
+DlgTextType : "ប្រភេទ",
+DlgTextTypeText : "ពាក្យ",
+DlgTextTypePass : "ពាក្យសំងាត់",
+
+// Hidden Field Dialog
+DlgHiddenName : "ឈ្មោះ",
+DlgHiddenValue : "តំលៃ",
+
+// Bulleted List Dialog
+BulletedListProp : "កំណត់បញ្ជីរង្វង់",
+NumberedListProp : "កំណត់បញ្េជីលេខ",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "ប្រភេទ",
+DlgLstTypeCircle : "រង្វង់",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "ការេ",
+DlgLstTypeNumbers : "លេខ(1, 2, 3)",
+DlgLstTypeLCase : "អក្សរតូច(a, b, c)",
+DlgLstTypeUCase : "អក្សរធំ(A, B, C)",
+DlgLstTypeSRoman : "អក្សរឡាតាំងតូច(i, ii, iii)",
+DlgLstTypeLRoman : "អក្សរឡាតាំងធំ(I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "ទូទៅ",
+DlgDocBackTab : "ផ្នែកខាងក្រោយ",
+DlgDocColorsTab : "ទំព័រ​និង ស៊ុម",
+DlgDocMetaTab : "ទិន្នន័យមេ",
+
+DlgDocPageTitle : "ចំណងជើងទំព័រ",
+DlgDocLangDir : "ទិសដៅសរសេរភាសា",
+DlgDocLangDirLTR : "ពីឆ្វេងទៅស្ដាំ(LTR)",
+DlgDocLangDirRTL : "ពីស្ដាំទៅឆ្វេង(RTL)",
+DlgDocLangCode : "លេខកូតភាសា",
+DlgDocCharSet : "កំណត់លេខកូតភាសា",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "កំណត់លេខកូតភាសាផ្សេងទៀត",
+
+DlgDocDocType : "ប្រភេទក្បាលទំព័រ",
+DlgDocDocTypeOther : "ប្រភេទក្បាលទំព័រផ្សេងទៀត",
+DlgDocIncXHTML : "បញ្ជូល XHTML",
+DlgDocBgColor : "ពណ៌ខាងក្រោម",
+DlgDocBgImage : "URL របស់រូបភាពខាងក្រោម",
+DlgDocBgNoScroll : "ទំព័រក្រោមមិនប្តូរ",
+DlgDocCText : "អត្តបទ",
+DlgDocCLink : "ឈ្នាប់",
+DlgDocCVisited : "ឈ្នាប់មើលហើយ",
+DlgDocCActive : "ឈ្នាប់កំពុងមើល",
+DlgDocMargins : "ស៊ុមទំព័រ",
+DlgDocMaTop : "លើ",
+DlgDocMaLeft : "ឆ្វេង",
+DlgDocMaRight : "ស្ដាំ",
+DlgDocMaBottom : "ក្រោម",
+DlgDocMeIndex : "ពាក្យនៅក្នុងឯកសារ (ផ្តាច់ពីគ្នាដោយក្បៀស)",
+DlgDocMeDescr : "សេចក្តីអត្ថាធិប្បាយអំពីឯកសារ",
+DlgDocMeAuthor : "អ្នកនិពន្ធ",
+DlgDocMeCopy : "រក្សាសិទ្ធិ៏",
+DlgDocPreview : "មើលសាកល្បង",
+
+// Templates Dialog
+Templates : "ឯកសារគំរូ",
+DlgTemplatesTitle : "ឯកសារគំរូ របស់អត្ថន័យ",
+DlgTemplatesSelMsg : "សូមជ្រើសរើសឯកសារគំរូ ដើម្បីបើកនៅក្នុងកម្មវិធីតាក់តែងអត្ថបទ<br>(អត្ថបទនឹងបាត់បង់):",
+DlgTemplatesLoading : "កំពុងអានបញ្ជីឯកសារគំរូ ។ សូមរងចាំ...",
+DlgTemplatesNoTpl : "(ពុំមានឯកសារគំរូត្រូវបានកំណត់)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "អំពី",
+DlgAboutBrowserInfoTab : "ព៌តមានកម្មវិធីរុករក",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "ជំនាន់",
+DlgAboutInfo : "សំរាប់ព៌តមានផ្សេងទៀត សូមទាក់ទង"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ko.js b/httemplate/elements/fckeditor/editor/lang/ko.js
new file mode 100644
index 000000000..0a2efa6eb
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ko.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Korean language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "툴바 감추기",
+ToolbarExpand : "툴바 보이기",
+
+// Toolbar Items and Context Menu
+Save : "저장하기",
+NewPage : "새 문서",
+Preview : "미리보기",
+Cut : "잘라내기",
+Copy : "복사하기",
+Paste : "붙여넣기",
+PasteText : "텍스트로 붙여넣기",
+PasteWord : "MS Word 형식에서 붙여넣기",
+Print : "인쇄하기",
+SelectAll : "전체선택",
+RemoveFormat : "포맷 지우기",
+InsertLinkLbl : "링크",
+InsertLink : "링크 삽입/변경",
+RemoveLink : "링크 삭제",
+Anchor : "책갈피 삽입/변경",
+InsertImageLbl : "이미지",
+InsertImage : "이미지 삽입/변경",
+InsertFlashLbl : "플래쉬",
+InsertFlash : "플래쉬 삽입/변경",
+InsertTableLbl : "표",
+InsertTable : "표 삽입/변경",
+InsertLineLbl : "수평선",
+InsertLine : "수평선 삽입",
+InsertSpecialCharLbl: "특수문자 삽입",
+InsertSpecialChar : "특수문자 삽입",
+InsertSmileyLbl : "아이콘",
+InsertSmiley : "아이콘 삽입",
+About : "FCKeditor에 대하여",
+Bold : "진하게",
+Italic : "이텔릭",
+Underline : "밑줄",
+StrikeThrough : "취소선",
+Subscript : "아래 첨자",
+Superscript : "위 첨자",
+LeftJustify : "왼쪽 정렬",
+CenterJustify : "가운데 정렬",
+RightJustify : "오른쪽 정렬",
+BlockJustify : "양쪽 맞춤",
+DecreaseIndent : "내어쓰기",
+IncreaseIndent : "들여쓰기",
+Undo : "취소",
+Redo : "재실행",
+NumberedListLbl : "순서있는 목록",
+NumberedList : "순서있는 목록",
+BulletedListLbl : "순서없는 목록",
+BulletedList : "순서없는 목록",
+ShowTableBorders : "표 테두리 보기",
+ShowDetails : "문서기호 보기",
+Style : "스타일",
+FontFormat : "포맷",
+Font : "폰트",
+FontSize : "글자 크기",
+TextColor : "글자 색상",
+BGColor : "배경 색상",
+Source : "소스",
+Find : "찾기",
+Replace : "바꾸기",
+SpellCheck : "철자검사",
+UniversalKeyboard : "다국어 입력기",
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "폼",
+Checkbox : "체크박스",
+RadioButton : "라디오버튼",
+TextField : "입력필드",
+Textarea : "입력영역",
+HiddenField : "숨김필드",
+Button : "버튼",
+SelectionField : "펼침목록",
+ImageButton : "이미지버튼",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "링크 수정",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "가로줄 삽입",
+DeleteRows : "가로줄 삭제",
+InsertColumn : "세로줄 삽입",
+DeleteColumns : "세로줄 삭제",
+InsertCell : "셀 삽입",
+DeleteCells : "셀 삭제",
+MergeCells : "셀 합치기",
+SplitCell : "셀 나누기",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "셀 속성",
+TableProperties : "표 속성",
+ImageProperties : "이미지 속성",
+FlashProperties : "플래쉬 속성",
+
+AnchorProp : "책갈피 속성",
+ButtonProp : "버튼 속성",
+CheckboxProp : "체크박스 속성",
+HiddenFieldProp : "숨김필드 속성",
+RadioButtonProp : "라디오버튼 속성",
+ImageButtonProp : "이미지버튼 속성",
+TextFieldProp : "입력필드 속성",
+SelectionFieldProp : "펼침목록 속성",
+TextareaProp : "입력영역 속성",
+FormProp : "폼 속성",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML 처리중. 잠시만 기다려주십시요.",
+Done : "완료",
+PasteWordConfirm : "붙여넣기 할 텍스트는 MS Word에서 복사한 것입니다. 붙여넣기 전에 MS Word 포멧을 삭제하시겠습니까?",
+NotCompatiblePaste : "이 명령은 인터넷익스플로러 5.5 버전 이상에서만 작동합니다. 포멧을 삭제하지 않고 붙여넣기 하시겠습니까?",
+UnknownToolbarItem : "알수없는 툴바입니다. : \"%1\"",
+UnknownCommand : "알수없는 기능입니다. : \"%1\"",
+NotImplemented : "기능이 실행되지 않았습니다.",
+UnknownToolbarSet : "툴바 설정이 없습니다. : \"%1\"",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "예",
+DlgBtnCancel : "아니오",
+DlgBtnClose : "닫기",
+DlgBtnBrowseServer : "서버 보기",
+DlgAdvancedTag : "자세히",
+DlgOpOther : "<기타>",
+DlgInfoTab : "정보",
+DlgAlertUrl : "URL을 입력하십시요",
+
+// General Dialogs Labels
+DlgGenNotSet : "<설정되지 않음>",
+DlgGenId : "ID",
+DlgGenLangDir : "쓰기 방향",
+DlgGenLangDirLtr : "왼쪽에서 오른쪽 (LTR)",
+DlgGenLangDirRtl : "오른쪽에서 왼쪽 (RTL)",
+DlgGenLangCode : "언어 코드",
+DlgGenAccessKey : "엑세스 키",
+DlgGenName : "Name",
+DlgGenTabIndex : "탭 순서",
+DlgGenLongDescr : "URL 설명",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "이미지 설정",
+DlgImgInfoTab : "이미지 정보",
+DlgImgBtnUpload : "서버로 전송",
+DlgImgURL : "URL",
+DlgImgUpload : "업로드",
+DlgImgAlt : "이미지 설명",
+DlgImgWidth : "너비",
+DlgImgHeight : "높이",
+DlgImgLockRatio : "비율 유지",
+DlgBtnResetSize : "원래 크기로",
+DlgImgBorder : "테두리",
+DlgImgHSpace : "수평여백",
+DlgImgVSpace : "수직여백",
+DlgImgAlign : "정렬",
+DlgImgAlignLeft : "왼쪽",
+DlgImgAlignAbsBottom: "줄아래(Abs Bottom)",
+DlgImgAlignAbsMiddle: "줄중간(Abs Middle)",
+DlgImgAlignBaseline : "기준선",
+DlgImgAlignBottom : "아래",
+DlgImgAlignMiddle : "중간",
+DlgImgAlignRight : "오른쪽",
+DlgImgAlignTextTop : "글자위(Text Top)",
+DlgImgAlignTop : "위",
+DlgImgPreview : "미리보기",
+DlgImgAlertUrl : "이미지 URL을 입력하십시요",
+DlgImgLinkTab : "링크",
+
+// Flash Dialog
+DlgFlashTitle : "플래쉬 등록정보",
+DlgFlashChkPlay : "자동재생",
+DlgFlashChkLoop : "반복",
+DlgFlashChkMenu : "플래쉬메뉴 가능",
+DlgFlashScale : "영역",
+DlgFlashScaleAll : "모두보기",
+DlgFlashScaleNoBorder : "경계선없음",
+DlgFlashScaleFit : "영역자동조절",
+
+// Link Dialog
+DlgLnkWindowTitle : "링크",
+DlgLnkInfoTab : "링크 정보",
+DlgLnkTargetTab : "타겟",
+
+DlgLnkType : "링크 종류",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "책갈피",
+DlgLnkTypeEMail : "이메일",
+DlgLnkProto : "프로토콜",
+DlgLnkProtoOther : "<기타>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "책갈피 선택",
+DlgLnkAnchorByName : "책갈피 이름",
+DlgLnkAnchorById : "책갈피 ID",
+DlgLnkNoAnchors : "<문서에 책갈피가 없습니다.>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "이메일 주소",
+DlgLnkEMailSubject : "제목",
+DlgLnkEMailBody : "내용",
+DlgLnkUpload : "업로드",
+DlgLnkBtnUpload : "서버로 전송",
+
+DlgLnkTarget : "타겟",
+DlgLnkTargetFrame : "<프레임>",
+DlgLnkTargetPopup : "<팝업창>",
+DlgLnkTargetBlank : "새 창 (_blank)",
+DlgLnkTargetParent : "부모 창 (_parent)",
+DlgLnkTargetSelf : "현재 창 (_self)",
+DlgLnkTargetTop : "최 상위 창 (_top)",
+DlgLnkTargetFrameName : "타겟 프레임 이름",
+DlgLnkPopWinName : "팝업창 이름",
+DlgLnkPopWinFeat : "팝업창 설정",
+DlgLnkPopResize : "크기조정",
+DlgLnkPopLocation : "주소표시줄",
+DlgLnkPopMenu : "메뉴바",
+DlgLnkPopScroll : "스크롤바",
+DlgLnkPopStatus : "상태바",
+DlgLnkPopToolbar : "툴바",
+DlgLnkPopFullScrn : "전체화면 (IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "너비",
+DlgLnkPopHeight : "높이",
+DlgLnkPopLeft : "왼쪽 위치",
+DlgLnkPopTop : "윗쪽 위치",
+
+DlnLnkMsgNoUrl : "링크 URL을 입력하십시요.",
+DlnLnkMsgNoEMail : "이메일주소를 입력하십시요.",
+DlnLnkMsgNoAnchor : "책갈피명을 입력하십시요.",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "색상 선택",
+DlgColorBtnClear : "지우기",
+DlgColorHighlight : "현재",
+DlgColorSelected : "선택됨",
+
+// Smiley Dialog
+DlgSmileyTitle : "아이콘 삽입",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "특수문자 선택",
+
+// Table Dialog
+DlgTableTitle : "표 설정",
+DlgTableRows : "가로줄",
+DlgTableColumns : "세로줄",
+DlgTableBorder : "테두리 크기",
+DlgTableAlign : "정렬",
+DlgTableAlignNotSet : "<설정되지 않음>",
+DlgTableAlignLeft : "왼쪽",
+DlgTableAlignCenter : "가운데",
+DlgTableAlignRight : "오른쪽",
+DlgTableWidth : "너비",
+DlgTableWidthPx : "픽셀",
+DlgTableWidthPc : "퍼센트",
+DlgTableHeight : "높이",
+DlgTableCellSpace : "셀 간격",
+DlgTableCellPad : "셀 여백",
+DlgTableCaption : "캡션",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "셀 설정",
+DlgCellWidth : "너비",
+DlgCellWidthPx : "픽셀",
+DlgCellWidthPc : "퍼센트",
+DlgCellHeight : "높이",
+DlgCellWordWrap : "워드랩",
+DlgCellWordWrapNotSet : "<설정되지 않음>",
+DlgCellWordWrapYes : "예",
+DlgCellWordWrapNo : "아니오",
+DlgCellHorAlign : "수평 정렬",
+DlgCellHorAlignNotSet : "<설정되지 않음>",
+DlgCellHorAlignLeft : "왼쪽",
+DlgCellHorAlignCenter : "가운데",
+DlgCellHorAlignRight: "오른쪽",
+DlgCellVerAlign : "수직 정렬",
+DlgCellVerAlignNotSet : "<설정되지 않음>",
+DlgCellVerAlignTop : "위",
+DlgCellVerAlignMiddle : "중간",
+DlgCellVerAlignBottom : "아래",
+DlgCellVerAlignBaseline : "기준선",
+DlgCellRowSpan : "세로 합치기",
+DlgCellCollSpan : "가로 합치기",
+DlgCellBackColor : "배경 색상",
+DlgCellBorderColor : "테두리 색상",
+DlgCellBtnSelect : "선택",
+
+// Find Dialog
+DlgFindTitle : "찾기",
+DlgFindFindBtn : "찾기",
+DlgFindNotFoundMsg : "문자열을 찾을 수 없습니다.",
+
+// Replace Dialog
+DlgReplaceTitle : "바꾸기",
+DlgReplaceFindLbl : "찾을 문자열:",
+DlgReplaceReplaceLbl : "바꿀 문자열:",
+DlgReplaceCaseChk : "대소문자 구분",
+DlgReplaceReplaceBtn : "바꾸기",
+DlgReplaceReplAllBtn : "모두 바꾸기",
+DlgReplaceWordChk : "온전한 단어",
+
+// Paste Operations / Dialog
+PasteErrorCut : "브라우저의 보안설정때문에 잘라내기 기능을 실행할 수 없습니다. 키보드 명령을 사용하십시요. (Ctrl+X).",
+PasteErrorCopy : "브라우저의 보안설정때문에 복사하기 기능을 실행할 수 없습니다. 키보드 명령을 사용하십시요. (Ctrl+C).",
+
+PasteAsText : "텍스트로 붙여넣기",
+PasteFromWord : "MS Word 형식에서 붙여넣기",
+
+DlgPasteMsg2 : "키보드의 (<STRONG>Ctrl+V</STRONG>) 를 이용해서 상자안에 붙여넣고 <STRONG>OK</STRONG> 를 누르세요.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "폰트 설정 무시",
+DlgPasteRemoveStyles : "스타일 정의 제거",
+DlgPasteCleanBox : "글상자 제거",
+
+// Color Picker
+ColorAutomatic : "기본색상",
+ColorMoreColors : "색상선택...",
+
+// Document Properties
+DocProps : "문서 속성",
+
+// Anchor Dialog
+DlgAnchorTitle : "책갈피 속성",
+DlgAnchorName : "책갈피 이름",
+DlgAnchorErrorName : "책갈피 이름을 입력하십시요.",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "사전에 없는 단어",
+DlgSpellChangeTo : "변경할 단어",
+DlgSpellBtnIgnore : "건너뜀",
+DlgSpellBtnIgnoreAll : "모두 건너뜀",
+DlgSpellBtnReplace : "변경",
+DlgSpellBtnReplaceAll : "모두 변경",
+DlgSpellBtnUndo : "취소",
+DlgSpellNoSuggestions : "- 추천단어 없음 -",
+DlgSpellProgress : "철자검사를 진행중입니다...",
+DlgSpellNoMispell : "철자검사 완료: 잘못된 철자가 없습니다.",
+DlgSpellNoChanges : "철자검사 완료: 변경된 단어가 없습니다.",
+DlgSpellOneChange : "철자검사 완료: 단어가 변경되었습니다.",
+DlgSpellManyChanges : "철자검사 완료: %1 단어가 변경되었습니다.",
+
+IeSpellDownload : "철자 검사기가 철치되지 않았습니다. 지금 다운로드하시겠습니까?",
+
+// Button Dialog
+DlgButtonText : "버튼글자(값)",
+DlgButtonType : "버튼종류",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "이름",
+DlgCheckboxValue : "값",
+DlgCheckboxSelected : "선택됨",
+
+// Form Dialog
+DlgFormName : "폼이름",
+DlgFormAction : "실행경로(Action)",
+DlgFormMethod : "방법(Method)",
+
+// Select Field Dialog
+DlgSelectName : "이름",
+DlgSelectValue : "값",
+DlgSelectSize : "세로크기",
+DlgSelectLines : "줄",
+DlgSelectChkMulti : "여러항목 선택 허용",
+DlgSelectOpAvail : "선택옵션",
+DlgSelectOpText : "이름",
+DlgSelectOpValue : "값",
+DlgSelectBtnAdd : "추가",
+DlgSelectBtnModify : "변경",
+DlgSelectBtnUp : "위로",
+DlgSelectBtnDown : "아래로",
+DlgSelectBtnSetValue : "선택된것으로 설정",
+DlgSelectBtnDelete : "삭제",
+
+// Textarea Dialog
+DlgTextareaName : "이름",
+DlgTextareaCols : "칸수",
+DlgTextareaRows : "줄수",
+
+// Text Field Dialog
+DlgTextName : "이름",
+DlgTextValue : "값",
+DlgTextCharWidth : "글자 너비",
+DlgTextMaxChars : "최대 글자수",
+DlgTextType : "종류",
+DlgTextTypeText : "문자열",
+DlgTextTypePass : "비밀번호",
+
+// Hidden Field Dialog
+DlgHiddenName : "이름",
+DlgHiddenValue : "값",
+
+// Bulleted List Dialog
+BulletedListProp : "순서없는 목록 속성",
+NumberedListProp : "순서있는 목록 속성",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "종류",
+DlgLstTypeCircle : "원(Circle)",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "네모점(Square)",
+DlgLstTypeNumbers : "번호 (1, 2, 3)",
+DlgLstTypeLCase : "소문자 (a, b, c)",
+DlgLstTypeUCase : "대문자 (A, B, C)",
+DlgLstTypeSRoman : "로마자 수문자 (i, ii, iii)",
+DlgLstTypeLRoman : "로마자 대문자 (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "일반",
+DlgDocBackTab : "배경",
+DlgDocColorsTab : "색상 및 여백",
+DlgDocMetaTab : "메타데이터",
+
+DlgDocPageTitle : "페이지명",
+DlgDocLangDir : "문자 쓰기방향",
+DlgDocLangDirLTR : "왼쪽에서 오른쪽 (LTR)",
+DlgDocLangDirRTL : "오른쪽에서 왼쪽 (RTL)",
+DlgDocLangCode : "언어코드",
+DlgDocCharSet : "캐릭터셋 인코딩",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "다른 캐릭터셋 인코딩",
+
+DlgDocDocType : "문서 헤드",
+DlgDocDocTypeOther : "다른 문서헤드",
+DlgDocIncXHTML : "XHTML 문서정의 포함",
+DlgDocBgColor : "배경색상",
+DlgDocBgImage : "배경이미지 URL",
+DlgDocBgNoScroll : "스크롤되지않는 배경",
+DlgDocCText : "텍스트",
+DlgDocCLink : "링크",
+DlgDocCVisited : "방문한 링크(Visited)",
+DlgDocCActive : "활성화된 링크(Active)",
+DlgDocMargins : "페이지 여백",
+DlgDocMaTop : "위",
+DlgDocMaLeft : "왼쪽",
+DlgDocMaRight : "오른쪽",
+DlgDocMaBottom : "아래",
+DlgDocMeIndex : "문서 키워드 (콤마로 구분)",
+DlgDocMeDescr : "문서 설명",
+DlgDocMeAuthor : "작성자",
+DlgDocMeCopy : "저작권",
+DlgDocPreview : "미리보기",
+
+// Templates Dialog
+Templates : "템플릿",
+DlgTemplatesTitle : "내용 템플릿",
+DlgTemplatesSelMsg : "에디터에서 사용할 템플릿을 선택하십시요.<br>(지금까지 작성된 내용은 사라집니다.):",
+DlgTemplatesLoading : "템플릿 목록을 불러오는중입니다. 잠시만 기다려주십시요.",
+DlgTemplatesNoTpl : "(템플릿이 없습니다.)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "About",
+DlgAboutBrowserInfoTab : "브라우저 정보",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "버전",
+DlgAboutInfo : "For further information go to"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/lt.js b/httemplate/elements/fckeditor/editor/lang/lt.js
new file mode 100644
index 000000000..db994d0b9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/lt.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Lithuanian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Sutraukti mygtukų juostą",
+ToolbarExpand : "Išplėsti mygtukų juostą",
+
+// Toolbar Items and Context Menu
+Save : "Išsaugoti",
+NewPage : "Naujas puslapis",
+Preview : "Peržiūra",
+Cut : "Iškirpti",
+Copy : "Kopijuoti",
+Paste : "Įdėti",
+PasteText : "Įdėti kaip gryną tekstą",
+PasteWord : "Įdėti iš Word",
+Print : "Spausdinti",
+SelectAll : "Pažymėti viską",
+RemoveFormat : "Panaikinti formatą",
+InsertLinkLbl : "Nuoroda",
+InsertLink : "Įterpti/taisyti nuorodą",
+RemoveLink : "Panaikinti nuorodą",
+Anchor : "Įterpti/modifikuoti žymę",
+InsertImageLbl : "Vaizdas",
+InsertImage : "Įterpti/taisyti vaizdą",
+InsertFlashLbl : "Flash",
+InsertFlash : "Įterpti/taisyti Flash",
+InsertTableLbl : "Lentelė",
+InsertTable : "Įterpti/taisyti lentelę",
+InsertLineLbl : "Linija",
+InsertLine : "Įterpti horizontalią liniją",
+InsertSpecialCharLbl: "Spec. simbolis",
+InsertSpecialChar : "Įterpti specialų simbolį",
+InsertSmileyLbl : "Veideliai",
+InsertSmiley : "Įterpti veidelį",
+About : "Apie FCKeditor",
+Bold : "Pusjuodis",
+Italic : "Kursyvas",
+Underline : "Pabrauktas",
+StrikeThrough : "Perbrauktas",
+Subscript : "Apatinis indeksas",
+Superscript : "Viršutinis indeksas",
+LeftJustify : "Lygiuoti kairę",
+CenterJustify : "Centruoti",
+RightJustify : "Lygiuoti dešinę",
+BlockJustify : "Lygiuoti abi puses",
+DecreaseIndent : "Sumažinti įtrauką",
+IncreaseIndent : "Padidinti įtrauką",
+Undo : "Atšaukti",
+Redo : "Atstatyti",
+NumberedListLbl : "Numeruotas sąrašas",
+NumberedList : "Įterpti/Panaikinti numeruotą sąrašą",
+BulletedListLbl : "Suženklintas sąrašas",
+BulletedList : "Įterpti/Panaikinti suženklintą sąrašą",
+ShowTableBorders : "Rodyti lentelės rėmus",
+ShowDetails : "Rodyti detales",
+Style : "Stilius",
+FontFormat : "Šrifto formatas",
+Font : "Šriftas",
+FontSize : "Šrifto dydis",
+TextColor : "Teksto spalva",
+BGColor : "Fono spalva",
+Source : "Šaltinis",
+Find : "Rasti",
+Replace : "Pakeisti",
+SpellCheck : "Rašybos tikrinimas",
+UniversalKeyboard : "Universali klaviatūra",
+PageBreakLbl : "Puslapių skirtukas",
+PageBreak : "Įterpti puslapių skirtuką",
+
+Form : "Forma",
+Checkbox : "Žymimasis langelis",
+RadioButton : "Žymimoji akutė",
+TextField : "Teksto laukas",
+Textarea : "Teksto sritis",
+HiddenField : "Nerodomas laukas",
+Button : "Mygtukas",
+SelectionField : "Atrankos laukas",
+ImageButton : "Vaizdinis mygtukas",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Taisyti nuorodą",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Įterpti eilutę",
+DeleteRows : "Šalinti eilutes",
+InsertColumn : "Įterpti stulpelį",
+DeleteColumns : "Šalinti stulpelius",
+InsertCell : "Įterpti langelį",
+DeleteCells : "Šalinti langelius",
+MergeCells : "Sujungti langelius",
+SplitCell : "Skaidyti langelius",
+TableDelete : "Šalinti lentelę",
+CellProperties : "Langelio savybės",
+TableProperties : "Lentelės savybės",
+ImageProperties : "Vaizdo savybės",
+FlashProperties : "Flash savybės",
+
+AnchorProp : "Žymės savybės",
+ButtonProp : "Mygtuko savybės",
+CheckboxProp : "Žymimojo langelio savybės",
+HiddenFieldProp : "Nerodomo lauko savybės",
+RadioButtonProp : "Žymimosios akutės savybės",
+ImageButtonProp : "Vaizdinio mygtuko savybės",
+TextFieldProp : "Teksto lauko savybės",
+SelectionFieldProp : "Atrankos lauko savybės",
+TextareaProp : "Teksto srities savybės",
+FormProp : "Formos savybės",
+
+FontFormats : "Normalus;Formuotas;Kreipinio;Antraštinis 1;Antraštinis 2;Antraštinis 3;Antraštinis 4;Antraštinis 5;Antraštinis 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Apdorojamas XHTML. Prašome palaukti...",
+Done : "Baigta",
+PasteWordConfirm : "Įdedamas tekstas yra panašus į kopiją iš Word. Ar Jūs norite prieš įdėjimą išvalyti jį?",
+NotCompatiblePaste : "Ši komanda yra prieinama tik per Internet Explorer 5.5 ar aukštesnę versiją. Ar Jūs norite įterpti be valymo?",
+UnknownToolbarItem : "Nežinomas mygtukų juosta elementas \"%1\"",
+UnknownCommand : "Nežinomas komandos vardas \"%1\"",
+NotImplemented : "Komanda nėra įgyvendinta",
+UnknownToolbarSet : "Mygtukų juostos rinkinys \"%1\" neegzistuoja",
+NoActiveX : "Jūsų naršyklės saugumo nuostatos gali riboti kai kurias redaktoriaus savybes. Jūs turite aktyvuoti opciją \"Run ActiveX controls and plug-ins\". Kitu atveju Jums bus pranešama apie klaidas ir trūkstamas savybes.",
+BrowseServerBlocked : "Neįmanoma atidaryti naujo naršyklės lango. Įsitikinkite, kad iškylančių langų blokavimo programos neveiksnios.",
+DialogBlocked : "Neįmanoma atidaryti dialogo lango. Įsitikinkite, kad iškylančių langų blokavimo programos neveiksnios.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Nutraukti",
+DlgBtnClose : "Uždaryti",
+DlgBtnBrowseServer : "Naršyti po serverį",
+DlgAdvancedTag : "Papildomas",
+DlgOpOther : "<Kita>",
+DlgInfoTab : "Informacija",
+DlgAlertUrl : "Prašome įrašyti URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nėra nustatyta>",
+DlgGenId : "Id",
+DlgGenLangDir : "Teksto kryptis",
+DlgGenLangDirLtr : "Iš kairės į dešinę (LTR)",
+DlgGenLangDirRtl : "Iš dešinės į kairę (RTL)",
+DlgGenLangCode : "Kalbos kodas",
+DlgGenAccessKey : "Prieigos raktas",
+DlgGenName : "Vardas",
+DlgGenTabIndex : "Tabuliavimo indeksas",
+DlgGenLongDescr : "Ilgas aprašymas URL",
+DlgGenClass : "Stilių lentelės klasės",
+DlgGenTitle : "Konsultacinė antraštė",
+DlgGenContType : "Konsultacinio turinio tipas",
+DlgGenLinkCharset : "Susietų išteklių simbolių lentelė",
+DlgGenStyle : "Stilius",
+
+// Image Dialog
+DlgImgTitle : "Vaizdo savybės",
+DlgImgInfoTab : "Vaizdo informacija",
+DlgImgBtnUpload : "Siųsti į serverį",
+DlgImgURL : "URL",
+DlgImgUpload : "Nusiųsti",
+DlgImgAlt : "Alternatyvus Tekstas",
+DlgImgWidth : "Plotis",
+DlgImgHeight : "Aukštis",
+DlgImgLockRatio : "Išlaikyti proporciją",
+DlgBtnResetSize : "Atstatyti dydį",
+DlgImgBorder : "Rėmelis",
+DlgImgHSpace : "Hor.Erdvė",
+DlgImgVSpace : "Vert.Erdvė",
+DlgImgAlign : "Lygiuoti",
+DlgImgAlignLeft : "Kairę",
+DlgImgAlignAbsBottom: "Absoliučią apačią",
+DlgImgAlignAbsMiddle: "Absoliutų vidurį",
+DlgImgAlignBaseline : "Apatinę liniją",
+DlgImgAlignBottom : "Apačią",
+DlgImgAlignMiddle : "Vidurį",
+DlgImgAlignRight : "Dešinę",
+DlgImgAlignTextTop : "Teksto viršūnę",
+DlgImgAlignTop : "Viršūnę",
+DlgImgPreview : "Peržiūra",
+DlgImgAlertUrl : "Prašome įvesti vaizdo URL",
+DlgImgLinkTab : "Nuoroda",
+
+// Flash Dialog
+DlgFlashTitle : "Flash savybės",
+DlgFlashChkPlay : "Automatinis paleidimas",
+DlgFlashChkLoop : "Ciklas",
+DlgFlashChkMenu : "Leisti Flash meniu",
+DlgFlashScale : "Mastelis",
+DlgFlashScaleAll : "Rodyti visą",
+DlgFlashScaleNoBorder : "Be rėmelio",
+DlgFlashScaleFit : "Tikslus atitikimas",
+
+// Link Dialog
+DlgLnkWindowTitle : "Nuoroda",
+DlgLnkInfoTab : "Nuorodos informacija",
+DlgLnkTargetTab : "Paskirtis",
+
+DlgLnkType : "Nuorodos tipas",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Žymė šiame puslapyje",
+DlgLnkTypeEMail : "El.paštas",
+DlgLnkProto : "Protokolas",
+DlgLnkProtoOther : "<kitas>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Pasirinkite žymę",
+DlgLnkAnchorByName : "Pagal žymės vardą",
+DlgLnkAnchorById : "Pagal žymės Id",
+DlgLnkNoAnchors : "<Šiame dokumente žymių nėra>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "El.pašto adresas",
+DlgLnkEMailSubject : "Žinutės tema",
+DlgLnkEMailBody : "Žinutės turinys",
+DlgLnkUpload : "Siųsti",
+DlgLnkBtnUpload : "Siųsti į serverį",
+
+DlgLnkTarget : "Paskirties vieta",
+DlgLnkTargetFrame : "<kadras>",
+DlgLnkTargetPopup : "<išskleidžiamas langas>",
+DlgLnkTargetBlank : "Naujas langas (_blank)",
+DlgLnkTargetParent : "Pirminis langas (_parent)",
+DlgLnkTargetSelf : "Tas pats langas (_self)",
+DlgLnkTargetTop : "Svarbiausias langas (_top)",
+DlgLnkTargetFrameName : "Paskirties kadro vardas",
+DlgLnkPopWinName : "Paskirties lango vardas",
+DlgLnkPopWinFeat : "Išskleidžiamo lango savybės",
+DlgLnkPopResize : "Keičiamas dydis",
+DlgLnkPopLocation : "Adreso juosta",
+DlgLnkPopMenu : "Meniu juosta",
+DlgLnkPopScroll : "Slinkties juostos",
+DlgLnkPopStatus : "Būsenos juosta",
+DlgLnkPopToolbar : "Mygtukų juosta",
+DlgLnkPopFullScrn : "Visas ekranas (IE)",
+DlgLnkPopDependent : "Priklausomas (Netscape)",
+DlgLnkPopWidth : "Plotis",
+DlgLnkPopHeight : "Aukštis",
+DlgLnkPopLeft : "Kairė pozicija",
+DlgLnkPopTop : "Viršutinė pozicija",
+
+DlnLnkMsgNoUrl : "Prašome įvesti nuorodos URL",
+DlnLnkMsgNoEMail : "Prašome įvesti el.pašto adresą",
+DlnLnkMsgNoAnchor : "Prašome pasirinkti žymę",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Pasirinkite spalvą",
+DlgColorBtnClear : "Trinti",
+DlgColorHighlight : "Paryškinta",
+DlgColorSelected : "Pažymėta",
+
+// Smiley Dialog
+DlgSmileyTitle : "Įterpti veidelį",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Pasirinkite specialų simbolį",
+
+// Table Dialog
+DlgTableTitle : "Lentelės savybės",
+DlgTableRows : "Eilutės",
+DlgTableColumns : "Stulpeliai",
+DlgTableBorder : "Rėmelio dydis",
+DlgTableAlign : "Lygiuoti",
+DlgTableAlignNotSet : "<Nenustatyta>",
+DlgTableAlignLeft : "Kairę",
+DlgTableAlignCenter : "Centrą",
+DlgTableAlignRight : "Dešinę",
+DlgTableWidth : "Plotis",
+DlgTableWidthPx : "taškais",
+DlgTableWidthPc : "procentais",
+DlgTableHeight : "Aukštis",
+DlgTableCellSpace : "Tarpas tarp langelių",
+DlgTableCellPad : "Trapas nuo langelio rėmo iki teksto",
+DlgTableCaption : "Antraštė",
+DlgTableSummary : "Santrauka",
+
+// Table Cell Dialog
+DlgCellTitle : "Langelio savybės",
+DlgCellWidth : "Plotis",
+DlgCellWidthPx : "taškais",
+DlgCellWidthPc : "procentais",
+DlgCellHeight : "Aukštis",
+DlgCellWordWrap : "Teksto laužymas",
+DlgCellWordWrapNotSet : "<Nenustatyta>",
+DlgCellWordWrapYes : "Taip",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Horizontaliai lygiuoti",
+DlgCellHorAlignNotSet : "<Nenustatyta>",
+DlgCellHorAlignLeft : "Kairę",
+DlgCellHorAlignCenter : "Centrą",
+DlgCellHorAlignRight: "Dešinę",
+DlgCellVerAlign : "Vertikaliai lygiuoti",
+DlgCellVerAlignNotSet : "<Nenustatyta>",
+DlgCellVerAlignTop : "Viršų",
+DlgCellVerAlignMiddle : "Vidurį",
+DlgCellVerAlignBottom : "Apačią",
+DlgCellVerAlignBaseline : "Apatinę liniją",
+DlgCellRowSpan : "Eilučių apjungimas",
+DlgCellCollSpan : "Stulpelių apjungimas",
+DlgCellBackColor : "Fono spalva",
+DlgCellBorderColor : "Rėmelio spalva",
+DlgCellBtnSelect : "Pažymėti...",
+
+// Find Dialog
+DlgFindTitle : "Paieška",
+DlgFindFindBtn : "Surasti",
+DlgFindNotFoundMsg : "Nurodytas tekstas nerastas.",
+
+// Replace Dialog
+DlgReplaceTitle : "Pakeisti",
+DlgReplaceFindLbl : "Surasti tekstą:",
+DlgReplaceReplaceLbl : "Pakeisti tekstu:",
+DlgReplaceCaseChk : "Skirti didžiąsias ir mažąsias raides",
+DlgReplaceReplaceBtn : "Pakeisti",
+DlgReplaceReplAllBtn : "Pakeisti viską",
+DlgReplaceWordChk : "Atitikti pilną žodį",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti iškirpimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl+X).",
+PasteErrorCopy : "Jūsų naršyklės saugumo nustatymai neleidžia redaktoriui automatiškai įvykdyti kopijavimo operacijų. Tam prašome naudoti klaviatūrą (Ctrl+C).",
+
+PasteAsText : "Įdėti kaip gryną tekstą",
+PasteFromWord : "Įdėti iš Word",
+
+DlgPasteMsg2 : "Žemiau esančiame įvedimo lauke įdėkite tekstą, naudodami klaviatūrą (<STRONG>Ctrl+V</STRONG>) ir spūstelkite mygtuką <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoruoti šriftų nustatymus",
+DlgPasteRemoveStyles : "Pašalinti stilių nustatymus",
+DlgPasteCleanBox : "Trinti įvedimo lauką",
+
+// Color Picker
+ColorAutomatic : "Automatinis",
+ColorMoreColors : "Daugiau spalvų...",
+
+// Document Properties
+DocProps : "Dokumento savybės",
+
+// Anchor Dialog
+DlgAnchorTitle : "Žymės savybės",
+DlgAnchorName : "Žymės vardas",
+DlgAnchorErrorName : "Prašome įvesti žymės vardą",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Žodyne nerastas",
+DlgSpellChangeTo : "Pakeisti į",
+DlgSpellBtnIgnore : "Ignoruoti",
+DlgSpellBtnIgnoreAll : "Ignoruoti visus",
+DlgSpellBtnReplace : "Pakeisti",
+DlgSpellBtnReplaceAll : "Pakeisti visus",
+DlgSpellBtnUndo : "Atšaukti",
+DlgSpellNoSuggestions : "- Nėra pasiūlymų -",
+DlgSpellProgress : "Vyksta rašybos tikrinimas...",
+DlgSpellNoMispell : "Rašybos tikrinimas baigtas: Nerasta rašybos klaidų",
+DlgSpellNoChanges : "Rašybos tikrinimas baigtas: Nėra pakeistų žodžių",
+DlgSpellOneChange : "Rašybos tikrinimas baigtas: Vienas žodis pakeistas",
+DlgSpellManyChanges : "Rašybos tikrinimas baigtas: Pakeista %1 žodžių",
+
+IeSpellDownload : "Rašybos tikrinimas neinstaliuotas. Ar Jūs norite jį dabar atsisiųsti?",
+
+// Button Dialog
+DlgButtonText : "Tekstas (Reikšmė)",
+DlgButtonType : "Tipas",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Vardas",
+DlgCheckboxValue : "Reikšmė",
+DlgCheckboxSelected : "Pažymėtas",
+
+// Form Dialog
+DlgFormName : "Vardas",
+DlgFormAction : "Veiksmas",
+DlgFormMethod : "Metodas",
+
+// Select Field Dialog
+DlgSelectName : "Vardas",
+DlgSelectValue : "Reikšmė",
+DlgSelectSize : "Dydis",
+DlgSelectLines : "eilučių",
+DlgSelectChkMulti : "Leisti daugeriopą atranką",
+DlgSelectOpAvail : "Galimos parinktys",
+DlgSelectOpText : "Tekstas",
+DlgSelectOpValue : "Reikšmė",
+DlgSelectBtnAdd : "Įtraukti",
+DlgSelectBtnModify : "Modifikuoti",
+DlgSelectBtnUp : "Aukštyn",
+DlgSelectBtnDown : "Žemyn",
+DlgSelectBtnSetValue : "Laikyti pažymėta reikšme",
+DlgSelectBtnDelete : "Trinti",
+
+// Textarea Dialog
+DlgTextareaName : "Vardas",
+DlgTextareaCols : "Ilgis",
+DlgTextareaRows : "Plotis",
+
+// Text Field Dialog
+DlgTextName : "Vardas",
+DlgTextValue : "Reikšmė",
+DlgTextCharWidth : "Ilgis simboliais",
+DlgTextMaxChars : "Maksimalus simbolių skaičius",
+DlgTextType : "Tipas",
+DlgTextTypeText : "Tekstas",
+DlgTextTypePass : "Slaptažodis",
+
+// Hidden Field Dialog
+DlgHiddenName : "Vardas",
+DlgHiddenValue : "Reikšmė",
+
+// Bulleted List Dialog
+BulletedListProp : "Suženklinto sąrašo savybės",
+NumberedListProp : "Numeruoto sąrašo savybės",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tipas",
+DlgLstTypeCircle : "Apskritimas",
+DlgLstTypeDisc : "Diskas",
+DlgLstTypeSquare : "Kvadratas",
+DlgLstTypeNumbers : "Skaičiai (1, 2, 3)",
+DlgLstTypeLCase : "Mažosios raidės (a, b, c)",
+DlgLstTypeUCase : "Didžiosios raidės (A, B, C)",
+DlgLstTypeSRoman : "Romėnų mažieji skaičiai (i, ii, iii)",
+DlgLstTypeLRoman : "Romėnų didieji skaičiai (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Bendros savybės",
+DlgDocBackTab : "Fonas",
+DlgDocColorsTab : "Spalvos ir kraštinės",
+DlgDocMetaTab : "Meta duomenys",
+
+DlgDocPageTitle : "Puslapio antraštė",
+DlgDocLangDir : "Kalbos kryptis",
+DlgDocLangDirLTR : "Iš kairės į dešinę (LTR)",
+DlgDocLangDirRTL : "Iš dešinės į kairę (RTL)",
+DlgDocLangCode : "Kalbos kodas",
+DlgDocCharSet : "Simbolių kodavimo lentelė",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Kita simbolių kodavimo lentelė",
+
+DlgDocDocType : "Dokumento tipo antraštė",
+DlgDocDocTypeOther : "Kita dokumento tipo antraštė",
+DlgDocIncXHTML : "Įtraukti XHTML deklaracijas",
+DlgDocBgColor : "Fono spalva",
+DlgDocBgImage : "Fono paveikslėlio nuoroda (URL)",
+DlgDocBgNoScroll : "Neslenkantis fonas",
+DlgDocCText : "Tekstas",
+DlgDocCLink : "Nuoroda",
+DlgDocCVisited : "Aplankyta nuoroda",
+DlgDocCActive : "Aktyvi nuoroda",
+DlgDocMargins : "Puslapio kraštinės",
+DlgDocMaTop : "Viršuje",
+DlgDocMaLeft : "Kairėje",
+DlgDocMaRight : "Dešinėje",
+DlgDocMaBottom : "Apačioje",
+DlgDocMeIndex : "Dokumento indeksavimo raktiniai žodžiai (atskirti kableliais)",
+DlgDocMeDescr : "Dokumento apibūdinimas",
+DlgDocMeAuthor : "Autorius",
+DlgDocMeCopy : "Autorinės teisės",
+DlgDocPreview : "Peržiūra",
+
+// Templates Dialog
+Templates : "Šablonai",
+DlgTemplatesTitle : "Turinio šablonai",
+DlgTemplatesSelMsg : "Pasirinkite norimą šabloną<br>(<b>Dėmesio!</b> esamas turinys bus prarastas):",
+DlgTemplatesLoading : "Įkeliamas šablonų sąrašas. Prašome palaukti...",
+DlgTemplatesNoTpl : "(Šablonų sąrašas tuščias)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Apie",
+DlgAboutBrowserInfoTab : "Naršyklės informacija",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "versija",
+DlgAboutInfo : "Papildomą informaciją galima gauti"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/lv.js b/httemplate/elements/fckeditor/editor/lang/lv.js
new file mode 100644
index 000000000..680942675
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/lv.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Latvian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Samazināt rīku joslu",
+ToolbarExpand : "Paplašināt rīku joslu",
+
+// Toolbar Items and Context Menu
+Save : "Saglabāt",
+NewPage : "Jauna lapa",
+Preview : "Pārskatīt",
+Cut : "Izgriezt",
+Copy : "Kopēt",
+Paste : "Ievietot",
+PasteText : "Ievietot kā vienkāršu tekstu",
+PasteWord : "Ievietot no Worda",
+Print : "Drukāt",
+SelectAll : "Iezīmēt visu",
+RemoveFormat : "Noņemt stilus",
+InsertLinkLbl : "Hipersaite",
+InsertLink : "Ievietot/Labot hipersaiti",
+RemoveLink : "Noņemt hipersaiti",
+Anchor : "Ievietot/Labot iezīmi",
+InsertImageLbl : "Attēls",
+InsertImage : "Ievietot/Labot Attēlu",
+InsertFlashLbl : "Flash",
+InsertFlash : "Ievietot/Labot Flash",
+InsertTableLbl : "Tabula",
+InsertTable : "Ievietot/Labot Tabulu",
+InsertLineLbl : "Atdalītājsvītra",
+InsertLine : "Ievietot horizontālu Atdalītājsvītru",
+InsertSpecialCharLbl: "Īpašs simbols",
+InsertSpecialChar : "Ievietot speciālo simbolu",
+InsertSmileyLbl : "Smaidiņi",
+InsertSmiley : "Ievietot smaidiņu",
+About : "Īsumā par FCKeditor",
+Bold : "Treknu šriftu",
+Italic : "Slīprakstā",
+Underline : "Apakšsvītra",
+StrikeThrough : "Pārsvītrots",
+Subscript : "Zemrakstā",
+Superscript : "Augšrakstā",
+LeftJustify : "Izlīdzināt pa kreisi",
+CenterJustify : "Izlīdzināt pret centru",
+RightJustify : "Izlīdzināt pa labi",
+BlockJustify : "Izlīdzināt malas",
+DecreaseIndent : "Samazināt atkāpi",
+IncreaseIndent : "Palielināt atkāpi",
+Undo : "Atcelt",
+Redo : "Atkārtot",
+NumberedListLbl : "Numurēts saraksts",
+NumberedList : "Ievietot/Noņemt numerēto sarakstu",
+BulletedListLbl : "Izcelts saraksts",
+BulletedList : "Ievietot/Noņemt izceltu sarakstu",
+ShowTableBorders : "Parādīt tabulas robežas",
+ShowDetails : "Parādīt sīkāku informāciju",
+Style : "Stils",
+FontFormat : "Formāts",
+Font : "Šrifts",
+FontSize : "Izmērs",
+TextColor : "Teksta krāsa",
+BGColor : "Fona krāsa",
+Source : "HTML kods",
+Find : "Meklēt",
+Replace : "Nomainīt",
+SpellCheck : "Pareizrakstības pārbaude",
+UniversalKeyboard : "Universāla klaviatūra",
+PageBreakLbl : "Lapas pārtraukums",
+PageBreak : "Ievietot lapas pārtraukumu",
+
+Form : "Forma",
+Checkbox : "Atzīmēšanas kastīte",
+RadioButton : "Izvēles poga",
+TextField : "Teksta rinda",
+Textarea : "Teksta laukums",
+HiddenField : "Paslēpta teksta rinda",
+Button : "Poga",
+SelectionField : "Iezīmēšanas lauks",
+ImageButton : "Attēlpoga",
+
+FitWindow : "Maksimizēt redaktora izmēru",
+
+// Context Menu
+EditLink : "Labot hipersaiti",
+CellCM : "Šūna",
+RowCM : "Rinda",
+ColumnCM : "Kolonna",
+InsertRow : "Ievietot rindu",
+DeleteRows : "Dzēst rindas",
+InsertColumn : "Ievietot kolonnu",
+DeleteColumns : "Dzēst kolonnas",
+InsertCell : "Ievietot rūtiņu",
+DeleteCells : "Dzēst rūtiņas",
+MergeCells : "Apvienot rūtiņas",
+SplitCell : "Sadalīt rūtiņu",
+TableDelete : "Dzēst tabulu",
+CellProperties : "Rūtiņas īpašības",
+TableProperties : "Tabulas īpašības",
+ImageProperties : "Attēla īpašības",
+FlashProperties : "Flash īpašības",
+
+AnchorProp : "Iezīmes īpašības",
+ButtonProp : "Pogas īpašības",
+CheckboxProp : "Atzīmēšanas kastītes īpašības",
+HiddenFieldProp : "Paslēptās teksta rindas īpašības",
+RadioButtonProp : "Izvēles poga īpašības",
+ImageButtonProp : "Attēlpogas īpašības",
+TextFieldProp : "Teksta rindas īpašības",
+SelectionFieldProp : "Iezīmēšanas lauka īpašības",
+TextareaProp : "Teksta laukuma īpašības",
+FormProp : "Formas īpašības",
+
+FontFormats : "Normāls teksts;Formatēts teksts;Adrese;Virsraksts 1;Virsraksts 2;Virsraksts 3;Virsraksts 4;Virsraksts 5;Virsraksts 6;Rindkopa (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Tiek apstrādāts XHTML. Lūdzu uzgaidiet...",
+Done : "Darīts",
+PasteWordConfirm : "Teksta fragments, kas tiek ievietots, izskatās, ka būtu sagatavots Word'ā. Vai vēlaties to apstrādāt pirms ievietošanas?",
+NotCompatiblePaste : "Šī darbība ir pieejama Internet Explorer'ī, kas jaunāks par 5.5 versiju. Vai vēlaties ievietot bez apstrādes?",
+UnknownToolbarItem : "Nezināms rīku joslas objekts \"%1\"",
+UnknownCommand : "Nezināmas darbības nosaukums \"%1\"",
+NotImplemented : "Darbība netika paveikta",
+UnknownToolbarSet : "Rīku joslas komplekts \"%1\" neeksistē",
+NoActiveX : "Interneta pārlūkprogrammas drošības uzstādījumi varētu ietekmēt dažas no redaktora īpašībām. Jābūt aktivizētai sadaļai \"Run ActiveX controls and plug-ins\". Savādāk ir iespējamas kļūdas darbībā un kļūdu paziņojumu parādīšanās.",
+BrowseServerBlocked : "Resursu pārlūks nevar tikt atvērts. Pārliecinieties, ka uznirstošo logu bloķētāji ir atslēgti.",
+DialogBlocked : "Nav iespējams atvērt dialoglogu. Pārliecinieties, ka uznirstošo logu bloķētāji ir atslēgti.",
+
+// Dialogs
+DlgBtnOK : "Darīts!",
+DlgBtnCancel : "Atcelt",
+DlgBtnClose : "Aizvērt",
+DlgBtnBrowseServer : "Skatīt servera saturu",
+DlgAdvancedTag : "Izvērstais",
+DlgOpOther : "<Cits>",
+DlgInfoTab : "Informācija",
+DlgAlertUrl : "Lūdzu, ievietojiet hipersaiti",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nav iestatīts>",
+DlgGenId : "Id",
+DlgGenLangDir : "Valodas lasīšanas virziens",
+DlgGenLangDirLtr : "No kreisās uz labo (LTR)",
+DlgGenLangDirRtl : "No labās uz kreiso (RTL)",
+DlgGenLangCode : "Valodas kods",
+DlgGenAccessKey : "Pieejas kods",
+DlgGenName : "Nosaukums",
+DlgGenTabIndex : "Ciļņu indekss",
+DlgGenLongDescr : "Gara apraksta Hipersaite",
+DlgGenClass : "Stilu saraksta klases",
+DlgGenTitle : "Konsultatīvs virsraksts",
+DlgGenContType : "Konsultatīvs satura tips",
+DlgGenLinkCharset : "Pievienotā resursa kodu tabula",
+DlgGenStyle : "Stils",
+
+// Image Dialog
+DlgImgTitle : "Attēla īpašības",
+DlgImgInfoTab : "Informācija par attēlu",
+DlgImgBtnUpload : "Nosūtīt serverim",
+DlgImgURL : "URL",
+DlgImgUpload : "Augšupielādēt",
+DlgImgAlt : "Alternatīvais teksts",
+DlgImgWidth : "Platums",
+DlgImgHeight : "Augstums",
+DlgImgLockRatio : "Nemainīga Augstuma/Platuma attiecība",
+DlgBtnResetSize : "Atjaunot sākotnējo izmēru",
+DlgImgBorder : "Rāmis",
+DlgImgHSpace : "Horizontālā telpa",
+DlgImgVSpace : "Vertikālā telpa",
+DlgImgAlign : "Nolīdzināt",
+DlgImgAlignLeft : "Pa kreisi",
+DlgImgAlignAbsBottom: "Absolūti apakšā",
+DlgImgAlignAbsMiddle: "Absolūti vertikāli centrēts",
+DlgImgAlignBaseline : "Pamatrindā",
+DlgImgAlignBottom : "Apakšā",
+DlgImgAlignMiddle : "Vertikāli centrēts",
+DlgImgAlignRight : "Pa labi",
+DlgImgAlignTextTop : "Teksta augšā",
+DlgImgAlignTop : "Augšā",
+DlgImgPreview : "Pārskats",
+DlgImgAlertUrl : "Lūdzu norādīt attēla hipersaiti",
+DlgImgLinkTab : "Hipersaite",
+
+// Flash Dialog
+DlgFlashTitle : "Flash īpašības",
+DlgFlashChkPlay : "Automātiska atskaņošana",
+DlgFlashChkLoop : "Nepārtraukti",
+DlgFlashChkMenu : "Atļaut Flash izvēlni",
+DlgFlashScale : "Mainīt izmēru",
+DlgFlashScaleAll : "Rādīt visu",
+DlgFlashScaleNoBorder : "Bez rāmja",
+DlgFlashScaleFit : "Precīzs izmērs",
+
+// Link Dialog
+DlgLnkWindowTitle : "Hipersaite",
+DlgLnkInfoTab : "Hipersaites informācija",
+DlgLnkTargetTab : "Mērķis",
+
+DlgLnkType : "Hipersaites tips",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Iezīme šajā lapā",
+DlgLnkTypeEMail : "E-pasts",
+DlgLnkProto : "Protokols",
+DlgLnkProtoOther : "<cits>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Izvēlēties iezīmi",
+DlgLnkAnchorByName : "Pēc iezīmes nosaukuma",
+DlgLnkAnchorById : "Pēc elementa ID",
+DlgLnkNoAnchors : "<Šajā dokumentā nav iezīmju>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-pasta adrese",
+DlgLnkEMailSubject : "Ziņas tēma",
+DlgLnkEMailBody : "Ziņas saturs",
+DlgLnkUpload : "Augšupielādēt",
+DlgLnkBtnUpload : "Nosūtīt serverim",
+
+DlgLnkTarget : "Mērķis",
+DlgLnkTargetFrame : "<ietvars>",
+DlgLnkTargetPopup : "<uznirstošā logā>",
+DlgLnkTargetBlank : "Jaunā logā (_blank)",
+DlgLnkTargetParent : "Esošajā logā (_parent)",
+DlgLnkTargetSelf : "Tajā pašā logā (_self)",
+DlgLnkTargetTop : "Visredzamākajā logā (_top)",
+DlgLnkTargetFrameName : "Mērķa ietvara nosaukums",
+DlgLnkPopWinName : "Uznirstošā loga nosaukums",
+DlgLnkPopWinFeat : "Uznirstošā loga nosaukums īpašības",
+DlgLnkPopResize : "Ar maināmu izmēru",
+DlgLnkPopLocation : "Atrašanās vietas josla",
+DlgLnkPopMenu : "Izvēlnes josla",
+DlgLnkPopScroll : "Ritjoslas",
+DlgLnkPopStatus : "Statusa josla",
+DlgLnkPopToolbar : "Rīku josla",
+DlgLnkPopFullScrn : "Pilnā ekrānā (IE)",
+DlgLnkPopDependent : "Atkarīgs (Netscape)",
+DlgLnkPopWidth : "Platums",
+DlgLnkPopHeight : "Augstums",
+DlgLnkPopLeft : "Kreisā koordināte",
+DlgLnkPopTop : "Augšējā koordināte",
+
+DlnLnkMsgNoUrl : "Lūdzu norādi hipersaiti",
+DlnLnkMsgNoEMail : "Lūdzu norādi e-pasta adresi",
+DlnLnkMsgNoAnchor : "Lūdzu norādi iezīmi",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Izvēlies krāsu",
+DlgColorBtnClear : "Dzēst",
+DlgColorHighlight : "Izcelt",
+DlgColorSelected : "Iezīmētais",
+
+// Smiley Dialog
+DlgSmileyTitle : "Ievietot smaidiņu",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Ievietot īpašu simbolu",
+
+// Table Dialog
+DlgTableTitle : "Tabulas īpašības",
+DlgTableRows : "Rindas",
+DlgTableColumns : "Kolonnas",
+DlgTableBorder : "Rāmja izmērs",
+DlgTableAlign : "Novietojums",
+DlgTableAlignNotSet : "<nav norādīts>",
+DlgTableAlignLeft : "Pa kreisi",
+DlgTableAlignCenter : "Centrēti",
+DlgTableAlignRight : "Pa labi",
+DlgTableWidth : "Platums",
+DlgTableWidthPx : "pikseļos",
+DlgTableWidthPc : "procentuāli",
+DlgTableHeight : "Augstums",
+DlgTableCellSpace : "Rūtiņu atstatums",
+DlgTableCellPad : "Rūtiņu nobīde",
+DlgTableCaption : "Leģenda",
+DlgTableSummary : "Anotācija",
+
+// Table Cell Dialog
+DlgCellTitle : "Rūtiņas īpašības",
+DlgCellWidth : "Platums",
+DlgCellWidthPx : "pikseļi",
+DlgCellWidthPc : "procentos",
+DlgCellHeight : "Augstums",
+DlgCellWordWrap : "Teksta pārnese",
+DlgCellWordWrapNotSet : "<nav norādīta>",
+DlgCellWordWrapYes : "Jā",
+DlgCellWordWrapNo : "Nē",
+DlgCellHorAlign : "Horizontāla novietojums",
+DlgCellHorAlignNotSet : "<Nav norādīts>",
+DlgCellHorAlignLeft : "Pa kreisi",
+DlgCellHorAlignCenter : "Centrēti",
+DlgCellHorAlignRight: "Pa labi",
+DlgCellVerAlign : "Vertikālais novietojums",
+DlgCellVerAlignNotSet : "<nav norādīts>",
+DlgCellVerAlignTop : "Augša",
+DlgCellVerAlignMiddle : "Vidus",
+DlgCellVerAlignBottom : "Apakša",
+DlgCellVerAlignBaseline : "Pamatrindā",
+DlgCellRowSpan : "Rindu pārnese",
+DlgCellCollSpan : "Kolonnu pārnese",
+DlgCellBackColor : "Fona krāsa",
+DlgCellBorderColor : "Rāmja krāsa",
+DlgCellBtnSelect : "Iezīmē...",
+
+// Find Dialog
+DlgFindTitle : "Meklētājs",
+DlgFindFindBtn : "Meklēt",
+DlgFindNotFoundMsg : "Norādītā frāze netika atrasta.",
+
+// Replace Dialog
+DlgReplaceTitle : "Aizvietošana",
+DlgReplaceFindLbl : "Meklēt:",
+DlgReplaceReplaceLbl : "Nomainīt uz:",
+DlgReplaceCaseChk : "Reģistrjūtīgs",
+DlgReplaceReplaceBtn : "Aizvietot",
+DlgReplaceReplAllBtn : "Aizvietot visu",
+DlgReplaceWordChk : "Jāsakrīt pilnībā",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj editoram automātiski veikt izgriešanas darbību. Lūdzu, izmantojiet (Ctrl+X, lai veiktu šo darbību.",
+PasteErrorCopy : "Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj editoram automātiski veikt kopēšanas darbību. Lūdzu, izmantojiet (Ctrl+C), lai veiktu šo darbību.",
+
+PasteAsText : "Ievietot kā vienkāršu tekstu",
+PasteFromWord : "Ievietot no Worda",
+
+DlgPasteMsg2 : "Lūdzu, ievietojiet tekstu šajā laukumā, izmantojot klaviatūru (<STRONG>Ctrl+V</STRONG>) un apstipriniet ar <STRONG>Darīts!</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorēt iepriekš norādītos fontus",
+DlgPasteRemoveStyles : "Noņemt norādītos stilus",
+DlgPasteCleanBox : "Apstrādāt laukuma saturu",
+
+// Color Picker
+ColorAutomatic : "Automātiska",
+ColorMoreColors : "Plašāka palete...",
+
+// Document Properties
+DocProps : "Dokumenta īpašības",
+
+// Anchor Dialog
+DlgAnchorTitle : "Iezīmes īpašības",
+DlgAnchorName : "Iezīmes nosaukums",
+DlgAnchorErrorName : "Lūdzu norādiet iezīmes nosaukumu",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Netika atrasts vārdnīcā",
+DlgSpellChangeTo : "Nomainīt uz",
+DlgSpellBtnIgnore : "Ignorēt",
+DlgSpellBtnIgnoreAll : "Ignorēt visu",
+DlgSpellBtnReplace : "Aizvietot",
+DlgSpellBtnReplaceAll : "Aizvietot visu",
+DlgSpellBtnUndo : "Atcelt",
+DlgSpellNoSuggestions : "- Nav ieteikumu -",
+DlgSpellProgress : "Notiek pareizrakstības pārbaude...",
+DlgSpellNoMispell : "Pareizrakstības pārbaude pabeigta: kļūdas netika atrastas",
+DlgSpellNoChanges : "Pareizrakstības pārbaude pabeigta: nekas netika labots",
+DlgSpellOneChange : "Pareizrakstības pārbaude pabeigta: 1 vārds izmainīts",
+DlgSpellManyChanges : "Pareizrakstības pārbaude pabeigta: %1 vārdi tika mainīti",
+
+IeSpellDownload : "Pareizrakstības pārbaudītājs nav pievienots. Vai vēlaties to lejupielādēt tagad?",
+
+// Button Dialog
+DlgButtonText : "Teksts (vērtība)",
+DlgButtonType : "Tips",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nosaukums",
+DlgCheckboxValue : "Vērtība",
+DlgCheckboxSelected : "Iezīmēts",
+
+// Form Dialog
+DlgFormName : "Nosaukums",
+DlgFormAction : "Darbība",
+DlgFormMethod : "Metode",
+
+// Select Field Dialog
+DlgSelectName : "Nosaukums",
+DlgSelectValue : "Vērtība",
+DlgSelectSize : "Izmērs",
+DlgSelectLines : "rindas",
+DlgSelectChkMulti : "Atļaut vairākus iezīmējumus",
+DlgSelectOpAvail : "Pieejamās iespējas",
+DlgSelectOpText : "Teksts",
+DlgSelectOpValue : "Vērtība",
+DlgSelectBtnAdd : "Pievienot",
+DlgSelectBtnModify : "Veikt izmaiņas",
+DlgSelectBtnUp : "Augšup",
+DlgSelectBtnDown : "Lejup",
+DlgSelectBtnSetValue : "Noteikt kā iezīmēto vērtību",
+DlgSelectBtnDelete : "Dzēst",
+
+// Textarea Dialog
+DlgTextareaName : "Nosaukums",
+DlgTextareaCols : "Kolonnas",
+DlgTextareaRows : "Rindas",
+
+// Text Field Dialog
+DlgTextName : "Nosaukums",
+DlgTextValue : "Vērtība",
+DlgTextCharWidth : "Simbolu platums",
+DlgTextMaxChars : "Simbolu maksimālais daudzums",
+DlgTextType : "Tips",
+DlgTextTypeText : "Teksts",
+DlgTextTypePass : "Parole",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nosaukums",
+DlgHiddenValue : "Vērtība",
+
+// Bulleted List Dialog
+BulletedListProp : "Aizzīmju saraksta īpašības",
+NumberedListProp : "Numerētā saraksta īpašības",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tips",
+DlgLstTypeCircle : "Aplis",
+DlgLstTypeDisc : "Disks",
+DlgLstTypeSquare : "Kvadrāts",
+DlgLstTypeNumbers : "Skaitļi (1, 2, 3)",
+DlgLstTypeLCase : "Maziem burtiem (a, b, c)",
+DlgLstTypeUCase : "Lieliem burtiem (A, B, C)",
+DlgLstTypeSRoman : "Maziem romiešu cipariem (i, ii, iii)",
+DlgLstTypeLRoman : "Lieliem romiešu cipariem (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Vispārīga informācija",
+DlgDocBackTab : "Fons",
+DlgDocColorsTab : "Krāsas un robežu nobīdes",
+DlgDocMetaTab : "META dati",
+
+DlgDocPageTitle : "Dokumenta virsraksts <Title>",
+DlgDocLangDir : "Valodas lasīšanas virziens",
+DlgDocLangDirLTR : "No kreisās uz labo (LTR)",
+DlgDocLangDirRTL : "No labās uz kreiso (RTL)",
+DlgDocLangCode : "Valodas kods",
+DlgDocCharSet : "Simbolu kodējums",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Cits simbolu kodējums",
+
+DlgDocDocType : "Dokumenta tips",
+DlgDocDocTypeOther : "Cits dokumenta tips",
+DlgDocIncXHTML : "Ietvert XHTML deklarācijas",
+DlgDocBgColor : "Fona krāsa",
+DlgDocBgImage : "Fona attēla hipersaite",
+DlgDocBgNoScroll : "Fona attēls ir fiksēts",
+DlgDocCText : "Teksts",
+DlgDocCLink : "Hipersaite",
+DlgDocCVisited : "Apmeklēta hipersaite",
+DlgDocCActive : "Aktīva hipersaite",
+DlgDocMargins : "Lapas robežas",
+DlgDocMaTop : "Augšā",
+DlgDocMaLeft : "Pa kreisi",
+DlgDocMaRight : "Pa labi",
+DlgDocMaBottom : "Apakšā",
+DlgDocMeIndex : "Dokumentu aprakstoši atslēgvārdi (atdalīti ar komatu)",
+DlgDocMeDescr : "Dokumenta apraksts",
+DlgDocMeAuthor : "Autors",
+DlgDocMeCopy : "Autortiesības",
+DlgDocPreview : "Priekšskats",
+
+// Templates Dialog
+Templates : "Sagataves",
+DlgTemplatesTitle : "Satura sagataves",
+DlgTemplatesSelMsg : "Lūdzu, norādiet sagatavi, ko atvērt editorā<br>(patreizējie dati tiks zaudēti):",
+DlgTemplatesLoading : "Notiek sagatavju saraksta ielāde. Lūdzu, uzgaidiet...",
+DlgTemplatesNoTpl : "(Nav norādītas sagataves)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Par",
+DlgAboutBrowserInfoTab : "Informācija par pārlūkprogrammu",
+DlgAboutLicenseTab : "Licence",
+DlgAboutVersion : "versija",
+DlgAboutInfo : "Papildus informācija ir pieejama"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/mn.js b/httemplate/elements/fckeditor/editor/lang/mn.js
new file mode 100644
index 000000000..ba8f798e6
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/mn.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Mongolian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Багажны хэсэг эвдэх",
+ToolbarExpand : "Багажны хэсэг өргөтгөх",
+
+// Toolbar Items and Context Menu
+Save : "Хадгалах",
+NewPage : "Шинэ хуудас",
+Preview : "Уридчлан харах",
+Cut : "Хайчлах",
+Copy : "Хуулах",
+Paste : "Буулгах",
+PasteText : "plain text-ээс буулгах",
+PasteWord : "Word-оос буулгах",
+Print : "Хэвлэх",
+SelectAll : "Бүгдийг нь сонгох",
+RemoveFormat : "Формат авч хаях",
+InsertLinkLbl : "Линк",
+InsertLink : "Линк Оруулах/Засварлах",
+RemoveLink : "Линк авч хаях",
+Anchor : "Insert/Edit Anchor", //MISSING
+InsertImageLbl : "Зураг",
+InsertImage : "Зураг Оруулах/Засварлах",
+InsertFlashLbl : "Flash", //MISSING
+InsertFlash : "Insert/Edit Flash", //MISSING
+InsertTableLbl : "Хүснэгт",
+InsertTable : "Хүснэгт Оруулах/Засварлах",
+InsertLineLbl : "Зураас",
+InsertLine : "Хөндлөн зураас оруулах",
+InsertSpecialCharLbl: "Онцгой тэмдэгт",
+InsertSpecialChar : "Онцгой тэмдэгт оруулах",
+InsertSmileyLbl : "Тодорхойлолт",
+InsertSmiley : "Тодорхойлолт оруулах",
+About : "FCKeditor-н тухай",
+Bold : "Тод бүдүүн",
+Italic : "Налуу",
+Underline : "Доогуур нь зураастай болгох",
+StrikeThrough : "Дундуур нь зураастай болгох",
+Subscript : "Суурь болгох",
+Superscript : "Зэрэг болгох",
+LeftJustify : "Зүүн талд байрлуулах",
+CenterJustify : "Төвд байрлуулах",
+RightJustify : "Баруун талд байрлуулах",
+BlockJustify : "Блок хэлбэрээр байрлуулах",
+DecreaseIndent : "Догол мөр нэмэх",
+IncreaseIndent : "Догол мөр хасах",
+Undo : "Хүчингүй болгох",
+Redo : "Өмнөх үйлдлээ сэргээх",
+NumberedListLbl : "Дугаарлагдсан жагсаалт",
+NumberedList : "Дугаарлагдсан жагсаалт Оруулах/Авах",
+BulletedListLbl : "Цэгтэй жагсаалт",
+BulletedList : "Цэгтэй жагсаалт Оруулах/Авах",
+ShowTableBorders : "Хүснэгтийн хүрээг үзүүлэх",
+ShowDetails : "Деталчлан үзүүлэх",
+Style : "Загвар",
+FontFormat : "Формат",
+Font : "Фонт",
+FontSize : "Хэмжээ",
+TextColor : "Фонтны өнгө",
+BGColor : "Фонны өнгө",
+Source : "Код",
+Find : "Хайх",
+Replace : "Солих",
+SpellCheck : "Check Spelling", //MISSING
+UniversalKeyboard : "Universal Keyboard", //MISSING
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Form", //MISSING
+Checkbox : "Checkbox", //MISSING
+RadioButton : "Radio Button", //MISSING
+TextField : "Text Field", //MISSING
+Textarea : "Textarea", //MISSING
+HiddenField : "Hidden Field", //MISSING
+Button : "Button", //MISSING
+SelectionField : "Selection Field", //MISSING
+ImageButton : "Image Button", //MISSING
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Холбоос засварлах",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Мөр оруулах",
+DeleteRows : "Мөр устгах",
+InsertColumn : "Багана оруулах",
+DeleteColumns : "Багана устгах",
+InsertCell : "Нүх оруулах",
+DeleteCells : "Нүх устгах",
+MergeCells : "Нүх нэгтэх",
+SplitCell : "Нүх тусгайрлах",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Хоосон зайн шинж чанар",
+TableProperties : "Хүснэгт",
+ImageProperties : "Зураг",
+FlashProperties : "Flash Properties", //MISSING
+
+AnchorProp : "Anchor Properties", //MISSING
+ButtonProp : "Button Properties", //MISSING
+CheckboxProp : "Checkbox Properties", //MISSING
+HiddenFieldProp : "Hidden Field Properties", //MISSING
+RadioButtonProp : "Radio Button Properties", //MISSING
+ImageButtonProp : "Image Button Properties", //MISSING
+TextFieldProp : "Text Field Properties", //MISSING
+SelectionFieldProp : "Selection Field Properties", //MISSING
+TextareaProp : "Textarea Properties", //MISSING
+FormProp : "Form Properties", //MISSING
+
+FontFormats : "Хэвийн;Formatted;Хаяг;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Paragraph (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML үйл явц явагдаж байна. Хүлээнэ үү...",
+Done : "Хийх",
+PasteWordConfirm : "Word-оос хуулсан текстээ санаж байгааг нь буулгахыг та хүсч байна уу. Та текст-ээ буулгахын өмнө цэвэрлэх үү?",
+NotCompatiblePaste : "Энэ комманд Internet Explorer-ын 5.5 буюу түүнээс дээш хувилбарт идвэхшинэ. Та цэвэрлэхгүйгээр буулгахыг хүсч байна?",
+UnknownToolbarItem : "Багажны хэсгийн \"%1\" item мэдэгдэхгүй байна",
+UnknownCommand : "\"%1\" комманд нэр мэдагдэхгүй байна",
+NotImplemented : "Зөвшөөрөгдөхгүй комманд",
+UnknownToolbarSet : "Багажны хэсэгт \"%1\" оноох, үүсээгүй байна",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Болих",
+DlgBtnClose : "Хаах",
+DlgBtnBrowseServer : "Browse Server", //MISSING
+DlgAdvancedTag : "Нэмэлт",
+DlgOpOther : "<Other>", //MISSING
+DlgInfoTab : "Info", //MISSING
+DlgAlertUrl : "Please insert the URL", //MISSING
+
+// General Dialogs Labels
+DlgGenNotSet : "<Оноохгүй>",
+DlgGenId : "Id",
+DlgGenLangDir : "Хэлний чиглэл",
+DlgGenLangDirLtr : "Зүүнээс баруун (LTR)",
+DlgGenLangDirRtl : "Баруунаас зүүн (RTL)",
+DlgGenLangCode : "Хэлний код",
+DlgGenAccessKey : "Холбох түлхүүр",
+DlgGenName : "Нэр",
+DlgGenTabIndex : "Tab индекс",
+DlgGenLongDescr : "URL-ын тайлбар",
+DlgGenClass : "Stylesheet классууд",
+DlgGenTitle : "Зөвлөлдөх гарчиг",
+DlgGenContType : "Зөвлөлдөх төрлийн агуулга",
+DlgGenLinkCharset : "Тэмдэгт оноох нөөцөд холбогдсон",
+DlgGenStyle : "Загвар",
+
+// Image Dialog
+DlgImgTitle : "Зураг",
+DlgImgInfoTab : "Зурагны мэдээлэл",
+DlgImgBtnUpload : "Үүнийг сервэррүү илгээ",
+DlgImgURL : "URL",
+DlgImgUpload : "Хуулах",
+DlgImgAlt : "Тайлбар текст",
+DlgImgWidth : "Өргөн",
+DlgImgHeight : "Өндөр",
+DlgImgLockRatio : "Lock Ratio",
+DlgBtnResetSize : "хэмжээ дахин оноох",
+DlgImgBorder : "Хүрээ",
+DlgImgHSpace : "Хөндлөн зай",
+DlgImgVSpace : "Босоо зай",
+DlgImgAlign : "Эгнээ",
+DlgImgAlignLeft : "Зүүн",
+DlgImgAlignAbsBottom: "Abs доод талд",
+DlgImgAlignAbsMiddle: "Abs Дунд талд",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Доод талд",
+DlgImgAlignMiddle : "Дунд талд",
+DlgImgAlignRight : "Баруун",
+DlgImgAlignTextTop : "Текст дээр",
+DlgImgAlignTop : "Дээд талд",
+DlgImgPreview : "Уридчлан харах",
+DlgImgAlertUrl : "Зурагны URL-ын төрлийн сонгоно уу",
+DlgImgLinkTab : "Link", //MISSING
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties", //MISSING
+DlgFlashChkPlay : "Auto Play", //MISSING
+DlgFlashChkLoop : "Loop", //MISSING
+DlgFlashChkMenu : "Enable Flash Menu", //MISSING
+DlgFlashScale : "Scale", //MISSING
+DlgFlashScaleAll : "Show all", //MISSING
+DlgFlashScaleNoBorder : "No Border", //MISSING
+DlgFlashScaleFit : "Exact Fit", //MISSING
+
+// Link Dialog
+DlgLnkWindowTitle : "Линк",
+DlgLnkInfoTab : "Линкийн мэдээлэл",
+DlgLnkTargetTab : "Байрлал",
+
+DlgLnkType : "Линкийн төрөл",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Энэ хуудасандах холбоос",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Протокол",
+DlgLnkProtoOther : "<бусад>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Холбоос сонгох",
+DlgLnkAnchorByName : "Холбоосын нэрээр",
+DlgLnkAnchorById : "Элемэнт Id-гаар",
+DlgLnkNoAnchors : "<Баримт бичиг холбоосгүй байна>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail Хаяг",
+DlgLnkEMailSubject : "Message Subject",
+DlgLnkEMailBody : "Message-ийн агуулга",
+DlgLnkUpload : "Хуулах",
+DlgLnkBtnUpload : "Үүнийг серверрүү илгээ",
+
+DlgLnkTarget : "Байрлал",
+DlgLnkTargetFrame : "<Агуулах хүрээ>",
+DlgLnkTargetPopup : "<popup цонх>",
+DlgLnkTargetBlank : "Шинэ цонх (_blank)",
+DlgLnkTargetParent : "Эцэг цонх (_parent)",
+DlgLnkTargetSelf : "Төстэй цонх (_self)",
+DlgLnkTargetTop : "Хамгийн түрүүн байх цонх (_top)",
+DlgLnkTargetFrameName : "Target Frame Name", //MISSING
+DlgLnkPopWinName : "Popup цонхны нэр",
+DlgLnkPopWinFeat : "Popup цонхны онцлог",
+DlgLnkPopResize : "Хэмжээ өөрчлөх",
+DlgLnkPopLocation : "Location хэсэг",
+DlgLnkPopMenu : "Meню хэсэг",
+DlgLnkPopScroll : "Скрол хэсэгүүд",
+DlgLnkPopStatus : "Статус хэсэг",
+DlgLnkPopToolbar : "Багажны хэсэг",
+DlgLnkPopFullScrn : "Цонх дүүргэх (IE)",
+DlgLnkPopDependent : "Хамаатай (Netscape)",
+DlgLnkPopWidth : "Өргөн",
+DlgLnkPopHeight : "Өндөр",
+DlgLnkPopLeft : "Зүүн байрлал",
+DlgLnkPopTop : "Дээд байрлал",
+
+DlnLnkMsgNoUrl : "Линк URL-ээ төрөлжүүлнэ үү",
+DlnLnkMsgNoEMail : "Е-mail хаягаа төрөлжүүлнэ үү",
+DlnLnkMsgNoAnchor : "Холбоосоо сонгоно уу",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Өнгө сонгох",
+DlgColorBtnClear : "Цэвэрлэх",
+DlgColorHighlight : "Өнгө",
+DlgColorSelected : "Сонгогдсон",
+
+// Smiley Dialog
+DlgSmileyTitle : "Тодорхойлолт оруулах",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Онцгой тэмдэгт сонгох",
+
+// Table Dialog
+DlgTableTitle : "Хүснэгт",
+DlgTableRows : "Мөр",
+DlgTableColumns : "Багана",
+DlgTableBorder : "Хүрээний хэмжээ",
+DlgTableAlign : "Эгнээ",
+DlgTableAlignNotSet : "<Оноохгүй>",
+DlgTableAlignLeft : "Зүүн талд",
+DlgTableAlignCenter : "Төвд",
+DlgTableAlignRight : "Баруун талд",
+DlgTableWidth : "Өргөн",
+DlgTableWidthPx : "цэг",
+DlgTableWidthPc : "хувь",
+DlgTableHeight : "Өндөр",
+DlgTableCellSpace : "Нүх хоорондын зай",
+DlgTableCellPad : "Нүх доторлох",
+DlgTableCaption : "Тайлбар",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Хоосон зайн шинж чанар",
+DlgCellWidth : "Өргөн",
+DlgCellWidthPx : "цэг",
+DlgCellWidthPc : "хувь",
+DlgCellHeight : "Өндөр",
+DlgCellWordWrap : "Үг таслах",
+DlgCellWordWrapNotSet : "<Оноохгүй>",
+DlgCellWordWrapYes : "Тийм",
+DlgCellWordWrapNo : "Үгүй",
+DlgCellHorAlign : "Босоо эгнээ",
+DlgCellHorAlignNotSet : "<Оноохгүй>",
+DlgCellHorAlignLeft : "Зүүн",
+DlgCellHorAlignCenter : "Төв",
+DlgCellHorAlignRight: "Баруун",
+DlgCellVerAlign : "Хөндлөн эгнээ",
+DlgCellVerAlignNotSet : "<Оноохгүй>",
+DlgCellVerAlignTop : "Дээд тал",
+DlgCellVerAlignMiddle : "Дунд",
+DlgCellVerAlignBottom : "Доод тал",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Нийт мөр",
+DlgCellCollSpan : "Нийт багана",
+DlgCellBackColor : "Фонны өнгө",
+DlgCellBorderColor : "Хүрээний өнгө",
+DlgCellBtnSelect : "Сонго...",
+
+// Find Dialog
+DlgFindTitle : "Хайх",
+DlgFindFindBtn : "Хайх",
+DlgFindNotFoundMsg : "Хайсан текст олсонгүй.",
+
+// Replace Dialog
+DlgReplaceTitle : "Солих",
+DlgReplaceFindLbl : "Хайх үг/үсэг:",
+DlgReplaceReplaceLbl : "Солих үг:",
+DlgReplaceCaseChk : "Тэнцэх төлөв",
+DlgReplaceReplaceBtn : "Солих",
+DlgReplaceReplAllBtn : "Бүгдийг нь Солих",
+DlgReplaceWordChk : "Тэнцэх бүтэн үг",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хайчлах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl+X) товчны хослолыг ашиглана уу.",
+PasteErrorCopy : "Таны browser-ын хамгаалалтын тохиргоо editor-д автоматаар хуулах үйлдэлийг зөвшөөрөхгүй байна. (Ctrl+C) товчны хослолыг ашиглана уу.",
+
+PasteAsText : "Plain Text-ээс буулгах",
+PasteFromWord : "Word-оос буулгах",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.", //MISSING
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING
+DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING
+DlgPasteCleanBox : "Clean Up Box", //MISSING
+
+// Color Picker
+ColorAutomatic : "Автоматаар",
+ColorMoreColors : "Нэмэлт өнгөнүүд...",
+
+// Document Properties
+DocProps : "Document Properties", //MISSING
+
+// Anchor Dialog
+DlgAnchorTitle : "Anchor Properties", //MISSING
+DlgAnchorName : "Anchor Name", //MISSING
+DlgAnchorErrorName : "Please type the anchor name", //MISSING
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Not in dictionary", //MISSING
+DlgSpellChangeTo : "Change to", //MISSING
+DlgSpellBtnIgnore : "Ignore", //MISSING
+DlgSpellBtnIgnoreAll : "Ignore All", //MISSING
+DlgSpellBtnReplace : "Replace", //MISSING
+DlgSpellBtnReplaceAll : "Replace All", //MISSING
+DlgSpellBtnUndo : "Undo", //MISSING
+DlgSpellNoSuggestions : "- No suggestions -", //MISSING
+DlgSpellProgress : "Spell check in progress...", //MISSING
+DlgSpellNoMispell : "Spell check complete: No misspellings found", //MISSING
+DlgSpellNoChanges : "Spell check complete: No words changed", //MISSING
+DlgSpellOneChange : "Spell check complete: One word changed", //MISSING
+DlgSpellManyChanges : "Spell check complete: %1 words changed", //MISSING
+
+IeSpellDownload : "Spell checker not installed. Do you want to download it now?", //MISSING
+
+// Button Dialog
+DlgButtonText : "Text (Value)", //MISSING
+DlgButtonType : "Type", //MISSING
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Name", //MISSING
+DlgCheckboxValue : "Value", //MISSING
+DlgCheckboxSelected : "Selected", //MISSING
+
+// Form Dialog
+DlgFormName : "Name", //MISSING
+DlgFormAction : "Action", //MISSING
+DlgFormMethod : "Method", //MISSING
+
+// Select Field Dialog
+DlgSelectName : "Name", //MISSING
+DlgSelectValue : "Value", //MISSING
+DlgSelectSize : "Size", //MISSING
+DlgSelectLines : "lines", //MISSING
+DlgSelectChkMulti : "Allow multiple selections", //MISSING
+DlgSelectOpAvail : "Available Options", //MISSING
+DlgSelectOpText : "Text", //MISSING
+DlgSelectOpValue : "Value", //MISSING
+DlgSelectBtnAdd : "Add", //MISSING
+DlgSelectBtnModify : "Modify", //MISSING
+DlgSelectBtnUp : "Up", //MISSING
+DlgSelectBtnDown : "Down", //MISSING
+DlgSelectBtnSetValue : "Set as selected value", //MISSING
+DlgSelectBtnDelete : "Delete", //MISSING
+
+// Textarea Dialog
+DlgTextareaName : "Name", //MISSING
+DlgTextareaCols : "Columns", //MISSING
+DlgTextareaRows : "Rows", //MISSING
+
+// Text Field Dialog
+DlgTextName : "Name", //MISSING
+DlgTextValue : "Value", //MISSING
+DlgTextCharWidth : "Character Width", //MISSING
+DlgTextMaxChars : "Maximum Characters", //MISSING
+DlgTextType : "Type", //MISSING
+DlgTextTypeText : "Text", //MISSING
+DlgTextTypePass : "Password", //MISSING
+
+// Hidden Field Dialog
+DlgHiddenName : "Name", //MISSING
+DlgHiddenValue : "Value", //MISSING
+
+// Bulleted List Dialog
+BulletedListProp : "Bulleted List Properties", //MISSING
+NumberedListProp : "Numbered List Properties", //MISSING
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Type", //MISSING
+DlgLstTypeCircle : "Circle", //MISSING
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Square", //MISSING
+DlgLstTypeNumbers : "Numbers (1, 2, 3)", //MISSING
+DlgLstTypeLCase : "Lowercase Letters (a, b, c)", //MISSING
+DlgLstTypeUCase : "Uppercase Letters (A, B, C)", //MISSING
+DlgLstTypeSRoman : "Small Roman Numerals (i, ii, iii)", //MISSING
+DlgLstTypeLRoman : "Large Roman Numerals (I, II, III)", //MISSING
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General", //MISSING
+DlgDocBackTab : "Background", //MISSING
+DlgDocColorsTab : "Colors and Margins", //MISSING
+DlgDocMetaTab : "Meta Data", //MISSING
+
+DlgDocPageTitle : "Page Title", //MISSING
+DlgDocLangDir : "Language Direction", //MISSING
+DlgDocLangDirLTR : "Left to Right (LTR)", //MISSING
+DlgDocLangDirRTL : "Right to Left (RTL)", //MISSING
+DlgDocLangCode : "Language Code", //MISSING
+DlgDocCharSet : "Character Set Encoding", //MISSING
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Other Character Set Encoding", //MISSING
+
+DlgDocDocType : "Document Type Heading", //MISSING
+DlgDocDocTypeOther : "Other Document Type Heading", //MISSING
+DlgDocIncXHTML : "Include XHTML Declarations", //MISSING
+DlgDocBgColor : "Background Color", //MISSING
+DlgDocBgImage : "Background Image URL", //MISSING
+DlgDocBgNoScroll : "Nonscrolling Background", //MISSING
+DlgDocCText : "Text", //MISSING
+DlgDocCLink : "Link", //MISSING
+DlgDocCVisited : "Visited Link", //MISSING
+DlgDocCActive : "Active Link", //MISSING
+DlgDocMargins : "Page Margins", //MISSING
+DlgDocMaTop : "Top", //MISSING
+DlgDocMaLeft : "Left", //MISSING
+DlgDocMaRight : "Right", //MISSING
+DlgDocMaBottom : "Bottom", //MISSING
+DlgDocMeIndex : "Document Indexing Keywords (comma separated)", //MISSING
+DlgDocMeDescr : "Document Description", //MISSING
+DlgDocMeAuthor : "Author", //MISSING
+DlgDocMeCopy : "Copyright", //MISSING
+DlgDocPreview : "Preview", //MISSING
+
+// Templates Dialog
+Templates : "Templates", //MISSING
+DlgTemplatesTitle : "Content Templates", //MISSING
+DlgTemplatesSelMsg : "Please select the template to open in the editor<br />(the actual contents will be lost):", //MISSING
+DlgTemplatesLoading : "Loading templates list. Please wait...", //MISSING
+DlgTemplatesNoTpl : "(No templates defined)", //MISSING
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "About", //MISSING
+DlgAboutBrowserInfoTab : "Browser Info", //MISSING
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "Хувилбар",
+DlgAboutInfo : "Мэдээллээр туслах"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ms.js b/httemplate/elements/fckeditor/editor/lang/ms.js
new file mode 100644
index 000000000..efe05299f
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ms.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Malay language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Collapse Toolbar",
+ToolbarExpand : "Expand Toolbar",
+
+// Toolbar Items and Context Menu
+Save : "Simpan",
+NewPage : "Helaian Baru",
+Preview : "Prebiu",
+Cut : "Potong",
+Copy : "Salin",
+Paste : "Tampal",
+PasteText : "Tampal sebagai Text Biasa",
+PasteWord : "Tampal dari Word",
+Print : "Cetak",
+SelectAll : "Pilih Semua",
+RemoveFormat : "Buang Format",
+InsertLinkLbl : "Sambungan",
+InsertLink : "Masukkan/Sunting Sambungan",
+RemoveLink : "Buang Sambungan",
+Anchor : "Masukkan/Sunting Pautan",
+InsertImageLbl : "Gambar",
+InsertImage : "Masukkan/Sunting Gambar",
+InsertFlashLbl : "Flash", //MISSING
+InsertFlash : "Insert/Edit Flash", //MISSING
+InsertTableLbl : "Jadual",
+InsertTable : "Masukkan/Sunting Jadual",
+InsertLineLbl : "Garisan",
+InsertLine : "Masukkan Garisan Membujur",
+InsertSpecialCharLbl: "Huruf Istimewa",
+InsertSpecialChar : "Masukkan Huruf Istimewa",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Masukkan Smiley",
+About : "Tentang FCKeditor",
+Bold : "Bold",
+Italic : "Italic",
+Underline : "Underline",
+StrikeThrough : "Strike Through",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Jajaran Kiri",
+CenterJustify : "Jajaran Tengah",
+RightJustify : "Jajaran Kanan",
+BlockJustify : "Jajaran Blok",
+DecreaseIndent : "Kurangkan Inden",
+IncreaseIndent : "Tambahkan Inden",
+Undo : "Batalkan",
+Redo : "Ulangkan",
+NumberedListLbl : "Senarai bernombor",
+NumberedList : "Masukkan/Sunting Senarai bernombor",
+BulletedListLbl : "Senarai tidak bernombor",
+BulletedList : "Masukkan/Sunting Senarai tidak bernombor",
+ShowTableBorders : "Tunjukkan Border Jadual",
+ShowDetails : "Tunjukkan Butiran",
+Style : "Stail",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Saiz",
+TextColor : "Warna Text",
+BGColor : "Warna Latarbelakang",
+Source : "Sumber",
+Find : "Cari",
+Replace : "Ganti",
+SpellCheck : "Semak Ejaan",
+UniversalKeyboard : "Papan Kekunci Universal",
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Borang",
+Checkbox : "Checkbox",
+RadioButton : "Butang Radio",
+TextField : "Text Field",
+Textarea : "Textarea",
+HiddenField : "Field Tersembunyi",
+Button : "Butang",
+SelectionField : "Field Pilihan",
+ImageButton : "Butang Bergambar",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Sunting Sambungan",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Masukkan Baris",
+DeleteRows : "Buangkan Baris",
+InsertColumn : "Masukkan Lajur",
+DeleteColumns : "Buangkan Lajur",
+InsertCell : "Masukkan Sel",
+DeleteCells : "Buangkan Sel-sel",
+MergeCells : "Cantumkan Sel-sel",
+SplitCell : "Bahagikan Sel",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Ciri-ciri Sel",
+TableProperties : "Ciri-ciri Jadual",
+ImageProperties : "Ciri-ciri Gambar",
+FlashProperties : "Flash Properties", //MISSING
+
+AnchorProp : "Ciri-ciri Pautan",
+ButtonProp : "Ciri-ciri Butang",
+CheckboxProp : "Ciri-ciri Checkbox",
+HiddenFieldProp : "Ciri-ciri Field Tersembunyi",
+RadioButtonProp : "Ciri-ciri Butang Radio",
+ImageButtonProp : "Ciri-ciri Butang Bergambar",
+TextFieldProp : "Ciri-ciri Text Field",
+SelectionFieldProp : "Ciri-ciri Selection Field",
+TextareaProp : "Ciri-ciri Textarea",
+FormProp : "Ciri-ciri Borang",
+
+FontFormats : "Normal;Telah Diformat;Alamat;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Perenggan (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Memproses XHTML. Sila tunggu...",
+Done : "Siap",
+PasteWordConfirm : "Text yang anda hendak tampal adalah berasal dari Word. Adakah anda mahu membuang semua format Word sebelum tampal ke dalam text?",
+NotCompatiblePaste : "Arahan ini bole dilakukan jika anda mempuunyai Internet Explorer version 5.5 atau yang lebih tinggi. Adakah anda hendak tampal text tanpa membuang format Word?",
+UnknownToolbarItem : "Toolbar item tidak diketahui\"%1\"",
+UnknownCommand : "Arahan tidak diketahui \"%1\"",
+NotImplemented : "Arahan tidak terdapat didalam sistem",
+UnknownToolbarSet : "Set toolbar \"%1\" tidak wujud",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Batal",
+DlgBtnClose : "Tutup",
+DlgBtnBrowseServer : "Browse Server",
+DlgAdvancedTag : "Advanced",
+DlgOpOther : "<Lain-lain>",
+DlgInfoTab : "Info", //MISSING
+DlgAlertUrl : "Please insert the URL", //MISSING
+
+// General Dialogs Labels
+DlgGenNotSet : "<tidak di set>",
+DlgGenId : "Id",
+DlgGenLangDir : "Arah Tulisan",
+DlgGenLangDirLtr : "Kiri ke Kanan (LTR)",
+DlgGenLangDirRtl : "Kanan ke Kiri (RTL)",
+DlgGenLangCode : "Kod Bahasa",
+DlgGenAccessKey : "Kunci Akses",
+DlgGenName : "Nama",
+DlgGenTabIndex : "Indeks Tab ",
+DlgGenLongDescr : "Butiran Panjang URL",
+DlgGenClass : "Kelas-kelas Stylesheet",
+DlgGenTitle : "Tajuk Makluman",
+DlgGenContType : "Jenis Kandungan Makluman",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Stail",
+
+// Image Dialog
+DlgImgTitle : "Ciri-ciri Imej",
+DlgImgInfoTab : "Info Imej",
+DlgImgBtnUpload : "Hantar ke Server",
+DlgImgURL : "URL",
+DlgImgUpload : "Muat Naik",
+DlgImgAlt : "Text Alternatif",
+DlgImgWidth : "Lebar",
+DlgImgHeight : "Tinggi",
+DlgImgLockRatio : "Tetapkan Nisbah",
+DlgBtnResetSize : "Saiz Set Semula",
+DlgImgBorder : "Border",
+DlgImgHSpace : "Ruang Melintang",
+DlgImgVSpace : "Ruang Menegak",
+DlgImgAlign : "Jajaran",
+DlgImgAlignLeft : "Kiri",
+DlgImgAlignAbsBottom: "Bawah Mutlak",
+DlgImgAlignAbsMiddle: "Pertengahan Mutlak",
+DlgImgAlignBaseline : "Garis Dasar",
+DlgImgAlignBottom : "Bawah",
+DlgImgAlignMiddle : "Pertengahan",
+DlgImgAlignRight : "Kanan",
+DlgImgAlignTextTop : "Atas Text",
+DlgImgAlignTop : "Atas",
+DlgImgPreview : "Prebiu",
+DlgImgAlertUrl : "Sila taip URL untuk fail gambar",
+DlgImgLinkTab : "Sambungan",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Properties", //MISSING
+DlgFlashChkPlay : "Auto Play", //MISSING
+DlgFlashChkLoop : "Loop", //MISSING
+DlgFlashChkMenu : "Enable Flash Menu", //MISSING
+DlgFlashScale : "Scale", //MISSING
+DlgFlashScaleAll : "Show all", //MISSING
+DlgFlashScaleNoBorder : "No Border", //MISSING
+DlgFlashScaleFit : "Exact Fit", //MISSING
+
+// Link Dialog
+DlgLnkWindowTitle : "Sambungan",
+DlgLnkInfoTab : "Butiran Sambungan",
+DlgLnkTargetTab : "Sasaran",
+
+DlgLnkType : "Jenis Sambungan",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Pautan dalam muka surat ini",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<lain-lain>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Sila pilih pautan",
+DlgLnkAnchorByName : "dengan menggunakan nama pautan",
+DlgLnkAnchorById : "dengan menggunakan ID elemen",
+DlgLnkNoAnchors : "<Tiada pautan terdapat dalam dokumen ini>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Alamat E-Mail",
+DlgLnkEMailSubject : "Subjek Mesej",
+DlgLnkEMailBody : "Isi Kandungan Mesej",
+DlgLnkUpload : "Muat Naik",
+DlgLnkBtnUpload : "Hantar ke Server",
+
+DlgLnkTarget : "Sasaran",
+DlgLnkTargetFrame : "<bingkai>",
+DlgLnkTargetPopup : "<tetingkap popup>",
+DlgLnkTargetBlank : "Tetingkap Baru (_blank)",
+DlgLnkTargetParent : "Tetingkap Parent (_parent)",
+DlgLnkTargetSelf : "Tetingkap yang Sama (_self)",
+DlgLnkTargetTop : "Tetingkap yang paling atas (_top)",
+DlgLnkTargetFrameName : "Nama Bingkai Sasaran",
+DlgLnkPopWinName : "Nama Tetingkap Popup",
+DlgLnkPopWinFeat : "Ciri Tetingkap Popup",
+DlgLnkPopResize : "Saiz bolehubah",
+DlgLnkPopLocation : "Bar Lokasi",
+DlgLnkPopMenu : "Bar Menu",
+DlgLnkPopScroll : "Bar-bar skrol",
+DlgLnkPopStatus : "Bar Status",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Skrin Penuh (IE)",
+DlgLnkPopDependent : "Bergantungan (Netscape)",
+DlgLnkPopWidth : "Lebar",
+DlgLnkPopHeight : "Tinggi",
+DlgLnkPopLeft : "Posisi Kiri",
+DlgLnkPopTop : "Posisi Atas",
+
+DlnLnkMsgNoUrl : "Sila taip sambungan URL",
+DlnLnkMsgNoEMail : "Sila taip alamat e-mail",
+DlnLnkMsgNoAnchor : "Sila pilih pautan berkenaaan",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Pilihan Warna",
+DlgColorBtnClear : "Nyahwarna",
+DlgColorHighlight : "Terang",
+DlgColorSelected : "Dipilih",
+
+// Smiley Dialog
+DlgSmileyTitle : "Masukkan Smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Sila pilih huruf istimewa",
+
+// Table Dialog
+DlgTableTitle : "Ciri-ciri Jadual",
+DlgTableRows : "Barisan",
+DlgTableColumns : "Jaluran",
+DlgTableBorder : "Saiz Border",
+DlgTableAlign : "Penjajaran",
+DlgTableAlignNotSet : "<Tidak diset>",
+DlgTableAlignLeft : "Kiri",
+DlgTableAlignCenter : "Tengah",
+DlgTableAlignRight : "Kanan",
+DlgTableWidth : "Lebar",
+DlgTableWidthPx : "piksel-piksel",
+DlgTableWidthPc : "peratus",
+DlgTableHeight : "Tinggi",
+DlgTableCellSpace : "Ruangan Antara Sel",
+DlgTableCellPad : "Tambahan Ruang Sel",
+DlgTableCaption : "Keterangan",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Ciri-ciri Sel",
+DlgCellWidth : "Lebar",
+DlgCellWidthPx : "piksel-piksel",
+DlgCellWidthPc : "peratus",
+DlgCellHeight : "Tinggi",
+DlgCellWordWrap : "Mengulung Perkataan",
+DlgCellWordWrapNotSet : "<Tidak diset>",
+DlgCellWordWrapYes : "Ya",
+DlgCellWordWrapNo : "Tidak",
+DlgCellHorAlign : "Jajaran Membujur",
+DlgCellHorAlignNotSet : "<Tidak diset>",
+DlgCellHorAlignLeft : "Kiri",
+DlgCellHorAlignCenter : "Tengah",
+DlgCellHorAlignRight: "Kanan",
+DlgCellVerAlign : "Jajaran Menegak",
+DlgCellVerAlignNotSet : "<Tidak diset>",
+DlgCellVerAlignTop : "Atas",
+DlgCellVerAlignMiddle : "Tengah",
+DlgCellVerAlignBottom : "Bawah",
+DlgCellVerAlignBaseline : "Garis Dasar",
+DlgCellRowSpan : "Penggunaan Baris",
+DlgCellCollSpan : "Penggunaan Lajur",
+DlgCellBackColor : "Warna Latarbelakang",
+DlgCellBorderColor : "Warna Border",
+DlgCellBtnSelect : "Pilih...",
+
+// Find Dialog
+DlgFindTitle : "Carian",
+DlgFindFindBtn : "Cari",
+DlgFindNotFoundMsg : "Text yang dicari tidak dijumpai.",
+
+// Replace Dialog
+DlgReplaceTitle : "Gantian",
+DlgReplaceFindLbl : "Perkataan yang dicari:",
+DlgReplaceReplaceLbl : "Diganti dengan:",
+DlgReplaceCaseChk : "Padanan case huruf",
+DlgReplaceReplaceBtn : "Ganti",
+DlgReplaceReplAllBtn : "Ganti semua",
+DlgReplaceWordChk : "Padana Keseluruhan perkataan",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Keselamatan perisian browser anda tidak membenarkan operasi suntingan text/imej. Sila gunakan papan kekunci (Ctrl+X).",
+PasteErrorCopy : "Keselamatan perisian browser anda tidak membenarkan operasi salinan text/imej. Sila gunakan papan kekunci (Ctrl+C).",
+
+PasteAsText : "Tampal sebagai text biasa",
+PasteFromWord : "Tampal dari perisian \"Word\"",
+
+DlgPasteMsg2 : "Please paste inside the following box using the keyboard (<strong>Ctrl+V</strong>) and hit <strong>OK</strong>.", //MISSING
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignore Font Face definitions", //MISSING
+DlgPasteRemoveStyles : "Remove Styles definitions", //MISSING
+DlgPasteCleanBox : "Clean Up Box", //MISSING
+
+// Color Picker
+ColorAutomatic : "Otomatik",
+ColorMoreColors : "Warna lain-lain...",
+
+// Document Properties
+DocProps : "Ciri-ciri dokumen",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ciri-ciri Pautan",
+DlgAnchorName : "Nama Pautan",
+DlgAnchorErrorName : "Sila taip nama pautan",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Tidak terdapat didalam kamus",
+DlgSpellChangeTo : "Tukarkan kepada",
+DlgSpellBtnIgnore : "Biar",
+DlgSpellBtnIgnoreAll : "Biarkan semua",
+DlgSpellBtnReplace : "Ganti",
+DlgSpellBtnReplaceAll : "Gantikan Semua",
+DlgSpellBtnUndo : "Batalkan",
+DlgSpellNoSuggestions : "- Tiada cadangan -",
+DlgSpellProgress : "Pemeriksaan ejaan sedang diproses...",
+DlgSpellNoMispell : "Pemeriksaan ejaan siap: Tiada salah ejaan",
+DlgSpellNoChanges : "Pemeriksaan ejaan siap: Tiada perkataan diubah",
+DlgSpellOneChange : "Pemeriksaan ejaan siap: Satu perkataan telah diubah",
+DlgSpellManyChanges : "Pemeriksaan ejaan siap: %1 perkataan diubah",
+
+IeSpellDownload : "Pemeriksa ejaan tidak dipasang. Adakah anda mahu muat turun sekarang?",
+
+// Button Dialog
+DlgButtonText : "Teks (Nilai)",
+DlgButtonType : "Jenis",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nama",
+DlgCheckboxValue : "Nilai",
+DlgCheckboxSelected : "Dipilih",
+
+// Form Dialog
+DlgFormName : "Nama",
+DlgFormAction : "Tindakan borang",
+DlgFormMethod : "Cara borang dihantar",
+
+// Select Field Dialog
+DlgSelectName : "Nama",
+DlgSelectValue : "Nilai",
+DlgSelectSize : "Saiz",
+DlgSelectLines : "garisan",
+DlgSelectChkMulti : "Benarkan pilihan pelbagai",
+DlgSelectOpAvail : "Pilihan sediada",
+DlgSelectOpText : "Teks",
+DlgSelectOpValue : "Nilai",
+DlgSelectBtnAdd : "Tambah Pilihan",
+DlgSelectBtnModify : "Ubah Pilihan",
+DlgSelectBtnUp : "Naik ke atas",
+DlgSelectBtnDown : "Turun ke bawah",
+DlgSelectBtnSetValue : "Set sebagai nilai terpilih",
+DlgSelectBtnDelete : "Padam",
+
+// Textarea Dialog
+DlgTextareaName : "Nama",
+DlgTextareaCols : "Lajur",
+DlgTextareaRows : "Baris",
+
+// Text Field Dialog
+DlgTextName : "Nama",
+DlgTextValue : "Nilai",
+DlgTextCharWidth : "Lebar isian",
+DlgTextMaxChars : "Isian Maksimum",
+DlgTextType : "Jenis",
+DlgTextTypeText : "Teks",
+DlgTextTypePass : "Kata Laluan",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nama",
+DlgHiddenValue : "Nilai",
+
+// Bulleted List Dialog
+BulletedListProp : "Ciri-ciri senarai berpeluru",
+NumberedListProp : "Ciri-ciri senarai bernombor",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Jenis",
+DlgLstTypeCircle : "Circle",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Square",
+DlgLstTypeNumbers : "Nombor-nombor (1, 2, 3)",
+DlgLstTypeLCase : "Huruf-huruf kecil (a, b, c)",
+DlgLstTypeUCase : "Huruf-huruf besar (A, B, C)",
+DlgLstTypeSRoman : "Nombor Roman Kecil (i, ii, iii)",
+DlgLstTypeLRoman : "Nombor Roman Besar (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Umum",
+DlgDocBackTab : "Latarbelakang",
+DlgDocColorsTab : "Warna dan margin",
+DlgDocMetaTab : "Data Meta",
+
+DlgDocPageTitle : "Tajuk Muka Surat",
+DlgDocLangDir : "Arah Tulisan",
+DlgDocLangDirLTR : "Kiri ke Kanan (LTR)",
+DlgDocLangDirRTL : "Kanan ke Kiri (RTL)",
+DlgDocLangCode : "Kod Bahasa",
+DlgDocCharSet : "Enkod Set Huruf",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Enkod Set Huruf yang Lain",
+
+DlgDocDocType : "Jenis Kepala Dokumen",
+DlgDocDocTypeOther : "Jenis Kepala Dokumen yang Lain",
+DlgDocIncXHTML : "Masukkan pemula kod XHTML",
+DlgDocBgColor : "Warna Latarbelakang",
+DlgDocBgImage : "URL Gambar Latarbelakang",
+DlgDocBgNoScroll : "Imej Latarbelakang tanpa Skrol",
+DlgDocCText : "Teks",
+DlgDocCLink : "Sambungan",
+DlgDocCVisited : "Sambungan telah Dilawati",
+DlgDocCActive : "Sambungan Aktif",
+DlgDocMargins : "Margin Muka Surat",
+DlgDocMaTop : "Atas",
+DlgDocMaLeft : "Kiri",
+DlgDocMaRight : "Kanan",
+DlgDocMaBottom : "Bawah",
+DlgDocMeIndex : "Kata Kunci Indeks Dokumen (dipisahkan oleh koma)",
+DlgDocMeDescr : "Keterangan Dokumen",
+DlgDocMeAuthor : "Penulis",
+DlgDocMeCopy : "Hakcipta",
+DlgDocPreview : "Prebiu",
+
+// Templates Dialog
+Templates : "Templat",
+DlgTemplatesTitle : "Templat Kandungan",
+DlgTemplatesSelMsg : "Sila pilih templat untuk dibuka oleh editor<br>(kandungan sebenar akan hilang):",
+DlgTemplatesLoading : "Senarai Templat sedang diproses. Sila Tunggu...",
+DlgTemplatesNoTpl : "(Tiada Templat Disimpan)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Tentang",
+DlgAboutBrowserInfoTab : "Maklumat Perisian Browser",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "versi",
+DlgAboutInfo : "Untuk maklumat lanjut sila pergi ke"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/nb.js b/httemplate/elements/fckeditor/editor/lang/nb.js
new file mode 100644
index 000000000..ae9fa649e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/nb.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Norwegian Bokmål language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skjul verktøylinje",
+ToolbarExpand : "Vis verktøylinje",
+
+// Toolbar Items and Context Menu
+Save : "Lagre",
+NewPage : "Ny Side",
+Preview : "Forhåndsvis",
+Cut : "Klipp ut",
+Copy : "Kopier",
+Paste : "Lim inn",
+PasteText : "Lim inn som ren tekst",
+PasteWord : "Lim inn fra Word",
+Print : "Skriv ut",
+SelectAll : "Merk alt",
+RemoveFormat : "Fjern format",
+InsertLinkLbl : "Lenke",
+InsertLink : "Sett inn/Rediger lenke",
+RemoveLink : "Fjern lenke",
+Anchor : "Sett inn/Rediger anker",
+InsertImageLbl : "Bilde",
+InsertImage : "Sett inn/Rediger bilde",
+InsertFlashLbl : "Flash",
+InsertFlash : "Sett inn/Rediger Flash",
+InsertTableLbl : "Tabell",
+InsertTable : "Sett inn/Rediger tabell",
+InsertLineLbl : "Linje",
+InsertLine : "Sett inn horisontal linje",
+InsertSpecialCharLbl: "Spesielt tegn",
+InsertSpecialChar : "Sett inn spesielt tegn",
+InsertSmileyLbl : "Smil",
+InsertSmiley : "Sett inn smil",
+About : "Om FCKeditor",
+Bold : "Fet",
+Italic : "Kursiv",
+Underline : "Understrek",
+StrikeThrough : "Gjennomstrek",
+Subscript : "Senket skrift",
+Superscript : "Hevet skrift",
+LeftJustify : "Venstrejuster",
+CenterJustify : "Midtjuster",
+RightJustify : "Høyrejuster",
+BlockJustify : "Blokkjuster",
+DecreaseIndent : "Senk nivå",
+IncreaseIndent : "Øk nivå",
+Undo : "Angre",
+Redo : "Gjør om",
+NumberedListLbl : "Numrert liste",
+NumberedList : "Sett inn/Fjern numrert liste",
+BulletedListLbl : "Uordnet liste",
+BulletedList : "Sett inn/Fjern uordnet liste",
+ShowTableBorders : "Vis tabellrammer",
+ShowDetails : "Vis detaljer",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Skrift",
+FontSize : "Størrelse",
+TextColor : "Tekstfarge",
+BGColor : "Bakgrunnsfarge",
+Source : "Kilde",
+Find : "Finn",
+Replace : "Erstatt",
+SpellCheck : "Stavekontroll",
+UniversalKeyboard : "Universelt tastatur",
+PageBreakLbl : "Sideskift",
+PageBreak : "Sett inn sideskift",
+
+Form : "Skjema",
+Checkbox : "Sjekkboks",
+RadioButton : "Radioknapp",
+TextField : "Tekstfelt",
+Textarea : "Tekstområde",
+HiddenField : "Skjult felt",
+Button : "Knapp",
+SelectionField : "Dropdown meny",
+ImageButton : "Bildeknapp",
+
+FitWindow : "Maksimer størrelsen på redigeringsverktøyet",
+
+// Context Menu
+EditLink : "Rediger lenke",
+CellCM : "Celle",
+RowCM : "Rader",
+ColumnCM : "Kolonne",
+InsertRow : "Sett inn rad",
+DeleteRows : "Slett rader",
+InsertColumn : "Sett inn kolonne",
+DeleteColumns : "Slett kolonner",
+InsertCell : "Sett inn celle",
+DeleteCells : "Slett celler",
+MergeCells : "Slå sammen celler",
+SplitCell : "Splitt celler",
+TableDelete : "Slett tabell",
+CellProperties : "Celleegenskaper",
+TableProperties : "Tabellegenskaper",
+ImageProperties : "Bildeegenskaper",
+FlashProperties : "Flash Egenskaper",
+
+AnchorProp : "Ankeregenskaper",
+ButtonProp : "Knappegenskaper",
+CheckboxProp : "Sjekkboksegenskaper",
+HiddenFieldProp : "Skjult felt egenskaper",
+RadioButtonProp : "Radioknappegenskaper",
+ImageButtonProp : "Bildeknappegenskaper",
+TextFieldProp : "Tekstfeltegenskaper",
+SelectionFieldProp : "Dropdown menyegenskaper",
+TextareaProp : "Tekstfeltegenskaper",
+FormProp : "Skjemaegenskaper",
+
+FontFormats : "Normal;Formatert;Adresse;Tittel 1;Tittel 2;Tittel 3;Tittel 4;Tittel 5;Tittel 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Lager XHTML. Vennligst vent...",
+Done : "Ferdig",
+PasteWordConfirm : "Teksten du prøver å lime inn ser ut som om den kommer fra word , du bør rense den før du limer inn , vil du gjøre dette?",
+NotCompatiblePaste : "Denne kommandoen er tilgjenglig kun for Internet Explorer version 5.5 eller bedre. Vil du fortsette uten å rense?(Du kan lime inn som ren tekst)",
+UnknownToolbarItem : "Ukjent menyvalg \"%1\"",
+UnknownCommand : "Ukjent kommando \"%1\"",
+NotImplemented : "Kommando ikke ennå implimentert",
+UnknownToolbarSet : "Verktøylinjesett \"%1\" finnes ikke",
+NoActiveX : "Din nettleser's sikkerhetsinstillinger kan begrense noen av funksjonene i redigeringsverktøyet. Du må aktivere \"Kjør ActiveXkontroller og plugins\". Du kan oppleve feil og advarsler om manglende funksjoner",
+BrowseServerBlocked : "Kunne ikke åpne dialogboksen for filarkiv. Pass på at du har slått av popupstoppere.",
+DialogBlocked : "Kunne ikke åpne dialogboksen. Pass på at du har slått av popupstoppere.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Avbryt",
+DlgBtnClose : "Lukk",
+DlgBtnBrowseServer : "Bla igjennom server",
+DlgAdvancedTag : "Avansert",
+DlgOpOther : "<Annet>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Vennligst skriv inn URL'en",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ikke satt>",
+DlgGenId : "Id",
+DlgGenLangDir : "Språkretning",
+DlgGenLangDirLtr : "Venstre til høyre (VTH)",
+DlgGenLangDirRtl : "Høyre til venstre (HTV)",
+DlgGenLangCode : "Språk kode",
+DlgGenAccessKey : "Aksessknapp",
+DlgGenName : "Navn",
+DlgGenTabIndex : "Tab Indeks",
+DlgGenLongDescr : "Utvidet beskrivelse",
+DlgGenClass : "Stilarkklasser",
+DlgGenTitle : "Tittel",
+DlgGenContType : "Type",
+DlgGenLinkCharset : "Lenket språkkart",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Bildeegenskaper",
+DlgImgInfoTab : "Bildeinformasjon",
+DlgImgBtnUpload : "Send det til serveren",
+DlgImgURL : "URL",
+DlgImgUpload : "Last opp",
+DlgImgAlt : "Alternativ tekst",
+DlgImgWidth : "Bredde",
+DlgImgHeight : "Høyde",
+DlgImgLockRatio : "Lås forhold",
+DlgBtnResetSize : "Tilbakestill størrelse",
+DlgImgBorder : "Ramme",
+DlgImgHSpace : "HMarg",
+DlgImgVSpace : "VMarg",
+DlgImgAlign : "Juster",
+DlgImgAlignLeft : "Venstre",
+DlgImgAlignAbsBottom: "Abs bunn",
+DlgImgAlignAbsMiddle: "Abs midten",
+DlgImgAlignBaseline : "Bunnlinje",
+DlgImgAlignBottom : "Bunn",
+DlgImgAlignMiddle : "Midten",
+DlgImgAlignRight : "Høyre",
+DlgImgAlignTextTop : "Tekst topp",
+DlgImgAlignTop : "Topp",
+DlgImgPreview : "Forhåndsvis",
+DlgImgAlertUrl : "Vennligst skriv bildeurlen",
+DlgImgLinkTab : "Lenke",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Egenskaper",
+DlgFlashChkPlay : "Auto Spill",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Slå på Flash meny",
+DlgFlashScale : "Skaler",
+DlgFlashScaleAll : "Vis alt",
+DlgFlashScaleNoBorder : "Ingen ramme",
+DlgFlashScaleFit : "Skaler til å passeExact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Lenke",
+DlgLnkInfoTab : "Lenkeinfo",
+DlgLnkTargetTab : "Mål",
+
+DlgLnkType : "Lenketype",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Lenke til bokmerke i teksten",
+DlgLnkTypeEMail : "E-Post",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<annet>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Velg ett anker",
+DlgLnkAnchorByName : "Anker etter navn",
+DlgLnkAnchorById : "Element etter ID",
+DlgLnkNoAnchors : "<Ingen anker i dokumentet>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Post Addresse",
+DlgLnkEMailSubject : "Meldingsemne",
+DlgLnkEMailBody : "Melding",
+DlgLnkUpload : "Last opp",
+DlgLnkBtnUpload : "Send til server",
+
+DlgLnkTarget : "Mål",
+DlgLnkTargetFrame : "<ramme>",
+DlgLnkTargetPopup : "<popup vindu>",
+DlgLnkTargetBlank : "Nytt vindu (_blank)",
+DlgLnkTargetParent : "Foreldre vindu (_parent)",
+DlgLnkTargetSelf : "Samme vindu (_self)",
+DlgLnkTargetTop : "Hele vindu (_top)",
+DlgLnkTargetFrameName : "Målramme",
+DlgLnkPopWinName : "Popup vindus navn",
+DlgLnkPopWinFeat : "Popup vindus egenskaper",
+DlgLnkPopResize : "Endre størrelse",
+DlgLnkPopLocation : "Adresselinje",
+DlgLnkPopMenu : "Menylinje",
+DlgLnkPopScroll : "Scrollbar",
+DlgLnkPopStatus : "Statuslinje",
+DlgLnkPopToolbar : "Verktøylinje",
+DlgLnkPopFullScrn : "Full skjerm (IE)",
+DlgLnkPopDependent : "Avhenging (Netscape)",
+DlgLnkPopWidth : "Bredde",
+DlgLnkPopHeight : "Høyde",
+DlgLnkPopLeft : "Venstre posisjon",
+DlgLnkPopTop : "Topp posisjon",
+
+DlnLnkMsgNoUrl : "Vennligst skriv inn lenkens url",
+DlnLnkMsgNoEMail : "Vennligst skriv inn e-postadressen",
+DlnLnkMsgNoAnchor : "Vennligst velg ett anker",
+DlnLnkMsgInvPopName : "Popup vinduets navn må begynne med en bokstav, og kan ikke inneholde mellomrom",
+
+// Color Dialog
+DlgColorTitle : "Velg farge",
+DlgColorBtnClear : "Tøm",
+DlgColorHighlight : "Marker",
+DlgColorSelected : "Velg",
+
+// Smiley Dialog
+DlgSmileyTitle : "Sett inn smil",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Velg spesielt tegn",
+
+// Table Dialog
+DlgTableTitle : "Tabellegenskaper",
+DlgTableRows : "Rader",
+DlgTableColumns : "Kolonner",
+DlgTableBorder : "Rammestørrelse",
+DlgTableAlign : "Justering",
+DlgTableAlignNotSet : "<Ikke satt>",
+DlgTableAlignLeft : "Venstre",
+DlgTableAlignCenter : "Midtjuster",
+DlgTableAlignRight : "Høyre",
+DlgTableWidth : "Bredde",
+DlgTableWidthPx : "pixler",
+DlgTableWidthPc : "prosent",
+DlgTableHeight : "Høyde",
+DlgTableCellSpace : "Celle marg",
+DlgTableCellPad : "Celle polstring",
+DlgTableCaption : "Tittel",
+DlgTableSummary : "Sammendrag",
+
+// Table Cell Dialog
+DlgCellTitle : "Celle egenskaper",
+DlgCellWidth : "Bredde",
+DlgCellWidthPx : "pixeler",
+DlgCellWidthPc : "prosent",
+DlgCellHeight : "Høyde",
+DlgCellWordWrap : "Tekstbrytning",
+DlgCellWordWrapNotSet : "<Ikke satt>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nei",
+DlgCellHorAlign : "Horisontal justering",
+DlgCellHorAlignNotSet : "<Ikke satt>",
+DlgCellHorAlignLeft : "Venstre",
+DlgCellHorAlignCenter : "Midtjuster",
+DlgCellHorAlignRight: "Høyre",
+DlgCellVerAlign : "Vertikal justering",
+DlgCellVerAlignNotSet : "<Ikke satt>",
+DlgCellVerAlignTop : "Topp",
+DlgCellVerAlignMiddle : "Midten",
+DlgCellVerAlignBottom : "Bunn",
+DlgCellVerAlignBaseline : "Bunnlinje",
+DlgCellRowSpan : "Radspenn",
+DlgCellCollSpan : "Kolonnespenn",
+DlgCellBackColor : "Bakgrunnsfarge",
+DlgCellBorderColor : "Rammefarge",
+DlgCellBtnSelect : "Velg...",
+
+// Find Dialog
+DlgFindTitle : "Finn",
+DlgFindFindBtn : "Finn",
+DlgFindNotFoundMsg : "Den spesifiserte teksten ble ikke funnet.",
+
+// Replace Dialog
+DlgReplaceTitle : "Erstatt",
+DlgReplaceFindLbl : "Finn hva:",
+DlgReplaceReplaceLbl : "Erstatt med:",
+DlgReplaceCaseChk : "Riktig case",
+DlgReplaceReplaceBtn : "Erstatt",
+DlgReplaceReplAllBtn : "Erstatt alle",
+DlgReplaceWordChk : "Finn hele ordet",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Din nettlesers sikkerhetsinstillinger tillater ikke automatisk klipping av tekst. Vennligst brukt snareveien (Ctrl+X).",
+PasteErrorCopy : "Din nettlesers sikkerhetsinstillinger tillater ikke automatisk kopiering av tekst. Vennligst brukt snareveien (Ctrl+C).",
+
+PasteAsText : "Lim inn som ren tekst",
+PasteFromWord : "Lim inn fra word",
+
+DlgPasteMsg2 : "Vennligst lim inn i den følgende boksen med tastaturet (<STRONG>Ctrl+V</STRONG>) og trykk <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Fjern skrifttyper",
+DlgPasteRemoveStyles : "Fjern stildefinisjoner",
+DlgPasteCleanBox : "Tøm boksen",
+
+// Color Picker
+ColorAutomatic : "Automatisk",
+ColorMoreColors : "Flere farger...",
+
+// Document Properties
+DocProps : "Dokumentegenskaper",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankeregenskaper",
+DlgAnchorName : "Ankernavn",
+DlgAnchorErrorName : "Vennligst skriv inn ankernavnet",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ikke i ordboken",
+DlgSpellChangeTo : "Endre til",
+DlgSpellBtnIgnore : "Ignorer",
+DlgSpellBtnIgnoreAll : "Ignorer alle",
+DlgSpellBtnReplace : "Erstatt",
+DlgSpellBtnReplaceAll : "Erstatt alle",
+DlgSpellBtnUndo : "Angre",
+DlgSpellNoSuggestions : "- ingen forslag -",
+DlgSpellProgress : "Stavekontroll pågår...",
+DlgSpellNoMispell : "Stavekontroll fullført: ingen feilstavinger funnet",
+DlgSpellNoChanges : "Stavekontroll fullført: ingen ord endret",
+DlgSpellOneChange : "Stavekontroll fullført: Ett ord endret",
+DlgSpellManyChanges : "Stavekontroll fullført: %1 ord endret",
+
+IeSpellDownload : "Stavekontroll ikke installert, vil du laste den ned nå?",
+
+// Button Dialog
+DlgButtonText : "Tekst",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Knapp",
+DlgButtonTypeSbm : "Send",
+DlgButtonTypeRst : "Nullstill",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Navn",
+DlgCheckboxValue : "Verdi",
+DlgCheckboxSelected : "Valgt",
+
+// Form Dialog
+DlgFormName : "Navn",
+DlgFormAction : "Handling",
+DlgFormMethod : "Metode",
+
+// Select Field Dialog
+DlgSelectName : "Navn",
+DlgSelectValue : "Verdi",
+DlgSelectSize : "Størrelse",
+DlgSelectLines : "Linjer",
+DlgSelectChkMulti : "Tillat flervalg",
+DlgSelectOpAvail : "Tilgjenglige alternativer",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Verdi",
+DlgSelectBtnAdd : "Legg til",
+DlgSelectBtnModify : "Endre",
+DlgSelectBtnUp : "Opp",
+DlgSelectBtnDown : "Ned",
+DlgSelectBtnSetValue : "Sett som valgt",
+DlgSelectBtnDelete : "Slett",
+
+// Textarea Dialog
+DlgTextareaName : "Navn",
+DlgTextareaCols : "Kolonner",
+DlgTextareaRows : "Rader",
+
+// Text Field Dialog
+DlgTextName : "Navn",
+DlgTextValue : "verdi",
+DlgTextCharWidth : "Tegnbredde",
+DlgTextMaxChars : "Maks antall tegn",
+DlgTextType : "Type",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Passord",
+
+// Hidden Field Dialog
+DlgHiddenName : "Navn",
+DlgHiddenValue : "Verdi",
+
+// Bulleted List Dialog
+BulletedListProp : "Uordnet listeegenskaper",
+NumberedListProp : "Ordnet listeegenskaper",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Sirkel",
+DlgLstTypeDisc : "Hel sirkel",
+DlgLstTypeSquare : "Firkant",
+DlgLstTypeNumbers : "Numre(1, 2, 3)",
+DlgLstTypeLCase : "Små bokstaver (a, b, c)",
+DlgLstTypeUCase : "Store bokstaver(A, B, C)",
+DlgLstTypeSRoman : "Små romerske tall(i, ii, iii)",
+DlgLstTypeLRoman : "Store romerske tall(I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Generalt",
+DlgDocBackTab : "Bakgrunn",
+DlgDocColorsTab : "Farger og marginer",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Sidetittel",
+DlgDocLangDir : "Språkretning",
+DlgDocLangDirLTR : "Venstre til høyre (LTR)",
+DlgDocLangDirRTL : "Høyre til venstre (RTL)",
+DlgDocLangCode : "Språkkode",
+DlgDocCharSet : "Tegnsett",
+DlgDocCharSetCE : "Sentraleuropeisk",
+DlgDocCharSetCT : "Tradisonell kinesisk(Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Gresk",
+DlgDocCharSetJP : "Japansk",
+DlgDocCharSetKR : "Koreansk",
+DlgDocCharSetTR : "Tyrkisk",
+DlgDocCharSetUN : "Unikode (UTF-8)",
+DlgDocCharSetWE : "Vesteuropeisk",
+DlgDocCharSetOther : "Annet tegnsett",
+
+DlgDocDocType : "Dokumenttype header",
+DlgDocDocTypeOther : "Annet dokumenttype header",
+DlgDocIncXHTML : "Inkulder XHTML deklarasjon",
+DlgDocBgColor : "Bakgrunnsfarge",
+DlgDocBgImage : "Bakgrunnsbilde url",
+DlgDocBgNoScroll : "Ikke scroll bakgrunnsbilde",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Besøkt lenke",
+DlgDocCActive : "Aktiv lenke",
+DlgDocMargins : "Sidemargin",
+DlgDocMaTop : "Topp",
+DlgDocMaLeft : "Venstre",
+DlgDocMaRight : "Høyre",
+DlgDocMaBottom : "Bunn",
+DlgDocMeIndex : "Dokument nøkkelord (kommaseparert)",
+DlgDocMeDescr : "Dokumentbeskrivelse",
+DlgDocMeAuthor : "Forfatter",
+DlgDocMeCopy : "Kopirett",
+DlgDocPreview : "Forhåndsvising",
+
+// Templates Dialog
+Templates : "Maler",
+DlgTemplatesTitle : "Innholdsmaler",
+DlgTemplatesSelMsg : "Velg malen du vil åpne<br>(innholdet du har skrevet blir tapt!):",
+DlgTemplatesLoading : "Laster malliste. Vennligst vent...",
+DlgTemplatesNoTpl : "(Ingen maler definert)",
+DlgTemplatesReplace : "Erstatt faktisk innold",
+
+// About Dialog
+DlgAboutAboutTab : "Om",
+DlgAboutBrowserInfoTab : "Nettleserinfo",
+DlgAboutLicenseTab : "Lisens",
+DlgAboutVersion : "versjon",
+DlgAboutInfo : "For further information go to" //MISSING
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/nl.js b/httemplate/elements/fckeditor/editor/lang/nl.js
new file mode 100644
index 000000000..f6b26b411
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/nl.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Dutch language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Menubalk inklappen",
+ToolbarExpand : "Menubalk uitklappen",
+
+// Toolbar Items and Context Menu
+Save : "Opslaan",
+NewPage : "Nieuwe pagina",
+Preview : "Voorbeeld",
+Cut : "Knippen",
+Copy : "Kopiëren",
+Paste : "Plakken",
+PasteText : "Plakken als platte tekst",
+PasteWord : "Plakken als Word-gegevens",
+Print : "Printen",
+SelectAll : "Alles selecteren",
+RemoveFormat : "Opmaak verwijderen",
+InsertLinkLbl : "Link",
+InsertLink : "Link invoegen/wijzigen",
+RemoveLink : "Link verwijderen",
+Anchor : "Interne link",
+InsertImageLbl : "Afbeelding",
+InsertImage : "Afbeelding invoegen/wijzigen",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash invoegen/wijzigen",
+InsertTableLbl : "Tabel",
+InsertTable : "Tabel invoegen/wijzigen",
+InsertLineLbl : "Lijn",
+InsertLine : "Invoegen horizontale lijn",
+InsertSpecialCharLbl: "Speciale tekens",
+InsertSpecialChar : "Speciaal teken invoegen",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Smiley invoegen",
+About : "Over FCKeditor",
+Bold : "Vet",
+Italic : "Schuingedrukt",
+Underline : "Onderstreept",
+StrikeThrough : "Doorhalen",
+Subscript : "Subscript",
+Superscript : "Superscript",
+LeftJustify : "Links uitlijnen",
+CenterJustify : "Centreren",
+RightJustify : "Rechts uitlijnen",
+BlockJustify : "Uitvullen",
+DecreaseIndent : "Inspringen verkleinen",
+IncreaseIndent : "Inspringen vergroten",
+Undo : "Ongedaan maken",
+Redo : "Opnieuw uitvoeren",
+NumberedListLbl : "Genummerde lijst",
+NumberedList : "Genummerde lijst invoegen/verwijderen",
+BulletedListLbl : "Opsomming",
+BulletedList : "Opsomming invoegen/verwijderen",
+ShowTableBorders : "Randen tabel weergeven",
+ShowDetails : "Details weergeven",
+Style : "Stijl",
+FontFormat : "Opmaak",
+Font : "Lettertype",
+FontSize : "Grootte",
+TextColor : "Tekstkleur",
+BGColor : "Achtergrondkleur",
+Source : "Code",
+Find : "Zoeken",
+Replace : "Vervangen",
+SpellCheck : "Spellingscontrole",
+UniversalKeyboard : "Universeel toetsenbord",
+PageBreakLbl : "Pagina-einde",
+PageBreak : "Pagina-einde invoegen",
+
+Form : "Formulier",
+Checkbox : "Aanvinkvakje",
+RadioButton : "Selectievakje",
+TextField : "Tekstveld",
+Textarea : "Tekstvak",
+HiddenField : "Verborgen veld",
+Button : "Knop",
+SelectionField : "Selectieveld",
+ImageButton : "Afbeeldingsknop",
+
+FitWindow : "De editor maximaliseren",
+
+// Context Menu
+EditLink : "Link wijzigen",
+CellCM : "Cel",
+RowCM : "Rij",
+ColumnCM : "Kolom",
+InsertRow : "Rij invoegen",
+DeleteRows : "Rijen verwijderen",
+InsertColumn : "Kolom invoegen",
+DeleteColumns : "Kolommen verwijderen",
+InsertCell : "Cel",
+DeleteCells : "Cellen verwijderen",
+MergeCells : "Cellen samenvoegen",
+SplitCell : "Cellen splitsen",
+TableDelete : "Tabel verwijderen",
+CellProperties : "Eigenschappen cel",
+TableProperties : "Eigenschappen tabel",
+ImageProperties : "Eigenschappen afbeelding",
+FlashProperties : "Eigenschappen Flash",
+
+AnchorProp : "Eigenschappen interne link",
+ButtonProp : "Eigenschappen knop",
+CheckboxProp : "Eigenschappen aanvinkvakje",
+HiddenFieldProp : "Eigenschappen verborgen veld",
+RadioButtonProp : "Eigenschappen selectievakje",
+ImageButtonProp : "Eigenschappen afbeeldingsknop",
+TextFieldProp : "Eigenschappen tekstveld",
+SelectionFieldProp : "Eigenschappen selectieveld",
+TextareaProp : "Eigenschappen tekstvak",
+FormProp : "Eigenschappen formulier",
+
+FontFormats : "Normaal;Met opmaak;Adres;Kop 1;Kop 2;Kop 3;Kop 4;Kop 5;Kop 6;Normaal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Bezig met verwerken XHTML. Even geduld aub...",
+Done : "Klaar",
+PasteWordConfirm : "De tekst die je plakte lijkt gekopieerd uit te zijn Word. Wil je de tekst opschonen voordat deze geplakt wordt?",
+NotCompatiblePaste : "Deze opdracht is beschikbaar voor Internet Explorer versie 5.5 of hoger. Wil je plakken zonder op te schonen?",
+UnknownToolbarItem : "Onbekend item op menubalk \"%1\"",
+UnknownCommand : "Onbekende opdrachtnaam: \"%1\"",
+NotImplemented : "Opdracht niet geïmplementeerd.",
+UnknownToolbarSet : "Menubalk \"%1\" bestaat niet.",
+NoActiveX : "De beveilingsinstellingen van je browser zouden sommige functies van de editor kunnen beperken. De optie \"Activeer ActiveX-elementen en plug-ins\" dient ingeschakeld te worden. Het kan zijn dat er nu functies ontbreken of niet werken.",
+BrowseServerBlocked : "De bestandsbrowser kon niet geopend worden. Zorg ervoor dat pop-up-blokkeerders uit staan.",
+DialogBlocked : "Kan het dialoogvenster niet weergeven. Zorg ervoor dat pop-up-blokkeerders uit staan.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Annuleren",
+DlgBtnClose : "Afsluiten",
+DlgBtnBrowseServer : "Bladeren op server",
+DlgAdvancedTag : "Geavanceerd",
+DlgOpOther : "<Anders>",
+DlgInfoTab : "Informatie",
+DlgAlertUrl : "Geef URL op",
+
+// General Dialogs Labels
+DlgGenNotSet : "<niet ingevuld>",
+DlgGenId : "Kenmerk",
+DlgGenLangDir : "Schrijfrichting",
+DlgGenLangDirLtr : "Links naar rechts (LTR)",
+DlgGenLangDirRtl : "Rechts naar links (RTL)",
+DlgGenLangCode : "Taalcode",
+DlgGenAccessKey : "Toegangstoets",
+DlgGenName : "Naam",
+DlgGenTabIndex : "Tabvolgorde",
+DlgGenLongDescr : "Lange URL-omschrijving",
+DlgGenClass : "Stylesheet-klassen",
+DlgGenTitle : "Aanbevolen titel",
+DlgGenContType : "Aanbevolen content-type",
+DlgGenLinkCharset : "Karakterset van gelinkte bron",
+DlgGenStyle : "Stijl",
+
+// Image Dialog
+DlgImgTitle : "Eigenschappen afbeelding",
+DlgImgInfoTab : "Informatie afbeelding",
+DlgImgBtnUpload : "Naar server verzenden",
+DlgImgURL : "URL",
+DlgImgUpload : "Upload",
+DlgImgAlt : "Alternatieve tekst",
+DlgImgWidth : "Breedte",
+DlgImgHeight : "Hoogte",
+DlgImgLockRatio : "Afmetingen vergrendelen",
+DlgBtnResetSize : "Afmetingen resetten",
+DlgImgBorder : "Rand",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Uitlijning",
+DlgImgAlignLeft : "Links",
+DlgImgAlignAbsBottom: "Absoluut-onder",
+DlgImgAlignAbsMiddle: "Absoluut-midden",
+DlgImgAlignBaseline : "Basislijn",
+DlgImgAlignBottom : "Beneden",
+DlgImgAlignMiddle : "Midden",
+DlgImgAlignRight : "Rechts",
+DlgImgAlignTextTop : "Boven tekst",
+DlgImgAlignTop : "Boven",
+DlgImgPreview : "Voorbeeld",
+DlgImgAlertUrl : "Geef de URL van de afbeelding",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Eigenschappen Flash",
+DlgFlashChkPlay : "Automatisch afspelen",
+DlgFlashChkLoop : "Herhalen",
+DlgFlashChkMenu : "Flashmenu\'s inschakelen",
+DlgFlashScale : "Schaal",
+DlgFlashScaleAll : "Alles tonen",
+DlgFlashScaleNoBorder : "Geen rand",
+DlgFlashScaleFit : "Precies passend",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Linkomschrijving",
+DlgLnkTargetTab : "Doel",
+
+DlgLnkType : "Linktype",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Interne link in pagina",
+DlgLnkTypeEMail : "E-mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<anders>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Kies een interne link",
+DlgLnkAnchorByName : "Op naam interne link",
+DlgLnkAnchorById : "Op kenmerk interne link",
+DlgLnkNoAnchors : "(Geen interne links in document gevonden)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-mailadres",
+DlgLnkEMailSubject : "Onderwerp bericht",
+DlgLnkEMailBody : "Inhoud bericht",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Naar de server versturen",
+
+DlgLnkTarget : "Doel",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<popup window>",
+DlgLnkTargetBlank : "Nieuw venster (_blank)",
+DlgLnkTargetParent : "Origineel venster (_parent)",
+DlgLnkTargetSelf : "Zelfde venster (_self)",
+DlgLnkTargetTop : "Hele venster (_top)",
+DlgLnkTargetFrameName : "Naam doelframe",
+DlgLnkPopWinName : "Naam popupvenster",
+DlgLnkPopWinFeat : "Instellingen popupvenster",
+DlgLnkPopResize : "Grootte wijzigen",
+DlgLnkPopLocation : "Locatiemenu",
+DlgLnkPopMenu : "Menubalk",
+DlgLnkPopScroll : "Schuifbalken",
+DlgLnkPopStatus : "Statusbalk",
+DlgLnkPopToolbar : "Menubalk",
+DlgLnkPopFullScrn : "Volledig scherm (IE)",
+DlgLnkPopDependent : "Afhankelijk (Netscape)",
+DlgLnkPopWidth : "Breedte",
+DlgLnkPopHeight : "Hoogte",
+DlgLnkPopLeft : "Positie links",
+DlgLnkPopTop : "Positie boven",
+
+DlnLnkMsgNoUrl : "Geef de link van de URL",
+DlnLnkMsgNoEMail : "Geef een e-mailadres",
+DlnLnkMsgNoAnchor : "Selecteer een interne link",
+DlnLnkMsgInvPopName : "De naam van de popup moet met een alfa-numerieke waarde beginnen, en mag geen spaties bevatten.",
+
+// Color Dialog
+DlgColorTitle : "Selecteer kleur",
+DlgColorBtnClear : "Opschonen",
+DlgColorHighlight : "Accentueren",
+DlgColorSelected : "Geselecteerd",
+
+// Smiley Dialog
+DlgSmileyTitle : "Smiley invoegen",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Selecteer speciaal teken",
+
+// Table Dialog
+DlgTableTitle : "Eigenschappen tabel",
+DlgTableRows : "Rijen",
+DlgTableColumns : "Kolommen",
+DlgTableBorder : "Breedte rand",
+DlgTableAlign : "Uitlijning",
+DlgTableAlignNotSet : "<Niet ingevoerd>",
+DlgTableAlignLeft : "Links",
+DlgTableAlignCenter : "Centreren",
+DlgTableAlignRight : "Rechts",
+DlgTableWidth : "Breedte",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "procent",
+DlgTableHeight : "Hoogte",
+DlgTableCellSpace : "Afstand tussen cellen",
+DlgTableCellPad : "Afstand vanaf rand cel",
+DlgTableCaption : "Naam",
+DlgTableSummary : "Samenvatting",
+
+// Table Cell Dialog
+DlgCellTitle : "Eigenschappen cel",
+DlgCellWidth : "Breedte",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "procent",
+DlgCellHeight : "Hoogte",
+DlgCellWordWrap : "Afbreken woorden",
+DlgCellWordWrapNotSet : "<Niet ingevoerd>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nee",
+DlgCellHorAlign : "Horizontale uitlijning",
+DlgCellHorAlignNotSet : "<Niet ingevoerd>",
+DlgCellHorAlignLeft : "Links",
+DlgCellHorAlignCenter : "Centreren",
+DlgCellHorAlignRight: "Rechts",
+DlgCellVerAlign : "Verticale uitlijning",
+DlgCellVerAlignNotSet : "<Niet ingevoerd>",
+DlgCellVerAlignTop : "Boven",
+DlgCellVerAlignMiddle : "Midden",
+DlgCellVerAlignBottom : "Beneden",
+DlgCellVerAlignBaseline : "Basislijn",
+DlgCellRowSpan : "Overkoepeling rijen",
+DlgCellCollSpan : "Overkoepeling kolommen",
+DlgCellBackColor : "Achtergrondkleur",
+DlgCellBorderColor : "Randkleur",
+DlgCellBtnSelect : "Selecteren...",
+
+// Find Dialog
+DlgFindTitle : "Zoeken",
+DlgFindFindBtn : "Zoeken",
+DlgFindNotFoundMsg : "De opgegeven tekst is niet gevonden.",
+
+// Replace Dialog
+DlgReplaceTitle : "Vervangen",
+DlgReplaceFindLbl : "Zoeken naar:",
+DlgReplaceReplaceLbl : "Vervangen met:",
+DlgReplaceCaseChk : "Hoofdlettergevoelig",
+DlgReplaceReplaceBtn : "Vervangen",
+DlgReplaceReplAllBtn : "Alles vervangen",
+DlgReplaceWordChk : "Hele woord moet voorkomen",
+
+// Paste Operations / Dialog
+PasteErrorCut : "De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl+X van het toetsenbord.",
+PasteErrorCopy : "De beveiligingsinstelling van de browser verhinderen het automatisch kopiëren. Gebruik de sneltoets Ctrl+C van het toetsenbord.",
+
+PasteAsText : "Plakken als platte tekst",
+PasteFromWord : "Plakken als Word-gegevens",
+
+DlgPasteMsg2 : "Plak de tekst in het volgende vak gebruik makend van je toetstenbord (<STRONG>Ctrl+V</STRONG>) en klik op <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Negeer \"Font Face\"-definities",
+DlgPasteRemoveStyles : "Verwijder \"Style\"-definities",
+DlgPasteCleanBox : "Vak opschonen",
+
+// Color Picker
+ColorAutomatic : "Automatisch",
+ColorMoreColors : "Meer kleuren...",
+
+// Document Properties
+DocProps : "Eigenschappen document",
+
+// Anchor Dialog
+DlgAnchorTitle : "Eigenschappen interne link",
+DlgAnchorName : "Naam interne link",
+DlgAnchorErrorName : "Geef de naam van de interne link op",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Niet in het woordenboek",
+DlgSpellChangeTo : "Wijzig in",
+DlgSpellBtnIgnore : "Negeren",
+DlgSpellBtnIgnoreAll : "Alles negeren",
+DlgSpellBtnReplace : "Vervangen",
+DlgSpellBtnReplaceAll : "Alles vervangen",
+DlgSpellBtnUndo : "Ongedaan maken",
+DlgSpellNoSuggestions : "-Geen suggesties-",
+DlgSpellProgress : "Bezig met spellingscontrole...",
+DlgSpellNoMispell : "Klaar met spellingscontrole: geen fouten gevonden",
+DlgSpellNoChanges : "Klaar met spellingscontrole: geen woorden aangepast",
+DlgSpellOneChange : "Klaar met spellingscontrole: één woord aangepast",
+DlgSpellManyChanges : "Klaar met spellingscontrole: %1 woorden aangepast",
+
+IeSpellDownload : "De spellingscontrole niet geïnstalleerd. Wil je deze nu downloaden?",
+
+// Button Dialog
+DlgButtonText : "Tekst (waarde)",
+DlgButtonType : "Soort",
+DlgButtonTypeBtn : "Knop",
+DlgButtonTypeSbm : "Versturen",
+DlgButtonTypeRst : "Leegmaken",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Naam",
+DlgCheckboxValue : "Waarde",
+DlgCheckboxSelected : "Geselecteerd",
+
+// Form Dialog
+DlgFormName : "Naam",
+DlgFormAction : "Actie",
+DlgFormMethod : "Methode",
+
+// Select Field Dialog
+DlgSelectName : "Naam",
+DlgSelectValue : "Waarde",
+DlgSelectSize : "Grootte",
+DlgSelectLines : "Regels",
+DlgSelectChkMulti : "Gecombineerde selecties toestaan",
+DlgSelectOpAvail : "Beschikbare opties",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Waarde",
+DlgSelectBtnAdd : "Toevoegen",
+DlgSelectBtnModify : "Wijzigen",
+DlgSelectBtnUp : "Omhoog",
+DlgSelectBtnDown : "Omlaag",
+DlgSelectBtnSetValue : "Als geselecteerde waarde instellen",
+DlgSelectBtnDelete : "Verwijderen",
+
+// Textarea Dialog
+DlgTextareaName : "Naam",
+DlgTextareaCols : "Kolommen",
+DlgTextareaRows : "Rijen",
+
+// Text Field Dialog
+DlgTextName : "Naam",
+DlgTextValue : "Waarde",
+DlgTextCharWidth : "Breedte (tekens)",
+DlgTextMaxChars : "Maximum aantal tekens",
+DlgTextType : "Soort",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Wachtwoord",
+
+// Hidden Field Dialog
+DlgHiddenName : "Naam",
+DlgHiddenValue : "Waarde",
+
+// Bulleted List Dialog
+BulletedListProp : "Eigenschappen opsommingslijst",
+NumberedListProp : "Eigenschappen genummerde opsommingslijst",
+DlgLstStart : "Start",
+DlgLstType : "Soort",
+DlgLstTypeCircle : "Cirkel",
+DlgLstTypeDisc : "Schijf",
+DlgLstTypeSquare : "Vierkant",
+DlgLstTypeNumbers : "Nummers (1, 2, 3)",
+DlgLstTypeLCase : "Kleine letters (a, b, c)",
+DlgLstTypeUCase : "Hoofdletters (A, B, C)",
+DlgLstTypeSRoman : "Klein Romeins (i, ii, iii)",
+DlgLstTypeLRoman : "Groot Romeins (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Algemeen",
+DlgDocBackTab : "Achtergrond",
+DlgDocColorsTab : "Kleuring en marges",
+DlgDocMetaTab : "META-data",
+
+DlgDocPageTitle : "Paginatitel",
+DlgDocLangDir : "Schrijfrichting",
+DlgDocLangDirLTR : "Links naar rechts",
+DlgDocLangDirRTL : "Rechts naar links",
+DlgDocLangCode : "Taalcode",
+DlgDocCharSet : "Karakterset-encoding",
+DlgDocCharSetCE : "Centraal Europees",
+DlgDocCharSetCT : "Traditioneel Chinees (Big5)",
+DlgDocCharSetCR : "Cyriliaans",
+DlgDocCharSetGR : "Grieks",
+DlgDocCharSetJP : "Japans",
+DlgDocCharSetKR : "Koreaans",
+DlgDocCharSetTR : "Turks",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "West europees",
+DlgDocCharSetOther : "Andere karakterset-encoding",
+
+DlgDocDocType : "Opschrift documentsoort",
+DlgDocDocTypeOther : "Ander opschrift documentsoort",
+DlgDocIncXHTML : "XHTML-declaraties meenemen",
+DlgDocBgColor : "Achtergrondkleur",
+DlgDocBgImage : "URL achtergrondplaatje",
+DlgDocBgNoScroll : "Vaste achtergrond",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Bezochte link",
+DlgDocCActive : "Active link",
+DlgDocMargins : "Afstandsinstellingen document",
+DlgDocMaTop : "Boven",
+DlgDocMaLeft : "Links",
+DlgDocMaRight : "Rechts",
+DlgDocMaBottom : "Onder",
+DlgDocMeIndex : "Trefwoorden betreffende document (kommagescheiden)",
+DlgDocMeDescr : "Beschrijving document",
+DlgDocMeAuthor : "Auteur",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Voorbeeld",
+
+// Templates Dialog
+Templates : "Sjablonen",
+DlgTemplatesTitle : "Inhoud sjabonen",
+DlgTemplatesSelMsg : "Selecteer het sjabloon dat in de editor geopend moet worden (de actuele inhoud gaat verloren):",
+DlgTemplatesLoading : "Bezig met laden sjabonen. Even geduld alstublieft...",
+DlgTemplatesNoTpl : "(Geen sjablonen gedefinieerd)",
+DlgTemplatesReplace : "Vervang de huidige inhoud",
+
+// About Dialog
+DlgAboutAboutTab : "Over",
+DlgAboutBrowserInfoTab : "Browserinformatie",
+DlgAboutLicenseTab : "Licentie",
+DlgAboutVersion : "Versie",
+DlgAboutInfo : "Voor meer informatie ga naar "
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/no.js b/httemplate/elements/fckeditor/editor/lang/no.js
new file mode 100644
index 000000000..d3b237d57
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/no.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Norwegian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skjul verktøylinje",
+ToolbarExpand : "Vis verktøylinje",
+
+// Toolbar Items and Context Menu
+Save : "Lagre",
+NewPage : "Ny Side",
+Preview : "Forhåndsvis",
+Cut : "Klipp ut",
+Copy : "Kopier",
+Paste : "Lim inn",
+PasteText : "Lim inn som ren tekst",
+PasteWord : "Lim inn fra Word",
+Print : "Skriv ut",
+SelectAll : "Merk alt",
+RemoveFormat : "Fjern format",
+InsertLinkLbl : "Lenke",
+InsertLink : "Sett inn/Rediger lenke",
+RemoveLink : "Fjern lenke",
+Anchor : "Sett inn/Rediger anker",
+InsertImageLbl : "Bilde",
+InsertImage : "Sett inn/Rediger bilde",
+InsertFlashLbl : "Flash",
+InsertFlash : "Sett inn/Rediger Flash",
+InsertTableLbl : "Tabell",
+InsertTable : "Sett inn/Rediger tabell",
+InsertLineLbl : "Linje",
+InsertLine : "Sett inn horisontal linje",
+InsertSpecialCharLbl: "Spesielt tegn",
+InsertSpecialChar : "Sett inn spesielt tegn",
+InsertSmileyLbl : "Smil",
+InsertSmiley : "Sett inn smil",
+About : "Om FCKeditor",
+Bold : "Fet",
+Italic : "Kursiv",
+Underline : "Understrek",
+StrikeThrough : "Gjennomstrek",
+Subscript : "Senket skrift",
+Superscript : "Hevet skrift",
+LeftJustify : "Venstrejuster",
+CenterJustify : "Midtjuster",
+RightJustify : "Høyrejuster",
+BlockJustify : "Blokkjuster",
+DecreaseIndent : "Senk nivå",
+IncreaseIndent : "Øk nivå",
+Undo : "Angre",
+Redo : "Gjør om",
+NumberedListLbl : "Numrert liste",
+NumberedList : "Sett inn/Fjern numrert liste",
+BulletedListLbl : "Uordnet liste",
+BulletedList : "Sett inn/Fjern uordnet liste",
+ShowTableBorders : "Vis tabellrammer",
+ShowDetails : "Vis detaljer",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Skrift",
+FontSize : "Størrelse",
+TextColor : "Tekstfarge",
+BGColor : "Bakgrunnsfarge",
+Source : "Kilde",
+Find : "Finn",
+Replace : "Erstatt",
+SpellCheck : "Stavekontroll",
+UniversalKeyboard : "Universelt tastatur",
+PageBreakLbl : "Sideskift",
+PageBreak : "Sett inn sideskift",
+
+Form : "Skjema",
+Checkbox : "Sjekkboks",
+RadioButton : "Radioknapp",
+TextField : "Tekstfelt",
+Textarea : "Tekstområde",
+HiddenField : "Skjult felt",
+Button : "Knapp",
+SelectionField : "Dropdown meny",
+ImageButton : "Bildeknapp",
+
+FitWindow : "Maksimer størrelsen på redigeringsverktøyet",
+
+// Context Menu
+EditLink : "Rediger lenke",
+CellCM : "Celle",
+RowCM : "Rader",
+ColumnCM : "Kolonne",
+InsertRow : "Sett inn rad",
+DeleteRows : "Slett rader",
+InsertColumn : "Sett inn kolonne",
+DeleteColumns : "Slett kolonner",
+InsertCell : "Sett inn celle",
+DeleteCells : "Slett celler",
+MergeCells : "Slå sammen celler",
+SplitCell : "Splitt celler",
+TableDelete : "Slett tabell",
+CellProperties : "Celleegenskaper",
+TableProperties : "Tabellegenskaper",
+ImageProperties : "Bildeegenskaper",
+FlashProperties : "Flash Egenskaper",
+
+AnchorProp : "Ankeregenskaper",
+ButtonProp : "Knappegenskaper",
+CheckboxProp : "Sjekkboksegenskaper",
+HiddenFieldProp : "Skjult felt egenskaper",
+RadioButtonProp : "Radioknappegenskaper",
+ImageButtonProp : "Bildeknappegenskaper",
+TextFieldProp : "Tekstfeltegenskaper",
+SelectionFieldProp : "Dropdown menyegenskaper",
+TextareaProp : "Tekstfeltegenskaper",
+FormProp : "Skjemaegenskaper",
+
+FontFormats : "Normal;Formatert;Adresse;Tittel 1;Tittel 2;Tittel 3;Tittel 4;Tittel 5;Tittel 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Lager XHTML. Vennligst vent...",
+Done : "Ferdig",
+PasteWordConfirm : "Teksten du prøver å lime inn ser ut som om den kommer fra word , du bør rense den før du limer inn , vil du gjøre dette?",
+NotCompatiblePaste : "Denne kommandoen er tilgjenglig kun for Internet Explorer version 5.5 eller bedre. Vil du fortsette uten å rense?(Du kan lime inn som ren tekst)",
+UnknownToolbarItem : "Ukjent menyvalg \"%1\"",
+UnknownCommand : "Ukjent kommando \"%1\"",
+NotImplemented : "Kommando ikke ennå implimentert",
+UnknownToolbarSet : "Verktøylinjesett \"%1\" finnes ikke",
+NoActiveX : "Din nettleser's sikkerhetsinstillinger kan begrense noen av funksjonene i redigeringsverktøyet. Du må aktivere \"Kjør ActiveXkontroller og plugins\". Du kan oppleve feil og advarsler om manglende funksjoner",
+BrowseServerBlocked : "Kunne ikke åpne dialogboksen for filarkiv. Pass på at du har slått av popupstoppere.",
+DialogBlocked : "Kunne ikke åpne dialogboksen. Pass på at du har slått av popupstoppere.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Avbryt",
+DlgBtnClose : "Lukk",
+DlgBtnBrowseServer : "Bla igjennom server",
+DlgAdvancedTag : "Avansert",
+DlgOpOther : "<Annet>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Vennligst skriv inn URL'en",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ikke satt>",
+DlgGenId : "Id",
+DlgGenLangDir : "Språkretning",
+DlgGenLangDirLtr : "Venstre til høyre (VTH)",
+DlgGenLangDirRtl : "Høyre til venstre (HTV)",
+DlgGenLangCode : "Språk kode",
+DlgGenAccessKey : "Aksessknapp",
+DlgGenName : "Navn",
+DlgGenTabIndex : "Tab Indeks",
+DlgGenLongDescr : "Utvidet beskrivelse",
+DlgGenClass : "Stilarkklasser",
+DlgGenTitle : "Tittel",
+DlgGenContType : "Type",
+DlgGenLinkCharset : "Lenket språkkart",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Bildeegenskaper",
+DlgImgInfoTab : "Bildeinformasjon",
+DlgImgBtnUpload : "Send det til serveren",
+DlgImgURL : "URL",
+DlgImgUpload : "Last opp",
+DlgImgAlt : "Alternativ tekst",
+DlgImgWidth : "Bredde",
+DlgImgHeight : "Høyde",
+DlgImgLockRatio : "Lås forhold",
+DlgBtnResetSize : "Tilbakestill størrelse",
+DlgImgBorder : "Ramme",
+DlgImgHSpace : "HMarg",
+DlgImgVSpace : "VMarg",
+DlgImgAlign : "Juster",
+DlgImgAlignLeft : "Venstre",
+DlgImgAlignAbsBottom: "Abs bunn",
+DlgImgAlignAbsMiddle: "Abs midten",
+DlgImgAlignBaseline : "Bunnlinje",
+DlgImgAlignBottom : "Bunn",
+DlgImgAlignMiddle : "Midten",
+DlgImgAlignRight : "Høyre",
+DlgImgAlignTextTop : "Tekst topp",
+DlgImgAlignTop : "Topp",
+DlgImgPreview : "Forhåndsvis",
+DlgImgAlertUrl : "Vennligst skriv bildeurlen",
+DlgImgLinkTab : "Lenke",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Egenskaper",
+DlgFlashChkPlay : "Auto Spill",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Slå på Flash meny",
+DlgFlashScale : "Skaler",
+DlgFlashScaleAll : "Vis alt",
+DlgFlashScaleNoBorder : "Ingen ramme",
+DlgFlashScaleFit : "Skaler til å passeExact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "Lenke",
+DlgLnkInfoTab : "Lenkeinfo",
+DlgLnkTargetTab : "Mål",
+
+DlgLnkType : "Lenketype",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Lenke til bokmerke i teksten",
+DlgLnkTypeEMail : "E-Post",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<annet>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Velg ett anker",
+DlgLnkAnchorByName : "Anker etter navn",
+DlgLnkAnchorById : "Element etter ID",
+DlgLnkNoAnchors : "<Ingen anker i dokumentet>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Post Addresse",
+DlgLnkEMailSubject : "Meldingsemne",
+DlgLnkEMailBody : "Melding",
+DlgLnkUpload : "Last opp",
+DlgLnkBtnUpload : "Send til server",
+
+DlgLnkTarget : "Mål",
+DlgLnkTargetFrame : "<ramme>",
+DlgLnkTargetPopup : "<popup vindu>",
+DlgLnkTargetBlank : "Nytt vindu (_blank)",
+DlgLnkTargetParent : "Foreldre vindu (_parent)",
+DlgLnkTargetSelf : "Samme vindu (_self)",
+DlgLnkTargetTop : "Hele vindu (_top)",
+DlgLnkTargetFrameName : "Målramme",
+DlgLnkPopWinName : "Popup vindus navn",
+DlgLnkPopWinFeat : "Popup vindus egenskaper",
+DlgLnkPopResize : "Endre størrelse",
+DlgLnkPopLocation : "Adresselinje",
+DlgLnkPopMenu : "Menylinje",
+DlgLnkPopScroll : "Scrollbar",
+DlgLnkPopStatus : "Statuslinje",
+DlgLnkPopToolbar : "Verktøylinje",
+DlgLnkPopFullScrn : "Full skjerm (IE)",
+DlgLnkPopDependent : "Avhenging (Netscape)",
+DlgLnkPopWidth : "Bredde",
+DlgLnkPopHeight : "Høyde",
+DlgLnkPopLeft : "Venstre posisjon",
+DlgLnkPopTop : "Topp posisjon",
+
+DlnLnkMsgNoUrl : "Vennligst skriv inn lenkens url",
+DlnLnkMsgNoEMail : "Vennligst skriv inn e-postadressen",
+DlnLnkMsgNoAnchor : "Vennligst velg ett anker",
+DlnLnkMsgInvPopName : "Popup vinduets navn må begynne med en bokstav, og kan ikke inneholde mellomrom",
+
+// Color Dialog
+DlgColorTitle : "Velg farge",
+DlgColorBtnClear : "Tøm",
+DlgColorHighlight : "Marker",
+DlgColorSelected : "Velg",
+
+// Smiley Dialog
+DlgSmileyTitle : "Sett inn smil",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Velg spesielt tegn",
+
+// Table Dialog
+DlgTableTitle : "Tabellegenskaper",
+DlgTableRows : "Rader",
+DlgTableColumns : "Kolonner",
+DlgTableBorder : "Rammestørrelse",
+DlgTableAlign : "Justering",
+DlgTableAlignNotSet : "<Ikke satt>",
+DlgTableAlignLeft : "Venstre",
+DlgTableAlignCenter : "Midtjuster",
+DlgTableAlignRight : "Høyre",
+DlgTableWidth : "Bredde",
+DlgTableWidthPx : "pixler",
+DlgTableWidthPc : "prosent",
+DlgTableHeight : "Høyde",
+DlgTableCellSpace : "Celle marg",
+DlgTableCellPad : "Celle polstring",
+DlgTableCaption : "Tittel",
+DlgTableSummary : "Sammendrag",
+
+// Table Cell Dialog
+DlgCellTitle : "Celle egenskaper",
+DlgCellWidth : "Bredde",
+DlgCellWidthPx : "pixeler",
+DlgCellWidthPc : "prosent",
+DlgCellHeight : "Høyde",
+DlgCellWordWrap : "Tekstbrytning",
+DlgCellWordWrapNotSet : "<Ikke satt>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nei",
+DlgCellHorAlign : "Horisontal justering",
+DlgCellHorAlignNotSet : "<Ikke satt>",
+DlgCellHorAlignLeft : "Venstre",
+DlgCellHorAlignCenter : "Midtjuster",
+DlgCellHorAlignRight: "Høyre",
+DlgCellVerAlign : "Vertikal justering",
+DlgCellVerAlignNotSet : "<Ikke satt>",
+DlgCellVerAlignTop : "Topp",
+DlgCellVerAlignMiddle : "Midten",
+DlgCellVerAlignBottom : "Bunn",
+DlgCellVerAlignBaseline : "Bunnlinje",
+DlgCellRowSpan : "Radspenn",
+DlgCellCollSpan : "Kolonnespenn",
+DlgCellBackColor : "Bakgrunnsfarge",
+DlgCellBorderColor : "Rammefarge",
+DlgCellBtnSelect : "Velg...",
+
+// Find Dialog
+DlgFindTitle : "Finn",
+DlgFindFindBtn : "Finn",
+DlgFindNotFoundMsg : "Den spesifiserte teksten ble ikke funnet.",
+
+// Replace Dialog
+DlgReplaceTitle : "Erstatt",
+DlgReplaceFindLbl : "Finn hva:",
+DlgReplaceReplaceLbl : "Erstatt med:",
+DlgReplaceCaseChk : "Riktig case",
+DlgReplaceReplaceBtn : "Erstatt",
+DlgReplaceReplAllBtn : "Erstatt alle",
+DlgReplaceWordChk : "Finn hele ordet",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Din nettlesers sikkerhetsinstillinger tillater ikke automatisk klipping av tekst. Vennligst brukt snareveien (Ctrl+X).",
+PasteErrorCopy : "Din nettlesers sikkerhetsinstillinger tillater ikke automatisk kopiering av tekst. Vennligst brukt snareveien (Ctrl+C).",
+
+PasteAsText : "Lim inn som ren tekst",
+PasteFromWord : "Lim inn fra word",
+
+DlgPasteMsg2 : "Vennligst lim inn i den følgende boksen med tastaturet (<STRONG>Ctrl+V</STRONG>) og trykk <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Fjern skrifttyper",
+DlgPasteRemoveStyles : "Fjern stildefinisjoner",
+DlgPasteCleanBox : "Tøm boksen",
+
+// Color Picker
+ColorAutomatic : "Automatisk",
+ColorMoreColors : "Flere farger...",
+
+// Document Properties
+DocProps : "Dokumentegenskaper",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankeregenskaper",
+DlgAnchorName : "Ankernavn",
+DlgAnchorErrorName : "Vennligst skriv inn ankernavnet",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ikke i ordboken",
+DlgSpellChangeTo : "Endre til",
+DlgSpellBtnIgnore : "Ignorer",
+DlgSpellBtnIgnoreAll : "Ignorer alle",
+DlgSpellBtnReplace : "Erstatt",
+DlgSpellBtnReplaceAll : "Erstatt alle",
+DlgSpellBtnUndo : "Angre",
+DlgSpellNoSuggestions : "- ingen forslag -",
+DlgSpellProgress : "Stavekontroll pågår...",
+DlgSpellNoMispell : "Stavekontroll fullført: ingen feilstavinger funnet",
+DlgSpellNoChanges : "Stavekontroll fullført: ingen ord endret",
+DlgSpellOneChange : "Stavekontroll fullført: Ett ord endret",
+DlgSpellManyChanges : "Stavekontroll fullført: %1 ord endret",
+
+IeSpellDownload : "Stavekontroll ikke installert, vil du laste den ned nå?",
+
+// Button Dialog
+DlgButtonText : "Tekst",
+DlgButtonType : "Type",
+DlgButtonTypeBtn : "Knapp",
+DlgButtonTypeSbm : "Send",
+DlgButtonTypeRst : "Nullstill",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Navn",
+DlgCheckboxValue : "Verdi",
+DlgCheckboxSelected : "Valgt",
+
+// Form Dialog
+DlgFormName : "Navn",
+DlgFormAction : "Handling",
+DlgFormMethod : "Metode",
+
+// Select Field Dialog
+DlgSelectName : "Navn",
+DlgSelectValue : "Verdi",
+DlgSelectSize : "Størrelse",
+DlgSelectLines : "Linjer",
+DlgSelectChkMulti : "Tillat flervalg",
+DlgSelectOpAvail : "Tilgjenglige alternativer",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Verdi",
+DlgSelectBtnAdd : "Legg til",
+DlgSelectBtnModify : "Endre",
+DlgSelectBtnUp : "Opp",
+DlgSelectBtnDown : "Ned",
+DlgSelectBtnSetValue : "Sett som valgt",
+DlgSelectBtnDelete : "Slett",
+
+// Textarea Dialog
+DlgTextareaName : "Navn",
+DlgTextareaCols : "Kolonner",
+DlgTextareaRows : "Rader",
+
+// Text Field Dialog
+DlgTextName : "Navn",
+DlgTextValue : "verdi",
+DlgTextCharWidth : "Tegnbredde",
+DlgTextMaxChars : "Maks antall tegn",
+DlgTextType : "Type",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Passord",
+
+// Hidden Field Dialog
+DlgHiddenName : "Navn",
+DlgHiddenValue : "Verdi",
+
+// Bulleted List Dialog
+BulletedListProp : "Uordnet listeegenskaper",
+NumberedListProp : "Ordnet listeegenskaper",
+DlgLstStart : "Start",
+DlgLstType : "Type",
+DlgLstTypeCircle : "Sirkel",
+DlgLstTypeDisc : "Hel sirkel",
+DlgLstTypeSquare : "Firkant",
+DlgLstTypeNumbers : "Numre(1, 2, 3)",
+DlgLstTypeLCase : "Små bokstaver (a, b, c)",
+DlgLstTypeUCase : "Store bokstaver(A, B, C)",
+DlgLstTypeSRoman : "Små romerske tall(i, ii, iii)",
+DlgLstTypeLRoman : "Store romerske tall(I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Generalt",
+DlgDocBackTab : "Bakgrunn",
+DlgDocColorsTab : "Farger og marginer",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Sidetittel",
+DlgDocLangDir : "Språkretning",
+DlgDocLangDirLTR : "Venstre til høyre (LTR)",
+DlgDocLangDirRTL : "Høyre til venstre (RTL)",
+DlgDocLangCode : "Språkkode",
+DlgDocCharSet : "Tegnsett",
+DlgDocCharSetCE : "Sentraleuropeisk",
+DlgDocCharSetCT : "Tradisonell kinesisk(Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Gresk",
+DlgDocCharSetJP : "Japansk",
+DlgDocCharSetKR : "Koreansk",
+DlgDocCharSetTR : "Tyrkisk",
+DlgDocCharSetUN : "Unikode (UTF-8)",
+DlgDocCharSetWE : "Vesteuropeisk",
+DlgDocCharSetOther : "Annet tegnsett",
+
+DlgDocDocType : "Dokumenttype header",
+DlgDocDocTypeOther : "Annet dokumenttype header",
+DlgDocIncXHTML : "Inkulder XHTML deklarasjon",
+DlgDocBgColor : "Bakgrunnsfarge",
+DlgDocBgImage : "Bakgrunnsbilde url",
+DlgDocBgNoScroll : "Ikke scroll bakgrunnsbilde",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Besøkt lenke",
+DlgDocCActive : "Aktiv lenke",
+DlgDocMargins : "Sidemargin",
+DlgDocMaTop : "Topp",
+DlgDocMaLeft : "Venstre",
+DlgDocMaRight : "Høyre",
+DlgDocMaBottom : "Bunn",
+DlgDocMeIndex : "Dokument nøkkelord (kommaseparert)",
+DlgDocMeDescr : "Dokumentbeskrivelse",
+DlgDocMeAuthor : "Forfatter",
+DlgDocMeCopy : "Kopirett",
+DlgDocPreview : "Forhåndsvising",
+
+// Templates Dialog
+Templates : "Maler",
+DlgTemplatesTitle : "Innholdsmaler",
+DlgTemplatesSelMsg : "Velg malen du vil åpne<br>(innholdet du har skrevet blir tapt!):",
+DlgTemplatesLoading : "Laster malliste. Vennligst vent...",
+DlgTemplatesNoTpl : "(Ingen maler definert)",
+DlgTemplatesReplace : "Erstatt faktisk innold",
+
+// About Dialog
+DlgAboutAboutTab : "Om",
+DlgAboutBrowserInfoTab : "Nettleserinfo",
+DlgAboutLicenseTab : "Lisens",
+DlgAboutVersion : "versjon",
+DlgAboutInfo : "For further information go to" //MISSING
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/pl.js b/httemplate/elements/fckeditor/editor/lang/pl.js
new file mode 100644
index 000000000..f01994dcd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/pl.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Polish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Zwiń pasek narzędzi",
+ToolbarExpand : "Rozwiń pasek narzędzi",
+
+// Toolbar Items and Context Menu
+Save : "Zapisz",
+NewPage : "Nowa strona",
+Preview : "Podgląd",
+Cut : "Wytnij",
+Copy : "Kopiuj",
+Paste : "Wklej",
+PasteText : "Wklej jako czysty tekst",
+PasteWord : "Wklej z Worda",
+Print : "Drukuj",
+SelectAll : "Zaznacz wszystko",
+RemoveFormat : "Usuń formatowanie",
+InsertLinkLbl : "Hiperłącze",
+InsertLink : "Wstaw/edytuj hiperłącze",
+RemoveLink : "Usuń hiperłącze",
+Anchor : "Wstaw/edytuj kotwicę",
+InsertImageLbl : "Obrazek",
+InsertImage : "Wstaw/edytuj obrazek",
+InsertFlashLbl : "Flash",
+InsertFlash : "Dodaj/Edytuj element Flash",
+InsertTableLbl : "Tabela",
+InsertTable : "Wstaw/edytuj tabelę",
+InsertLineLbl : "Linia pozioma",
+InsertLine : "Wstaw poziomą linię",
+InsertSpecialCharLbl: "Znak specjalny",
+InsertSpecialChar : "Wstaw znak specjalny",
+InsertSmileyLbl : "Emotikona",
+InsertSmiley : "Wstaw emotikonę",
+About : "O programie FCKeditor",
+Bold : "Pogrubienie",
+Italic : "Kursywa",
+Underline : "Podkreślenie",
+StrikeThrough : "Przekreślenie",
+Subscript : "Indeks dolny",
+Superscript : "Indeks górny",
+LeftJustify : "Wyrównaj do lewej",
+CenterJustify : "Wyrównaj do środka",
+RightJustify : "Wyrównaj do prawej",
+BlockJustify : "Wyrównaj do lewej i prawej",
+DecreaseIndent : "Zmniejsz wcięcie",
+IncreaseIndent : "Zwiększ wcięcie",
+Undo : "Cofnij",
+Redo : "Ponów",
+NumberedListLbl : "Lista numerowana",
+NumberedList : "Wstaw/usuń numerowanie listy",
+BulletedListLbl : "Lista wypunktowana",
+BulletedList : "Wstaw/usuń wypunktowanie listy",
+ShowTableBorders : "Pokazuj ramkę tabeli",
+ShowDetails : "Pokaż szczegóły",
+Style : "Styl",
+FontFormat : "Format",
+Font : "Czcionka",
+FontSize : "Rozmiar",
+TextColor : "Kolor tekstu",
+BGColor : "Kolor tła",
+Source : "Źródło dokumentu",
+Find : "Znajdź",
+Replace : "Zamień",
+SpellCheck : "Sprawdź pisownię",
+UniversalKeyboard : "Klawiatura Uniwersalna",
+PageBreakLbl : "Odstęp",
+PageBreak : "Wstaw odstęp",
+
+Form : "Formularz",
+Checkbox : "Checkbox",
+RadioButton : "Pole wyboru",
+TextField : "Pole tekstowe",
+Textarea : "Obszar tekstowy",
+HiddenField : "Pole ukryte",
+Button : "Przycisk",
+SelectionField : "Lista wyboru",
+ImageButton : "Przycisk obrazek",
+
+FitWindow : "Maksymalizuj rozmiar edytora",
+
+// Context Menu
+EditLink : "Edytuj hiperłącze",
+CellCM : "Komórka",
+RowCM : "Wiersz",
+ColumnCM : "Kolumna",
+InsertRow : "Wstaw wiersz",
+DeleteRows : "Usuń wiersze",
+InsertColumn : "Wstaw kolumnę",
+DeleteColumns : "Usuń kolumny",
+InsertCell : "Wstaw komórkę",
+DeleteCells : "Usuń komórki",
+MergeCells : "Połącz komórki",
+SplitCell : "Podziel komórkę",
+TableDelete : "Usuń tabelę",
+CellProperties : "Właściwości komórki",
+TableProperties : "Właściwości tabeli",
+ImageProperties : "Właściwości obrazka",
+FlashProperties : "Właściwości elementu Flash",
+
+AnchorProp : "Właściwości kotwicy",
+ButtonProp : "Właściwości przycisku",
+CheckboxProp : "Checkbox - właściwości",
+HiddenFieldProp : "Właściwości pola ukrytego",
+RadioButtonProp : "Właściwości pola wyboru",
+ImageButtonProp : "Właściwości przycisku obrazka",
+TextFieldProp : "Właściwości pola tekstowego",
+SelectionFieldProp : "Właściwości listy wyboru",
+TextareaProp : "Właściwości obszaru tekstowego",
+FormProp : "Właściwości formularza",
+
+FontFormats : "Normalny;Tekst sformatowany;Adres;Nagłówek 1;Nagłówek 2;Nagłówek 3;Nagłówek 4;Nagłówek 5;Nagłówek 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Przetwarzanie XHTML. Proszę czekać...",
+Done : "Gotowe",
+PasteWordConfirm : "Tekst, który chcesz wkleić, prawdopodobnie pochodzi z programu Word. Czy chcesz go wyczyścic przed wklejeniem?",
+NotCompatiblePaste : "Ta funkcja jest dostępna w programie Internet Explorer w wersji 5.5 lub wyższej. Czy chcesz wkleić tekst bez czyszczenia?",
+UnknownToolbarItem : "Nieznany element paska narzędzi \"%1\"",
+UnknownCommand : "Nieznana komenda \"%1\"",
+NotImplemented : "Komenda niezaimplementowana",
+UnknownToolbarSet : "Pasek narzędzi \"%1\" nie istnieje",
+NoActiveX : "Ustawienia zabezpieczeń twojej przeglądarki mogą ograniczyć niektóre funkcje edytora. Musisz włączyć opcję \"Uruchamianie formantów Activex i dodatków plugin\". W przeciwnym wypadku mogą pojawiać się błędy.",
+BrowseServerBlocked : "Okno menadżera plików nie może zostać otwarte. Upewnij się, że wszystkie blokady popup są wyłączone.",
+DialogBlocked : "Nie można otworzyć okna dialogowego. Upewnij się, że wszystkie blokady popup są wyłączone.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Anuluj",
+DlgBtnClose : "Zamknij",
+DlgBtnBrowseServer : "Przeglądaj",
+DlgAdvancedTag : "Zaawansowane",
+DlgOpOther : "<Inny>",
+DlgInfoTab : "Informacje",
+DlgAlertUrl : "Proszę podać URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nieustawione>",
+DlgGenId : "Id",
+DlgGenLangDir : "Kierunek tekstu",
+DlgGenLangDirLtr : "Od lewej do prawej (LTR)",
+DlgGenLangDirRtl : "Od prawej do lewej (RTL)",
+DlgGenLangCode : "Kod języka",
+DlgGenAccessKey : "Klawisz dostępu",
+DlgGenName : "Nazwa",
+DlgGenTabIndex : "Indeks tabeli",
+DlgGenLongDescr : "Long Description URL",
+DlgGenClass : "Stylesheet Classes",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Styl",
+
+// Image Dialog
+DlgImgTitle : "Właściwości obrazka",
+DlgImgInfoTab : "Informacje o obrazku",
+DlgImgBtnUpload : "Syślij",
+DlgImgURL : "Adres URL",
+DlgImgUpload : "Wyślij",
+DlgImgAlt : "Tekst zastępczy",
+DlgImgWidth : "Szerokość",
+DlgImgHeight : "Wysokość",
+DlgImgLockRatio : "Zablokuj proporcje",
+DlgBtnResetSize : "Przywróć rozmiar",
+DlgImgBorder : "Ramka",
+DlgImgHSpace : "Odstęp poziomy",
+DlgImgVSpace : "Odstęp pionowy",
+DlgImgAlign : "Wyrównaj",
+DlgImgAlignLeft : "Do lewej",
+DlgImgAlignAbsBottom: "Do dołu",
+DlgImgAlignAbsMiddle: "Do środka w pionie",
+DlgImgAlignBaseline : "Do linii bazowej",
+DlgImgAlignBottom : "Do dołu",
+DlgImgAlignMiddle : "Do środka",
+DlgImgAlignRight : "Do prawej",
+DlgImgAlignTextTop : "Do góry tekstu",
+DlgImgAlignTop : "Do góry",
+DlgImgPreview : "Podgląd",
+DlgImgAlertUrl : "Podaj adres obrazka.",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Właściwości elementu Flash",
+DlgFlashChkPlay : "Auto Odtwarzanie",
+DlgFlashChkLoop : "Pętla",
+DlgFlashChkMenu : "Włącz menu",
+DlgFlashScale : "Skaluj",
+DlgFlashScaleAll : "Pokaż wszystko",
+DlgFlashScaleNoBorder : "Bez Ramki",
+DlgFlashScaleFit : "Dokładne dopasowanie",
+
+// Link Dialog
+DlgLnkWindowTitle : "Hiperłącze",
+DlgLnkInfoTab : "Informacje ",
+DlgLnkTargetTab : "Cel",
+
+DlgLnkType : "Typ hiperłącza",
+DlgLnkTypeURL : "Adres URL",
+DlgLnkTypeAnchor : "Odnośnik wewnątrz strony",
+DlgLnkTypeEMail : "Adres e-mail",
+DlgLnkProto : "Protokół",
+DlgLnkProtoOther : "<inny>",
+DlgLnkURL : "Adres URL",
+DlgLnkAnchorSel : "Wybierz etykietę",
+DlgLnkAnchorByName : "Wg etykiety",
+DlgLnkAnchorById : "Wg identyfikatora elementu",
+DlgLnkNoAnchors : "<W dokumencie nie zdefiniowano żadnych etykiet>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Adres e-mail",
+DlgLnkEMailSubject : "Temat",
+DlgLnkEMailBody : "Treść",
+DlgLnkUpload : "Upload",
+DlgLnkBtnUpload : "Wyślij",
+
+DlgLnkTarget : "Cel",
+DlgLnkTargetFrame : "<ramka>",
+DlgLnkTargetPopup : "<wyskakujące okno>",
+DlgLnkTargetBlank : "Nowe okno (_blank)",
+DlgLnkTargetParent : "Okno nadrzędne (_parent)",
+DlgLnkTargetSelf : "To samo okno (_self)",
+DlgLnkTargetTop : "Okno najwyższe w hierarchii (_top)",
+DlgLnkTargetFrameName : "Nazwa Ramki Docelowej",
+DlgLnkPopWinName : "Nazwa wyskakującego okna",
+DlgLnkPopWinFeat : "Właściwości wyskakującego okna",
+DlgLnkPopResize : "Możliwa zmiana rozmiaru",
+DlgLnkPopLocation : "Pasek adresu",
+DlgLnkPopMenu : "Pasek menu",
+DlgLnkPopScroll : "Paski przewijania",
+DlgLnkPopStatus : "Pasek statusu",
+DlgLnkPopToolbar : "Pasek narzędzi",
+DlgLnkPopFullScrn : "Pełny ekran (IE)",
+DlgLnkPopDependent : "Okno zależne (Netscape)",
+DlgLnkPopWidth : "Szerokość",
+DlgLnkPopHeight : "Wysokość",
+DlgLnkPopLeft : "Pozycja w poziomie",
+DlgLnkPopTop : "Pozycja w pionie",
+
+DlnLnkMsgNoUrl : "Podaj adres URL",
+DlnLnkMsgNoEMail : "Podaj adres e-mail",
+DlnLnkMsgNoAnchor : "Wybierz etykietę",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Wybierz kolor",
+DlgColorBtnClear : "Wyczyść",
+DlgColorHighlight : "Podgląd",
+DlgColorSelected : "Wybrane",
+
+// Smiley Dialog
+DlgSmileyTitle : "Wstaw emotikonę",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Wybierz znak specjalny",
+
+// Table Dialog
+DlgTableTitle : "Właściwości tabeli",
+DlgTableRows : "Liczba wierszy",
+DlgTableColumns : "Liczba kolumn",
+DlgTableBorder : "Grubość ramki",
+DlgTableAlign : "Wyrównanie",
+DlgTableAlignNotSet : "<brak ustawień>",
+DlgTableAlignLeft : "Do lewej",
+DlgTableAlignCenter : "Do środka",
+DlgTableAlignRight : "Do prawej",
+DlgTableWidth : "Szerokość",
+DlgTableWidthPx : "piksele",
+DlgTableWidthPc : "%",
+DlgTableHeight : "Wysokość",
+DlgTableCellSpace : "Odstęp pomiędzy komórkami",
+DlgTableCellPad : "Margines wewnętrzny komórek",
+DlgTableCaption : "Tytuł",
+DlgTableSummary : "Podsumowanie",
+
+// Table Cell Dialog
+DlgCellTitle : "Właściwości komórki",
+DlgCellWidth : "Szerokość",
+DlgCellWidthPx : "piksele",
+DlgCellWidthPc : "%",
+DlgCellHeight : "Wysokość",
+DlgCellWordWrap : "Zawijanie tekstu",
+DlgCellWordWrapNotSet : "<brak ustawień>",
+DlgCellWordWrapYes : "Tak",
+DlgCellWordWrapNo : "Nie",
+DlgCellHorAlign : "Wyrównanie poziome",
+DlgCellHorAlignNotSet : "<brak ustawień>",
+DlgCellHorAlignLeft : "Do lewej",
+DlgCellHorAlignCenter : "Do środka",
+DlgCellHorAlignRight: "Do prawej",
+DlgCellVerAlign : "Wyrównanie pionowe",
+DlgCellVerAlignNotSet : "<brak ustawień>",
+DlgCellVerAlignTop : "Do góry",
+DlgCellVerAlignMiddle : "Do środka",
+DlgCellVerAlignBottom : "Do dołu",
+DlgCellVerAlignBaseline : "Do linii bazowej",
+DlgCellRowSpan : "Zajętość wierszy",
+DlgCellCollSpan : "Zajętość kolumn",
+DlgCellBackColor : "Kolor tła",
+DlgCellBorderColor : "Kolor ramki",
+DlgCellBtnSelect : "Wybierz...",
+
+// Find Dialog
+DlgFindTitle : "Znajdź",
+DlgFindFindBtn : "Znajdź",
+DlgFindNotFoundMsg : "Nie znaleziono szukanego hasła.",
+
+// Replace Dialog
+DlgReplaceTitle : "Zamień",
+DlgReplaceFindLbl : "Znajdź:",
+DlgReplaceReplaceLbl : "Zastąp przez:",
+DlgReplaceCaseChk : "Uwzględnij wielkość liter",
+DlgReplaceReplaceBtn : "Zastąp",
+DlgReplaceReplAllBtn : "Zastąp wszystko",
+DlgReplaceWordChk : "Całe słowa",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne wycinanie tekstu. Użyj skrótu klawiszowego Ctrl+X.",
+PasteErrorCopy : "Ustawienia bezpieczeństwa Twojej przeglądarki nie pozwalają na automatyczne kopiowanie tekstu. Użyj skrótu klawiszowego Ctrl+C.",
+
+PasteAsText : "Wklej jako czysty tekst",
+PasteFromWord : "Wklej z Worda",
+
+DlgPasteMsg2 : "Proszę wkleić w poniższym polu używając klawiaturowego skrótu (<STRONG>Ctrl+V</STRONG>) i kliknąć <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoruj definicje 'Font Face'",
+DlgPasteRemoveStyles : "Usuń definicje Stylów",
+DlgPasteCleanBox : "Wyczyść",
+
+// Color Picker
+ColorAutomatic : "Automatycznie",
+ColorMoreColors : "Więcej kolorów...",
+
+// Document Properties
+DocProps : "Właściwości dokumentu",
+
+// Anchor Dialog
+DlgAnchorTitle : "Właściwości kotwicy",
+DlgAnchorName : "Nazwa kotwicy",
+DlgAnchorErrorName : "Wpisz nazwę kotwicy",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Słowa nie ma w słowniku",
+DlgSpellChangeTo : "Zmień na",
+DlgSpellBtnIgnore : "Ignoruj",
+DlgSpellBtnIgnoreAll : "Ignoruj wszystkie",
+DlgSpellBtnReplace : "Zmień",
+DlgSpellBtnReplaceAll : "Zmień wszystkie",
+DlgSpellBtnUndo : "Undo",
+DlgSpellNoSuggestions : "- Brak sugestii -",
+DlgSpellProgress : "Trwa sprawdzanie ...",
+DlgSpellNoMispell : "Sprawdzanie zakończone: nie znaleziono błędów",
+DlgSpellNoChanges : "Sprawdzanie zakończone: nie zmieniono żadnego słowa",
+DlgSpellOneChange : "Sprawdzanie zakończone: zmieniono jedno słowo",
+DlgSpellManyChanges : "Sprawdzanie zakończone: zmieniono %l słów",
+
+IeSpellDownload : "Słownik nie jest zainstalowany. Chcesz go ściągnąć?",
+
+// Button Dialog
+DlgButtonText : "Tekst (Wartość)",
+DlgButtonType : "Typ",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nazwa",
+DlgCheckboxValue : "Wartość",
+DlgCheckboxSelected : "Zaznaczony",
+
+// Form Dialog
+DlgFormName : "Nazwa",
+DlgFormAction : "Akcja",
+DlgFormMethod : "Metoda",
+
+// Select Field Dialog
+DlgSelectName : "Nazwa",
+DlgSelectValue : "Wartość",
+DlgSelectSize : "Rozmiar",
+DlgSelectLines : "linii",
+DlgSelectChkMulti : "Wielokrotny wybór",
+DlgSelectOpAvail : "Dostępne opcje",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Wartość",
+DlgSelectBtnAdd : "Dodaj",
+DlgSelectBtnModify : "Zmień",
+DlgSelectBtnUp : "Do góry",
+DlgSelectBtnDown : "Do dołu",
+DlgSelectBtnSetValue : "Ustaw wartość zaznaczoną",
+DlgSelectBtnDelete : "Usuń",
+
+// Textarea Dialog
+DlgTextareaName : "Nazwa",
+DlgTextareaCols : "Kolumnu",
+DlgTextareaRows : "Wiersze",
+
+// Text Field Dialog
+DlgTextName : "Nazwa",
+DlgTextValue : "Wartość",
+DlgTextCharWidth : "Szerokość w znakach",
+DlgTextMaxChars : "Max. szerokość",
+DlgTextType : "Typ",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Hasło",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nazwa",
+DlgHiddenValue : "Wartość",
+
+// Bulleted List Dialog
+BulletedListProp : "Właściwości listy punktowanej",
+NumberedListProp : "Właściwości listy numerowanej",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Typ",
+DlgLstTypeCircle : "Koło",
+DlgLstTypeDisc : "Dysk",
+DlgLstTypeSquare : "Kwadrat",
+DlgLstTypeNumbers : "Cyfry (1, 2, 3)",
+DlgLstTypeLCase : "Małe litery (a, b, c)",
+DlgLstTypeUCase : "Duże litery (A, B, C)",
+DlgLstTypeSRoman : "Numeracja rzymska (i, ii, iii)",
+DlgLstTypeLRoman : "Numeracja rzymska (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Ogólne",
+DlgDocBackTab : "Tło",
+DlgDocColorsTab : "Kolory i marginesy",
+DlgDocMetaTab : "Meta Dane",
+
+DlgDocPageTitle : "Tytuł strony",
+DlgDocLangDir : "Kierunek pisania",
+DlgDocLangDirLTR : "Od lewej do prawej (LTR)",
+DlgDocLangDirRTL : "Od prawej do lewej (RTL)",
+DlgDocLangCode : "Kod języka",
+DlgDocCharSet : "Kodowanie znaków",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Inne kodowanie znaków",
+
+DlgDocDocType : "Nagłowek typu dokumentu",
+DlgDocDocTypeOther : "Inny typ dokumentu",
+DlgDocIncXHTML : "Dołącz deklarację XHTML",
+DlgDocBgColor : "Kolor tła",
+DlgDocBgImage : "Obrazek tła",
+DlgDocBgNoScroll : "Tło nieruchome",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Hiperłącze",
+DlgDocCVisited : "Odwiedzane hiperłącze",
+DlgDocCActive : "Aktywne hiperłącze",
+DlgDocMargins : "Marginesy strony",
+DlgDocMaTop : "Górny",
+DlgDocMaLeft : "Lewy",
+DlgDocMaRight : "Prawy",
+DlgDocMaBottom : "Dolny",
+DlgDocMeIndex : "Słowa kluczowe (oddzielone przecinkami)",
+DlgDocMeDescr : "Opis dokumentu",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Copyright",
+DlgDocPreview : "Podgląd",
+
+// Templates Dialog
+Templates : "Sablony",
+DlgTemplatesTitle : "Szablony zawartości",
+DlgTemplatesSelMsg : "Wybierz szablon do otwarcia w edytorze<br>(obecna zawartość okna edytora zostanie utracona):",
+DlgTemplatesLoading : "Ładowanie listy szablonów. Proszę czekać...",
+DlgTemplatesNoTpl : "(Brak zdefiniowanych szablonów)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "O ...",
+DlgAboutBrowserInfoTab : "O przeglądarce",
+DlgAboutLicenseTab : "Licencja",
+DlgAboutVersion : "wersja",
+DlgAboutInfo : "Więcej informacji uzyskasz pod adresem"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/pt-br.js b/httemplate/elements/fckeditor/editor/lang/pt-br.js
new file mode 100644
index 000000000..53a2b5ddd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/pt-br.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Brazilian Portuguese language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Ocultar Barra de Ferramentas",
+ToolbarExpand : "Exibir Barra de Ferramentas",
+
+// Toolbar Items and Context Menu
+Save : "Salvar",
+NewPage : "Novo",
+Preview : "Visualizar",
+Cut : "Recortar",
+Copy : "Copiar",
+Paste : "Colar",
+PasteText : "Colar como Texto sem Formatação",
+PasteWord : "Colar do Word",
+Print : "Imprimir",
+SelectAll : "Selecionar Tudo",
+RemoveFormat : "Remover Formatação",
+InsertLinkLbl : "Hiperlink",
+InsertLink : "Inserir/Editar Hiperlink",
+RemoveLink : "Remover Hiperlink",
+Anchor : "Inserir/Editar Âncora",
+InsertImageLbl : "Figura",
+InsertImage : "Inserir/Editar Figura",
+InsertFlashLbl : "Flash",
+InsertFlash : "Insere/Edita Flash",
+InsertTableLbl : "Tabela",
+InsertTable : "Inserir/Editar Tabela",
+InsertLineLbl : "Linha",
+InsertLine : "Inserir Linha Horizontal",
+InsertSpecialCharLbl: "Caracteres Especiais",
+InsertSpecialChar : "Inserir Caractere Especial",
+InsertSmileyLbl : "Emoticon",
+InsertSmiley : "Inserir Emoticon",
+About : "Sobre FCKeditor",
+Bold : "Negrito",
+Italic : "Itálico",
+Underline : "Sublinhado",
+StrikeThrough : "Tachado",
+Subscript : "Subscrito",
+Superscript : "Sobrescrito",
+LeftJustify : "Alinhar Esquerda",
+CenterJustify : "Centralizar",
+RightJustify : "Alinhar Direita",
+BlockJustify : "Justificado",
+DecreaseIndent : "Diminuir Recuo",
+IncreaseIndent : "Aumentar Recuo",
+Undo : "Desfazer",
+Redo : "Refazer",
+NumberedListLbl : "Numeração",
+NumberedList : "Inserir/Remover Numeração",
+BulletedListLbl : "Marcadores",
+BulletedList : "Inserir/Remover Marcadores",
+ShowTableBorders : "Exibir Bordas da Tabela",
+ShowDetails : "Exibir Detalhes",
+Style : "Estilo",
+FontFormat : "Formatação",
+Font : "Fonte",
+FontSize : "Tamanho",
+TextColor : "Cor do Texto",
+BGColor : "Cor do Plano de Fundo",
+Source : "Código-Fonte",
+Find : "Localizar",
+Replace : "Substituir",
+SpellCheck : "Verificar Ortografia",
+UniversalKeyboard : "Teclado Universal",
+PageBreakLbl : "Quebra de Página",
+PageBreak : "Inserir Quebra de Página",
+
+Form : "Formulário",
+Checkbox : "Caixa de Seleção",
+RadioButton : "Botão de Opção",
+TextField : "Caixa de Texto",
+Textarea : "Área de Texto",
+HiddenField : "Campo Oculto",
+Button : "Botão",
+SelectionField : "Caixa de Listagem",
+ImageButton : "Botão de Imagem",
+
+FitWindow : "Maximizar o tamanho do editor",
+
+// Context Menu
+EditLink : "Editar Hiperlink",
+CellCM : "Célula",
+RowCM : "Linha",
+ColumnCM : "Coluna",
+InsertRow : "Inserir Linha",
+DeleteRows : "Remover Linhas",
+InsertColumn : "Inserir Coluna",
+DeleteColumns : "Remover Colunas",
+InsertCell : "Inserir Células",
+DeleteCells : "Remover Células",
+MergeCells : "Mesclar Células",
+SplitCell : "Dividir Célular",
+TableDelete : "Apagar Tabela",
+CellProperties : "Formatar Célula",
+TableProperties : "Formatar Tabela",
+ImageProperties : "Formatar Figura",
+FlashProperties : "Propriedades Flash",
+
+AnchorProp : "Formatar Âncora",
+ButtonProp : "Formatar Botão",
+CheckboxProp : "Formatar Caixa de Seleção",
+HiddenFieldProp : "Formatar Campo Oculto",
+RadioButtonProp : "Formatar Botão de Opção",
+ImageButtonProp : "Formatar Botão de Imagem",
+TextFieldProp : "Formatar Caixa de Texto",
+SelectionFieldProp : "Formatar Caixa de Listagem",
+TextareaProp : "Formatar Área de Texto",
+FormProp : "Formatar Formulário",
+
+FontFormats : "Normal;Formatado;Endereço;Título 1;Título 2;Título 3;Título 4;Título 5;Título 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Processando XHTML. Por favor, aguarde...",
+Done : "Pronto",
+PasteWordConfirm : "O texto que você deseja colar parece ter sido copiado do Word. Você gostaria de remover a formatação antes de colar?",
+NotCompatiblePaste : "Este comando está disponível para o navegador Internet Explorer 5.5 ou superior. Você gostaria de colar sem remover a formatação?",
+UnknownToolbarItem : "O item da barra de ferramentas \"%1\" não é reconhecido",
+UnknownCommand : "O comando \"%1\" não é reconhecido",
+NotImplemented : "O comando não foi implementado",
+UnknownToolbarSet : "A barra de ferramentas \"%1\" não existe",
+NoActiveX : "As configurações de segurança do seu browser podem limitar algumas características do editor. Você precisa habilitar a opção \"Executar controles e plug-ins ActiveX\". Você pode experimentar erros e alertas de características faltantes.",
+BrowseServerBlocked : "Os recursos do browser não puderam ser abertos. Tenha certeza que todos os bloqueadores de popup estão desabilitados.",
+DialogBlocked : "Não foi possível abrir a janela de diálogo. Tenha certeza que todos os bloqueadores de popup estão desabilitados.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancelar",
+DlgBtnClose : "Fechar",
+DlgBtnBrowseServer : "Localizar no Servidor",
+DlgAdvancedTag : "Avançado",
+DlgOpOther : "<Outros>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Inserir a URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<não ajustado>",
+DlgGenId : "Id",
+DlgGenLangDir : "Direção do idioma",
+DlgGenLangDirLtr : "Esquerda para Direita (LTR)",
+DlgGenLangDirRtl : "Direita para Esquerda (RTL)",
+DlgGenLangCode : "Idioma",
+DlgGenAccessKey : "Chave de Acesso",
+DlgGenName : "Nome",
+DlgGenTabIndex : "Índice de Tabulação",
+DlgGenLongDescr : "Descrição da URL",
+DlgGenClass : "Classe de Folhas de Estilo",
+DlgGenTitle : "Título",
+DlgGenContType : "Tipo de Conteúdo",
+DlgGenLinkCharset : "Conjunto de Caracteres do Hiperlink",
+DlgGenStyle : "Estilos",
+
+// Image Dialog
+DlgImgTitle : "Formatar Figura",
+DlgImgInfoTab : "Informações da Figura",
+DlgImgBtnUpload : "Enviar para o Servidor",
+DlgImgURL : "URL",
+DlgImgUpload : "Submeter",
+DlgImgAlt : "Texto Alternativo",
+DlgImgWidth : "Largura",
+DlgImgHeight : "Altura",
+DlgImgLockRatio : "Manter proporções",
+DlgBtnResetSize : "Redefinir para o Tamanho Original",
+DlgImgBorder : "Borda",
+DlgImgHSpace : "Horizontal",
+DlgImgVSpace : "Vertical",
+DlgImgAlign : "Alinhamento",
+DlgImgAlignLeft : "Esquerda",
+DlgImgAlignAbsBottom: "Inferior Absoluto",
+DlgImgAlignAbsMiddle: "Centralizado Absoluto",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Inferior",
+DlgImgAlignMiddle : "Centralizado",
+DlgImgAlignRight : "Direita",
+DlgImgAlignTextTop : "Superior Absoluto",
+DlgImgAlignTop : "Superior",
+DlgImgPreview : "Visualização",
+DlgImgAlertUrl : "Por favor, digite o URL da figura.",
+DlgImgLinkTab : "Hiperlink",
+
+// Flash Dialog
+DlgFlashTitle : "Propriedades Flash",
+DlgFlashChkPlay : "Tocar Automaticamente",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Habilita Menu Flash",
+DlgFlashScale : "Escala",
+DlgFlashScaleAll : "Mostrar tudo",
+DlgFlashScaleNoBorder : "Sem Borda",
+DlgFlashScaleFit : "Escala Exata",
+
+// Link Dialog
+DlgLnkWindowTitle : "Hiperlink",
+DlgLnkInfoTab : "Informações",
+DlgLnkTargetTab : "Destino",
+
+DlgLnkType : "Tipo de hiperlink",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Âncora nesta página",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocolo",
+DlgLnkProtoOther : "<outro>",
+DlgLnkURL : "URL do hiperlink",
+DlgLnkAnchorSel : "Selecione uma âncora",
+DlgLnkAnchorByName : "Pelo Nome da âncora",
+DlgLnkAnchorById : "Pelo Id do Elemento",
+DlgLnkNoAnchors : "(Não há âncoras disponíveis neste documento)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Endereço E-Mail",
+DlgLnkEMailSubject : "Assunto da Mensagem",
+DlgLnkEMailBody : "Corpo da Mensagem",
+DlgLnkUpload : "Enviar ao Servidor",
+DlgLnkBtnUpload : "Enviar ao Servidor",
+
+DlgLnkTarget : "Destino",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<janela popup>",
+DlgLnkTargetBlank : "Nova Janela (_blank)",
+DlgLnkTargetParent : "Janela Pai (_parent)",
+DlgLnkTargetSelf : "Mesma Janela (_self)",
+DlgLnkTargetTop : "Janela Superior (_top)",
+DlgLnkTargetFrameName : "Nome do Frame de Destino",
+DlgLnkPopWinName : "Nome da Janela Pop-up",
+DlgLnkPopWinFeat : "Atributos da Janela Pop-up",
+DlgLnkPopResize : "Redimensionável",
+DlgLnkPopLocation : "Barra de Endereços",
+DlgLnkPopMenu : "Barra de Menus",
+DlgLnkPopScroll : "Barras de Rolagem",
+DlgLnkPopStatus : "Barra de Status",
+DlgLnkPopToolbar : "Barra de Ferramentas",
+DlgLnkPopFullScrn : "Modo Tela Cheia (IE)",
+DlgLnkPopDependent : "Dependente (Netscape)",
+DlgLnkPopWidth : "Largura",
+DlgLnkPopHeight : "Altura",
+DlgLnkPopLeft : "Esquerda",
+DlgLnkPopTop : "Superior",
+
+DlnLnkMsgNoUrl : "Por favor, digite o endereço do Hiperlink",
+DlnLnkMsgNoEMail : "Por favor, digite o endereço de e-mail",
+DlnLnkMsgNoAnchor : "Por favor, selecione uma âncora",
+DlnLnkMsgInvPopName : "O nome da janela popup deve começar com uma letra ou sublinhado (_) e não pode conter espaços",
+
+// Color Dialog
+DlgColorTitle : "Selecione uma Cor",
+DlgColorBtnClear : "Limpar",
+DlgColorHighlight : "Visualização",
+DlgColorSelected : "Selecionada",
+
+// Smiley Dialog
+DlgSmileyTitle : "Inserir Emoticon",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Selecione um Caractere Especial",
+
+// Table Dialog
+DlgTableTitle : "Formatar Tabela",
+DlgTableRows : "Linhas",
+DlgTableColumns : "Colunas",
+DlgTableBorder : "Borda",
+DlgTableAlign : "Alinhamento",
+DlgTableAlignNotSet : "<Não ajustado>",
+DlgTableAlignLeft : "Esquerda",
+DlgTableAlignCenter : "Centralizado",
+DlgTableAlignRight : "Direita",
+DlgTableWidth : "Largura",
+DlgTableWidthPx : "pixels",
+DlgTableWidthPc : "%",
+DlgTableHeight : "Altura",
+DlgTableCellSpace : "Espaçamento",
+DlgTableCellPad : "Enchimento",
+DlgTableCaption : "Legenda",
+DlgTableSummary : "Resumo",
+
+// Table Cell Dialog
+DlgCellTitle : "Formatar célula",
+DlgCellWidth : "Largura",
+DlgCellWidthPx : "pixels",
+DlgCellWidthPc : "%",
+DlgCellHeight : "Altura",
+DlgCellWordWrap : "Quebra de Linha",
+DlgCellWordWrapNotSet : "<Não ajustado>",
+DlgCellWordWrapYes : "Sim",
+DlgCellWordWrapNo : "Não",
+DlgCellHorAlign : "Alinhamento Horizontal",
+DlgCellHorAlignNotSet : "<Não ajustado>",
+DlgCellHorAlignLeft : "Esquerda",
+DlgCellHorAlignCenter : "Centralizado",
+DlgCellHorAlignRight: "Direita",
+DlgCellVerAlign : "Alinhamento Vertical",
+DlgCellVerAlignNotSet : "<Não ajustado>",
+DlgCellVerAlignTop : "Superior",
+DlgCellVerAlignMiddle : "Centralizado",
+DlgCellVerAlignBottom : "Inferior",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Transpor Linhas",
+DlgCellCollSpan : "Transpor Colunas",
+DlgCellBackColor : "Cor do Plano de Fundo",
+DlgCellBorderColor : "Cor da Borda",
+DlgCellBtnSelect : "Selecionar...",
+
+// Find Dialog
+DlgFindTitle : "Localizar...",
+DlgFindFindBtn : "Localizar",
+DlgFindNotFoundMsg : "O texto especificado não foi encontrado.",
+
+// Replace Dialog
+DlgReplaceTitle : "Substituir",
+DlgReplaceFindLbl : "Procurar por:",
+DlgReplaceReplaceLbl : "Substituir por:",
+DlgReplaceCaseChk : "Coincidir Maiúsculas/Minúsculas",
+DlgReplaceReplaceBtn : "Substituir",
+DlgReplaceReplAllBtn : "Substituir Tudo",
+DlgReplaceWordChk : "Coincidir a palavra inteira",
+
+// Paste Operations / Dialog
+PasteErrorCut : "As configurações de segurança do seu navegador não permitem que o editor execute operações de recortar automaticamente. Por favor, utilize o teclado para recortar (Ctrl+X).",
+PasteErrorCopy : "As configurações de segurança do seu navegador não permitem que o editor execute operações de copiar automaticamente. Por favor, utilize o teclado para copiar (Ctrl+C).",
+
+PasteAsText : "Colar como Texto sem Formatação",
+PasteFromWord : "Colar do Word",
+
+DlgPasteMsg2 : "Transfira o link usado no box usando o teclado com (<STRONG>Ctrl+V</STRONG>) e <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorar definições de fonte",
+DlgPasteRemoveStyles : "Remove definições de estilo",
+DlgPasteCleanBox : "Limpar Box",
+
+// Color Picker
+ColorAutomatic : "Automático",
+ColorMoreColors : "Mais Cores...",
+
+// Document Properties
+DocProps : "Propriedades Documento",
+
+// Anchor Dialog
+DlgAnchorTitle : "Formatar Âncora",
+DlgAnchorName : "Nome da Âncora",
+DlgAnchorErrorName : "Por favor, digite o nome da âncora",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Não encontrada",
+DlgSpellChangeTo : "Alterar para",
+DlgSpellBtnIgnore : "Ignorar uma vez",
+DlgSpellBtnIgnoreAll : "Ignorar Todas",
+DlgSpellBtnReplace : "Alterar",
+DlgSpellBtnReplaceAll : "Alterar Todas",
+DlgSpellBtnUndo : "Desfazer",
+DlgSpellNoSuggestions : "-sem sugestões de ortografia-",
+DlgSpellProgress : "Verificação ortográfica em andamento...",
+DlgSpellNoMispell : "Verificação encerrada: Não foram encontrados erros de ortografia",
+DlgSpellNoChanges : "Verificação ortográfica encerrada: Não houve alterações",
+DlgSpellOneChange : "Verificação ortográfica encerrada: Uma palavra foi alterada",
+DlgSpellManyChanges : "Verificação ortográfica encerrada: %1 foram alteradas",
+
+IeSpellDownload : "A verificação ortográfica não foi instalada. Você gostaria de realizar o download agora?",
+
+// Button Dialog
+DlgButtonText : "Texto (Valor)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Botão",
+DlgButtonTypeSbm : "Enviar",
+DlgButtonTypeRst : "Limpar",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nome",
+DlgCheckboxValue : "Valor",
+DlgCheckboxSelected : "Selecionado",
+
+// Form Dialog
+DlgFormName : "Nome",
+DlgFormAction : "Action",
+DlgFormMethod : "Método",
+
+// Select Field Dialog
+DlgSelectName : "Nome",
+DlgSelectValue : "Valor",
+DlgSelectSize : "Tamanho",
+DlgSelectLines : "linhas",
+DlgSelectChkMulti : "Permitir múltiplas seleções",
+DlgSelectOpAvail : "Opções disponíveis",
+DlgSelectOpText : "Texto",
+DlgSelectOpValue : "Valor",
+DlgSelectBtnAdd : "Adicionar",
+DlgSelectBtnModify : "Modificar",
+DlgSelectBtnUp : "Para cima",
+DlgSelectBtnDown : "Para baixo",
+DlgSelectBtnSetValue : "Definir como selecionado",
+DlgSelectBtnDelete : "Remover",
+
+// Textarea Dialog
+DlgTextareaName : "Nome",
+DlgTextareaCols : "Colunas",
+DlgTextareaRows : "Linhas",
+
+// Text Field Dialog
+DlgTextName : "Nome",
+DlgTextValue : "Valor",
+DlgTextCharWidth : "Comprimento (em caracteres)",
+DlgTextMaxChars : "Número Máximo de Caracteres",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Texto",
+DlgTextTypePass : "Senha",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nome",
+DlgHiddenValue : "Valor",
+
+// Bulleted List Dialog
+BulletedListProp : "Formatar Marcadores",
+NumberedListProp : "Formatar Numeração",
+DlgLstStart : "Iniciar",
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Círculo",
+DlgLstTypeDisc : "Disco",
+DlgLstTypeSquare : "Quadrado",
+DlgLstTypeNumbers : "Números (1, 2, 3)",
+DlgLstTypeLCase : "Letras Minúsculas (a, b, c)",
+DlgLstTypeUCase : "Letras Maiúsculas (A, B, C)",
+DlgLstTypeSRoman : "Números Romanos Minúsculos (i, ii, iii)",
+DlgLstTypeLRoman : "Números Romanos Maiúsculos (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Geral",
+DlgDocBackTab : "Plano de Fundo",
+DlgDocColorsTab : "Cores e Margens",
+DlgDocMetaTab : "Meta Dados",
+
+DlgDocPageTitle : "Título da Página",
+DlgDocLangDir : "Direção do Idioma",
+DlgDocLangDirLTR : "Esquerda para Direita (LTR)",
+DlgDocLangDirRTL : "Direita para Esquerda (RTL)",
+DlgDocLangCode : "Código do Idioma",
+DlgDocCharSet : "Codificação de Caracteres",
+DlgDocCharSetCE : "Europa Central",
+DlgDocCharSetCT : "Chinês Tradicional (Big5)",
+DlgDocCharSetCR : "Cirílico",
+DlgDocCharSetGR : "Grego",
+DlgDocCharSetJP : "Japonês",
+DlgDocCharSetKR : "Coreano",
+DlgDocCharSetTR : "Turco",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Europa Ocidental",
+DlgDocCharSetOther : "Outra Codificação de Caracteres",
+
+DlgDocDocType : "Cabeçalho Tipo de Documento",
+DlgDocDocTypeOther : "Other Document Type Heading",
+DlgDocIncXHTML : "Incluir Declarações XHTML",
+DlgDocBgColor : "Cor do Plano de Fundo",
+DlgDocBgImage : "URL da Imagem de Plano de Fundo",
+DlgDocBgNoScroll : "Plano de Fundo Fixo",
+DlgDocCText : "Texto",
+DlgDocCLink : "Hiperlink",
+DlgDocCVisited : "Hiperlink Visitado",
+DlgDocCActive : "Hiperlink Ativo",
+DlgDocMargins : "Margens da Página",
+DlgDocMaTop : "Superior",
+DlgDocMaLeft : "Inferior",
+DlgDocMaRight : "Direita",
+DlgDocMaBottom : "Inferior",
+DlgDocMeIndex : "Palavras-chave de Indexação do Documento (separadas por vírgula)",
+DlgDocMeDescr : "Descrição do Documento",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Direitos Autorais",
+DlgDocPreview : "Visualizar",
+
+// Templates Dialog
+Templates : "Modelos de layout",
+DlgTemplatesTitle : "Modelo de layout do conteúdo",
+DlgTemplatesSelMsg : "Selecione um modelo de layout para ser aberto no editor<br>(o conteúdo atual será perdido):",
+DlgTemplatesLoading : "Carregando a lista de modelos de layout. Aguarde...",
+DlgTemplatesNoTpl : "(Não foram definidos modelos de layout)",
+DlgTemplatesReplace : "Substituir o conteúdo atual",
+
+// About Dialog
+DlgAboutAboutTab : "Sobre",
+DlgAboutBrowserInfoTab : "Informações do Navegador",
+DlgAboutLicenseTab : "Licença",
+DlgAboutVersion : "versão",
+DlgAboutInfo : "Para maiores informações visite"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/pt.js b/httemplate/elements/fckeditor/editor/lang/pt.js
new file mode 100644
index 000000000..23bab35d9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/pt.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Portuguese language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Fechar Barra",
+ToolbarExpand : "Expandir Barra",
+
+// Toolbar Items and Context Menu
+Save : "Guardar",
+NewPage : "Nova Página",
+Preview : "Pré-visualizar",
+Cut : "Cortar",
+Copy : "Copiar",
+Paste : "Colar",
+PasteText : "Colar como texto não formatado",
+PasteWord : "Colar do Word",
+Print : "Imprimir",
+SelectAll : "Seleccionar Tudo",
+RemoveFormat : "Eliminar Formato",
+InsertLinkLbl : "Hiperligação",
+InsertLink : "Inserir/Editar Hiperligação",
+RemoveLink : "Eliminar Hiperligação",
+Anchor : " Inserir/Editar Âncora",
+InsertImageLbl : "Imagem",
+InsertImage : "Inserir/Editar Imagem",
+InsertFlashLbl : "Flash",
+InsertFlash : "Inserir/Editar Flash",
+InsertTableLbl : "Tabela",
+InsertTable : "Inserir/Editar Tabela",
+InsertLineLbl : "Linha",
+InsertLine : "Inserir Linha Horizontal",
+InsertSpecialCharLbl: "Caracter Especial",
+InsertSpecialChar : "Inserir Caracter Especial",
+InsertSmileyLbl : "Emoticons",
+InsertSmiley : "Inserir Emoticons",
+About : "Acerca do FCKeditor",
+Bold : "Negrito",
+Italic : "Itálico",
+Underline : "Sublinhado",
+StrikeThrough : "Rasurado",
+Subscript : "Superior à Linha",
+Superscript : "Inferior à Linha",
+LeftJustify : "Alinhar à Esquerda",
+CenterJustify : "Alinhar ao Centro",
+RightJustify : "Alinhar à Direita",
+BlockJustify : "Justificado",
+DecreaseIndent : "Diminuir Avanço",
+IncreaseIndent : "Aumentar Avanço",
+Undo : "Anular",
+Redo : "Repetir",
+NumberedListLbl : "Numeração",
+NumberedList : "Inserir/Eliminar Numeração",
+BulletedListLbl : "Marcas",
+BulletedList : "Inserir/Eliminar Marcas",
+ShowTableBorders : "Mostrar Limites da Tabelas",
+ShowDetails : "Mostrar Parágrafo",
+Style : "Estilo",
+FontFormat : "Formato",
+Font : "Tipo de Letra",
+FontSize : "Tamanho",
+TextColor : "Cor do Texto",
+BGColor : "Cor de Fundo",
+Source : "Fonte",
+Find : "Procurar",
+Replace : "Substituir",
+SpellCheck : "Verificação Ortográfica",
+UniversalKeyboard : "Teclado Universal",
+PageBreakLbl : "Quebra de Página",
+PageBreak : "Inserir Quebra de Página",
+
+Form : "Formulário",
+Checkbox : "Caixa de Verificação",
+RadioButton : "Botão de Opção",
+TextField : "Campo de Texto",
+Textarea : "Área de Texto",
+HiddenField : "Campo Escondido",
+Button : "Botão",
+SelectionField : "Caixa de Combinação",
+ImageButton : "Botão de Imagem",
+
+FitWindow : "Maximizar o tamanho do editor",
+
+// Context Menu
+EditLink : "Editar Hiperligação",
+CellCM : "Célula",
+RowCM : "Linha",
+ColumnCM : "Coluna",
+InsertRow : "Inserir Linha",
+DeleteRows : "Eliminar Linhas",
+InsertColumn : "Inserir Coluna",
+DeleteColumns : "Eliminar Coluna",
+InsertCell : "Inserir Célula",
+DeleteCells : "Eliminar Célula",
+MergeCells : "Unir Células",
+SplitCell : "Dividir Célula",
+TableDelete : "Eliminar Tabela",
+CellProperties : "Propriedades da Célula",
+TableProperties : "Propriedades da Tabela",
+ImageProperties : "Propriedades da Imagem",
+FlashProperties : "Propriedades do Flash",
+
+AnchorProp : "Propriedades da Âncora",
+ButtonProp : "Propriedades do Botão",
+CheckboxProp : "Propriedades da Caixa de Verificação",
+HiddenFieldProp : "Propriedades do Campo Escondido",
+RadioButtonProp : "Propriedades do Botão de Opção",
+ImageButtonProp : "Propriedades do Botão de imagens",
+TextFieldProp : "Propriedades do Campo de Texto",
+SelectionFieldProp : "Propriedades da Caixa de Combinação",
+TextareaProp : "Propriedades da Área de Texto",
+FormProp : "Propriedades do Formulário",
+
+FontFormats : "Normal;Formatado;Endereço;Título 1;Título 2;Título 3;Título 4;Título 5;Título 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "A Processar XHTML. Por favor, espere...",
+Done : "Concluído",
+PasteWordConfirm : "O texto que deseja parece ter sido copiado do Word. Deseja limpar a formatação antes de colar?",
+NotCompatiblePaste : "Este comando só está disponível para Internet Explorer versão 5.5 ou superior. Deseja colar sem limpar a formatação?",
+UnknownToolbarItem : "Item de barra desconhecido \"%1\"",
+UnknownCommand : "Nome de comando desconhecido \"%1\"",
+NotImplemented : "Comando não implementado",
+UnknownToolbarSet : "Nome de barra \"%1\" não definido",
+NoActiveX : "As definições de segurança do navegador podem limitar algumas potencalidades do editr. Deve activar a opção \"Executar controlos e extensões ActiveX\". Pode ocorrer erros ou verificar que faltam potencialidades.",
+BrowseServerBlocked : "Não foi possível abrir o navegador de recursos. Certifique-se que todos os bloqueadores de popup estão desactivados.",
+DialogBlocked : "Não foi possível abrir a janela de diálogo. Certifique-se que todos os bloqueadores de popup estão desactivados.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Cancelar",
+DlgBtnClose : "Fechar",
+DlgBtnBrowseServer : "Navegar no Servidor",
+DlgAdvancedTag : "Avançado",
+DlgOpOther : "<Outro>",
+DlgInfoTab : "Informação",
+DlgAlertUrl : "Por favor introduza o URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<Não definido>",
+DlgGenId : "Id",
+DlgGenLangDir : "Orientação de idioma",
+DlgGenLangDirLtr : "Esquerda à Direita (LTR)",
+DlgGenLangDirRtl : "Direita a Esquerda (RTL)",
+DlgGenLangCode : "Código de Idioma",
+DlgGenAccessKey : "Chave de Acesso",
+DlgGenName : "Nome",
+DlgGenTabIndex : "Índice de Tubulação",
+DlgGenLongDescr : "Descrição Completa do URL",
+DlgGenClass : "Classes de Estilo de Folhas Classes",
+DlgGenTitle : "Título",
+DlgGenContType : "Tipo de Conteúdo",
+DlgGenLinkCharset : "Fonte de caracteres vinculado",
+DlgGenStyle : "Estilo",
+
+// Image Dialog
+DlgImgTitle : "Propriedades da Imagem",
+DlgImgInfoTab : "Informação da Imagem",
+DlgImgBtnUpload : "Enviar para o Servidor",
+DlgImgURL : "URL",
+DlgImgUpload : "Carregar",
+DlgImgAlt : "Texto Alternativo",
+DlgImgWidth : "Largura",
+DlgImgHeight : "Altura",
+DlgImgLockRatio : "Proporcional",
+DlgBtnResetSize : "Tamanho Original",
+DlgImgBorder : "Limite",
+DlgImgHSpace : "Esp.Horiz",
+DlgImgVSpace : "Esp.Vert",
+DlgImgAlign : "Alinhamento",
+DlgImgAlignLeft : "Esquerda",
+DlgImgAlignAbsBottom: "Abs inferior",
+DlgImgAlignAbsMiddle: "Abs centro",
+DlgImgAlignBaseline : "Linha de base",
+DlgImgAlignBottom : "Fundo",
+DlgImgAlignMiddle : "Centro",
+DlgImgAlignRight : "Direita",
+DlgImgAlignTextTop : "Topo do texto",
+DlgImgAlignTop : "Topo",
+DlgImgPreview : "Pré-visualizar",
+DlgImgAlertUrl : "Por favor introduza o URL da imagem",
+DlgImgLinkTab : "Hiperligação",
+
+// Flash Dialog
+DlgFlashTitle : "Propriedades do Flash",
+DlgFlashChkPlay : "Reproduzir automaticamente",
+DlgFlashChkLoop : "Loop",
+DlgFlashChkMenu : "Permitir Menu do Flash",
+DlgFlashScale : "Escala",
+DlgFlashScaleAll : "Mostrar tudo",
+DlgFlashScaleNoBorder : "Sem Limites",
+DlgFlashScaleFit : "Tamanho Exacto",
+
+// Link Dialog
+DlgLnkWindowTitle : "Hiperligação",
+DlgLnkInfoTab : "Informação de Hiperligação",
+DlgLnkTargetTab : "Destino",
+
+DlgLnkType : "Tipo de Hiperligação",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Referência a esta página",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocolo",
+DlgLnkProtoOther : "<outro>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Seleccionar una referência",
+DlgLnkAnchorByName : "Por Nome de Referência",
+DlgLnkAnchorById : "Por ID de elemento",
+DlgLnkNoAnchors : "<Não há referências disponíveis no documento>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Endereço de E-Mail",
+DlgLnkEMailSubject : "Título de Mensagem",
+DlgLnkEMailBody : "Corpo da Mensagem",
+DlgLnkUpload : "Carregar",
+DlgLnkBtnUpload : "Enviar ao Servidor",
+
+DlgLnkTarget : "Destino",
+DlgLnkTargetFrame : "<Frame>",
+DlgLnkTargetPopup : "<Janela de popup>",
+DlgLnkTargetBlank : "Nova Janela(_blank)",
+DlgLnkTargetParent : "Janela Pai (_parent)",
+DlgLnkTargetSelf : "Mesma janela (_self)",
+DlgLnkTargetTop : "Janela primaria (_top)",
+DlgLnkTargetFrameName : "Nome do Frame Destino",
+DlgLnkPopWinName : "Nome da Janela de Popup",
+DlgLnkPopWinFeat : "Características de Janela de Popup",
+DlgLnkPopResize : "Ajustável",
+DlgLnkPopLocation : "Barra de localização",
+DlgLnkPopMenu : "Barra de Menu",
+DlgLnkPopScroll : "Barras de deslocamento",
+DlgLnkPopStatus : "Barra de Estado",
+DlgLnkPopToolbar : "Barra de Ferramentas",
+DlgLnkPopFullScrn : "Janela Completa (IE)",
+DlgLnkPopDependent : "Dependente (Netscape)",
+DlgLnkPopWidth : "Largura",
+DlgLnkPopHeight : "Altura",
+DlgLnkPopLeft : "Posição Esquerda",
+DlgLnkPopTop : "Posição Direita",
+
+DlnLnkMsgNoUrl : "Por favor introduza a hiperligação URL",
+DlnLnkMsgNoEMail : "Por favor introduza o endereço de e-mail",
+DlnLnkMsgNoAnchor : "Por favor seleccione uma referência",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Seleccionar Cor",
+DlgColorBtnClear : "Nenhuma",
+DlgColorHighlight : "Destacado",
+DlgColorSelected : "Seleccionado",
+
+// Smiley Dialog
+DlgSmileyTitle : "Inserir um Emoticon",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Seleccione um caracter especial",
+
+// Table Dialog
+DlgTableTitle : "Propriedades da Tabela",
+DlgTableRows : "Linhas",
+DlgTableColumns : "Colunas",
+DlgTableBorder : "Tamanho do Limite",
+DlgTableAlign : "Alinhamento",
+DlgTableAlignNotSet : "<Não definido>",
+DlgTableAlignLeft : "Esquerda",
+DlgTableAlignCenter : "Centrado",
+DlgTableAlignRight : "Direita",
+DlgTableWidth : "Largura",
+DlgTableWidthPx : "pixeis",
+DlgTableWidthPc : "percentagem",
+DlgTableHeight : "Altura",
+DlgTableCellSpace : "Esp. e/células",
+DlgTableCellPad : "Esp. interior",
+DlgTableCaption : "Título",
+DlgTableSummary : "Sumário",
+
+// Table Cell Dialog
+DlgCellTitle : "Propriedades da Célula",
+DlgCellWidth : "Largura",
+DlgCellWidthPx : "pixeis",
+DlgCellWidthPc : "percentagem",
+DlgCellHeight : "Altura",
+DlgCellWordWrap : "Moldar Texto",
+DlgCellWordWrapNotSet : "<Não definido>",
+DlgCellWordWrapYes : "Sim",
+DlgCellWordWrapNo : "Não",
+DlgCellHorAlign : "Alinhamento Horizontal",
+DlgCellHorAlignNotSet : "<Não definido>",
+DlgCellHorAlignLeft : "Esquerda",
+DlgCellHorAlignCenter : "Centrado",
+DlgCellHorAlignRight: "Direita",
+DlgCellVerAlign : "Alinhamento Vertical",
+DlgCellVerAlignNotSet : "<Não definido>",
+DlgCellVerAlignTop : "Topo",
+DlgCellVerAlignMiddle : "Médio",
+DlgCellVerAlignBottom : "Fundi",
+DlgCellVerAlignBaseline : "Linha de Base",
+DlgCellRowSpan : "Unir Linhas",
+DlgCellCollSpan : "Unir Colunas",
+DlgCellBackColor : "Cor do Fundo",
+DlgCellBorderColor : "Cor do Limite",
+DlgCellBtnSelect : "Seleccione...",
+
+// Find Dialog
+DlgFindTitle : "Procurar",
+DlgFindFindBtn : "Procurar",
+DlgFindNotFoundMsg : "O texto especificado não foi encontrado.",
+
+// Replace Dialog
+DlgReplaceTitle : "Substituir",
+DlgReplaceFindLbl : "Texto a Procurar:",
+DlgReplaceReplaceLbl : "Substituir por:",
+DlgReplaceCaseChk : "Maiúsculas/Minúsculas",
+DlgReplaceReplaceBtn : "Substituir",
+DlgReplaceReplAllBtn : "Substituir Tudo",
+DlgReplaceWordChk : "Coincidir com toda a palavra",
+
+// Paste Operations / Dialog
+PasteErrorCut : "A configuração de segurança do navegador não permite a execução automática de operações de cortar. Por favor use o teclado (Ctrl+X).",
+PasteErrorCopy : "A configuração de segurança do navegador não permite a execução automática de operações de copiar. Por favor use o teclado (Ctrl+C).",
+
+PasteAsText : "Colar como Texto Simples",
+PasteFromWord : "Colar do Word",
+
+DlgPasteMsg2 : "Por favor, cole dentro da seguinte caixa usando o teclado (<STRONG>Ctrl+V</STRONG>) e prima <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorar da definições do Tipo de Letra ",
+DlgPasteRemoveStyles : "Remover as definições de Estilos",
+DlgPasteCleanBox : "Caixa de Limpeza",
+
+// Color Picker
+ColorAutomatic : "Automático",
+ColorMoreColors : "Mais Cores...",
+
+// Document Properties
+DocProps : "Propriedades do Documento",
+
+// Anchor Dialog
+DlgAnchorTitle : "Propriedades da Âncora",
+DlgAnchorName : "Nome da Âncora",
+DlgAnchorErrorName : "Por favor, introduza o nome da âncora",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Não está num directório",
+DlgSpellChangeTo : "Mudar para",
+DlgSpellBtnIgnore : "Ignorar",
+DlgSpellBtnIgnoreAll : "Ignorar Tudo",
+DlgSpellBtnReplace : "Substituir",
+DlgSpellBtnReplaceAll : "Substituir Tudo",
+DlgSpellBtnUndo : "Anular",
+DlgSpellNoSuggestions : "- Sem sugestões -",
+DlgSpellProgress : "Verificação ortográfica em progresso…",
+DlgSpellNoMispell : "Verificação ortográfica completa: não foram encontrados erros",
+DlgSpellNoChanges : "Verificação ortográfica completa: não houve alteração de palavras",
+DlgSpellOneChange : "Verificação ortográfica completa: uma palavra alterada",
+DlgSpellManyChanges : "Verificação ortográfica completa: %1 palavras alteradas",
+
+IeSpellDownload : " Verificação ortográfica não instalada. Quer descarregar agora?",
+
+// Button Dialog
+DlgButtonText : "Texto (Valor)",
+DlgButtonType : "Tipo",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nome",
+DlgCheckboxValue : "Valor",
+DlgCheckboxSelected : "Seleccionado",
+
+// Form Dialog
+DlgFormName : "Nome",
+DlgFormAction : "Acção",
+DlgFormMethod : "Método",
+
+// Select Field Dialog
+DlgSelectName : "Nome",
+DlgSelectValue : "Valor",
+DlgSelectSize : "Tamanho",
+DlgSelectLines : "linhas",
+DlgSelectChkMulti : "Permitir selecções múltiplas",
+DlgSelectOpAvail : "Opções Possíveis",
+DlgSelectOpText : "Texto",
+DlgSelectOpValue : "Valor",
+DlgSelectBtnAdd : "Adicionar",
+DlgSelectBtnModify : "Modificar",
+DlgSelectBtnUp : "Para cima",
+DlgSelectBtnDown : "Para baixo",
+DlgSelectBtnSetValue : "Definir um valor por defeito",
+DlgSelectBtnDelete : "Apagar",
+
+// Textarea Dialog
+DlgTextareaName : "Nome",
+DlgTextareaCols : "Colunas",
+DlgTextareaRows : "Linhas",
+
+// Text Field Dialog
+DlgTextName : "Nome",
+DlgTextValue : "Valor",
+DlgTextCharWidth : "Tamanho do caracter",
+DlgTextMaxChars : "Nr. Máximo de Caracteres",
+DlgTextType : "Tipo",
+DlgTextTypeText : "Texto",
+DlgTextTypePass : "Palavra-chave",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nome",
+DlgHiddenValue : "Valor",
+
+// Bulleted List Dialog
+BulletedListProp : "Propriedades da Marca",
+NumberedListProp : "Propriedades da Numeração",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tipo",
+DlgLstTypeCircle : "Circulo",
+DlgLstTypeDisc : "Disco",
+DlgLstTypeSquare : "Quadrado",
+DlgLstTypeNumbers : "Números (1, 2, 3)",
+DlgLstTypeLCase : "Letras Minúsculas (a, b, c)",
+DlgLstTypeUCase : "Letras Maiúsculas (A, B, C)",
+DlgLstTypeSRoman : "Numeração Romana em Minúsculas (i, ii, iii)",
+DlgLstTypeLRoman : "Numeração Romana em Maiúsculas (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Geral",
+DlgDocBackTab : "Fundo",
+DlgDocColorsTab : "Cores e Margens",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Título da Página",
+DlgDocLangDir : "Orientação de idioma",
+DlgDocLangDirLTR : "Esquerda à Direita (LTR)",
+DlgDocLangDirRTL : "Direita à Esquerda (RTL)",
+DlgDocLangCode : "Código de Idioma",
+DlgDocCharSet : "Codificação de Caracteres",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Outra Codificação de Caracteres",
+
+DlgDocDocType : "Tipo de Cabeçalho do Documento",
+DlgDocDocTypeOther : "Outro Tipo de Cabeçalho do Documento",
+DlgDocIncXHTML : "Incluir Declarações XHTML",
+DlgDocBgColor : "Cor de Fundo",
+DlgDocBgImage : "Caminho para a Imagem de Fundo",
+DlgDocBgNoScroll : "Fundo Fixo",
+DlgDocCText : "Texto",
+DlgDocCLink : "Hiperligação",
+DlgDocCVisited : "Hiperligação Visitada",
+DlgDocCActive : "Hiperligação Activa",
+DlgDocMargins : "Margem das Páginas",
+DlgDocMaTop : "Topo",
+DlgDocMaLeft : "Esquerda",
+DlgDocMaRight : "Direita",
+DlgDocMaBottom : "Fundo",
+DlgDocMeIndex : "Palavras de Indexação do Documento (separadas por virgula)",
+DlgDocMeDescr : "Descrição do Documento",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Direitos de Autor",
+DlgDocPreview : "Pré-visualizar",
+
+// Templates Dialog
+Templates : "Modelos",
+DlgTemplatesTitle : "Modelo de Conteúdo",
+DlgTemplatesSelMsg : "Por favor, seleccione o modelo a abrir no editor<br>(o conteúdo actual será perdido):",
+DlgTemplatesLoading : "A carregar a lista de modelos. Aguarde por favor...",
+DlgTemplatesNoTpl : "(Sem modelos definidos)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Acerca",
+DlgAboutBrowserInfoTab : "Informação do Nevegador",
+DlgAboutLicenseTab : "Licença",
+DlgAboutVersion : "versão",
+DlgAboutInfo : "Para mais informações por favor dirija-se a"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ro.js b/httemplate/elements/fckeditor/editor/lang/ro.js
new file mode 100644
index 000000000..1f36961cf
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ro.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Romanian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Ascunde bara cu opţiuni",
+ToolbarExpand : "Expandează bara cu opţiuni",
+
+// Toolbar Items and Context Menu
+Save : "Salvează",
+NewPage : "Pagină nouă",
+Preview : "Previzualizare",
+Cut : "Taie",
+Copy : "Copiază",
+Paste : "Adaugă",
+PasteText : "Adaugă ca text simplu",
+PasteWord : "Adaugă din Word",
+Print : "Printează",
+SelectAll : "Selectează tot",
+RemoveFormat : "Înlătură formatarea",
+InsertLinkLbl : "Link (Legătură web)",
+InsertLink : "Inserează/Editează link (legătură web)",
+RemoveLink : "Înlătură link (legătură web)",
+Anchor : "Inserează/Editează ancoră",
+InsertImageLbl : "Imagine",
+InsertImage : "Inserează/Editează imagine",
+InsertFlashLbl : "Flash",
+InsertFlash : "Inserează/Editează flash",
+InsertTableLbl : "Tabel",
+InsertTable : "Inserează/Editează tabel",
+InsertLineLbl : "Linie",
+InsertLine : "Inserează linie orizontă",
+InsertSpecialCharLbl: "Caracter special",
+InsertSpecialChar : "Inserează caracter special",
+InsertSmileyLbl : "Figură expresivă (Emoticon)",
+InsertSmiley : "Inserează Figură expresivă (Emoticon)",
+About : "Despre FCKeditor",
+Bold : "Îngroşat (bold)",
+Italic : "Înclinat (italic)",
+Underline : "Subliniat (underline)",
+StrikeThrough : "Tăiat (strike through)",
+Subscript : "Indice (subscript)",
+Superscript : "Putere (superscript)",
+LeftJustify : "Aliniere la stânga",
+CenterJustify : "Aliniere centrală",
+RightJustify : "Aliniere la dreapta",
+BlockJustify : "Aliniere în bloc (Block Justify)",
+DecreaseIndent : "Scade indentarea",
+IncreaseIndent : "Creşte indentarea",
+Undo : "Starea anterioară (undo)",
+Redo : "Starea ulterioară (redo)",
+NumberedListLbl : "Listă numerotată",
+NumberedList : "Inserează/Şterge listă numerotată",
+BulletedListLbl : "Listă cu puncte",
+BulletedList : "Inserează/Şterge listă cu puncte",
+ShowTableBorders : "Arată marginile tabelului",
+ShowDetails : "Arată detalii",
+Style : "Stil",
+FontFormat : "Formatare",
+Font : "Font",
+FontSize : "Mărime",
+TextColor : "Culoarea textului",
+BGColor : "Coloarea fundalului",
+Source : "Sursa",
+Find : "Găseşte",
+Replace : "Înlocuieşte",
+SpellCheck : "Verifică text",
+UniversalKeyboard : "Tastatură universală",
+PageBreakLbl : "Separator de pagină (Page Break)",
+PageBreak : "Inserează separator de pagină (Page Break)",
+
+Form : "Formular (Form)",
+Checkbox : "Bifă (Checkbox)",
+RadioButton : "Buton radio (RadioButton)",
+TextField : "Câmp text (TextField)",
+Textarea : "Suprafaţă text (Textarea)",
+HiddenField : "Câmp ascuns (HiddenField)",
+Button : "Buton",
+SelectionField : "Câmp selecţie (SelectionField)",
+ImageButton : "Buton imagine (ImageButton)",
+
+FitWindow : "Maximizează mărimea editorului",
+
+// Context Menu
+EditLink : "Editează Link",
+CellCM : "Celulă",
+RowCM : "Linie",
+ColumnCM : "Coloană",
+InsertRow : "Inserează linie",
+DeleteRows : "Şterge linii",
+InsertColumn : "Inserează coloană",
+DeleteColumns : "Şterge celule",
+InsertCell : "Inserează celulă",
+DeleteCells : "Şterge celule",
+MergeCells : "Uneşte celule",
+SplitCell : "Împarte celulă",
+TableDelete : "Şterge tabel",
+CellProperties : "Proprietăţile celulei",
+TableProperties : "Proprietăţile tabelului",
+ImageProperties : "Proprietăţile imaginii",
+FlashProperties : "Proprietăţile flash-ului",
+
+AnchorProp : "Proprietăţi ancoră",
+ButtonProp : "Proprietăţi buton",
+CheckboxProp : "Proprietăţi bifă (Checkbox)",
+HiddenFieldProp : "Proprietăţi câmp ascuns (Hidden Field)",
+RadioButtonProp : "Proprietăţi buton radio (Radio Button)",
+ImageButtonProp : "Proprietăţi buton imagine (Image Button)",
+TextFieldProp : "Proprietăţi câmp text (Text Field)",
+SelectionFieldProp : "Proprietăţi câmp selecţie (Selection Field)",
+TextareaProp : "Proprietăţi suprafaţă text (Textarea)",
+FormProp : "Proprietăţi formular (Form)",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html //MISSING
+
+// Alerts and Messages
+ProcessingXHTML : "Procesăm XHTML. Vă rugăm aşteptaţi...",
+Done : "Am terminat",
+PasteWordConfirm : "Textul pe care doriţi să-l adăugaţi pare a fi formatat pentru Word. Doriţi să-l curăţaţi de această formatare înainte de a-l adăuga?",
+NotCompatiblePaste : "Această facilitate e disponibilă doar pentru Microsoft Internet Explorer, versiunea 5.5 sau ulterioară. Vreţi să-l adăugaţi fără a-i fi înlăturat formatarea?",
+UnknownToolbarItem : "Obiectul \"%1\" din bara cu opţiuni necunoscut",
+UnknownCommand : "Comanda \"%1\" necunoscută",
+NotImplemented : "Comandă neimplementată",
+UnknownToolbarSet : "Grupul din bara cu opţiuni \"%1\" nu există",
+NoActiveX : "Setările de securitate ale programului dvs. cu care navigaţi pe internet (browser) pot limita anumite funcţionalităţi ale editorului. Pentru a evita asta, trebuie să activaţi opţiunea \"Run ActiveX controls and plug-ins\". Poate veţi întâlni erori sau veţi observa funcţionalităţi lipsă.",
+BrowseServerBlocked : "The resources browser could not be opened. Asiguraţi-vă că nu e activ niciun \"popup blocker\" (funcţionalitate a programului de navigat (browser) sau a unui plug-in al acestuia de a bloca deschiderea unui noi ferestre).",
+DialogBlocked : "Nu a fost posibilă deschiderea unei ferestre de dialog. Asiguraţi-vă că nu e activ niciun \"popup blocker\" (funcţionalitate a programului de navigat (browser) sau a unui plug-in al acestuia de a bloca deschiderea unui noi ferestre).",
+
+// Dialogs
+DlgBtnOK : "Bine",
+DlgBtnCancel : "Anulare",
+DlgBtnClose : "Închidere",
+DlgBtnBrowseServer : "Răsfoieşte server",
+DlgAdvancedTag : "Avansat",
+DlgOpOther : "<Altul>",
+DlgInfoTab : "Informaţii",
+DlgAlertUrl : "Vă rugăm să scrieţi URL-ul",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nesetat>",
+DlgGenId : "Id",
+DlgGenLangDir : "Direcţia cuvintelor",
+DlgGenLangDirLtr : "stânga-dreapta (LTR)",
+DlgGenLangDirRtl : "dreapta-stânga (RTL)",
+DlgGenLangCode : "Codul limbii",
+DlgGenAccessKey : "Tasta de acces",
+DlgGenName : "Nume",
+DlgGenTabIndex : "Indexul tabului",
+DlgGenLongDescr : "Descrierea lungă URL",
+DlgGenClass : "Clasele cu stilul paginii (CSS)",
+DlgGenTitle : "Titlul consultativ",
+DlgGenContType : "Tipul consultativ al titlului",
+DlgGenLinkCharset : "Setul de caractere al resursei legate",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Proprietăţile imaginii",
+DlgImgInfoTab : "Informaţii despre imagine",
+DlgImgBtnUpload : "Trimite la server",
+DlgImgURL : "URL",
+DlgImgUpload : "Încarcă",
+DlgImgAlt : "Text alternativ",
+DlgImgWidth : "Lăţime",
+DlgImgHeight : "Înălţime",
+DlgImgLockRatio : "Păstrează proporţiile",
+DlgBtnResetSize : "Resetează mărimea",
+DlgImgBorder : "Margine",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Aliniere",
+DlgImgAlignLeft : "Stânga",
+DlgImgAlignAbsBottom: "Jos absolut (Abs Bottom)",
+DlgImgAlignAbsMiddle: "Mijloc absolut (Abs Middle)",
+DlgImgAlignBaseline : "Linia de jos (Baseline)",
+DlgImgAlignBottom : "Jos",
+DlgImgAlignMiddle : "Mijloc",
+DlgImgAlignRight : "Dreapta",
+DlgImgAlignTextTop : "Text sus",
+DlgImgAlignTop : "Sus",
+DlgImgPreview : "Previzualizare",
+DlgImgAlertUrl : "Vă rugăm să scrieţi URL-ul imaginii",
+DlgImgLinkTab : "Link (Legătură web)",
+
+// Flash Dialog
+DlgFlashTitle : "Proprietăţile flash-ului",
+DlgFlashChkPlay : "Rulează automat",
+DlgFlashChkLoop : "Repetă (Loop)",
+DlgFlashChkMenu : "Activează meniul flash",
+DlgFlashScale : "Scală",
+DlgFlashScaleAll : "Arată tot",
+DlgFlashScaleNoBorder : "Fără margini (No border)",
+DlgFlashScaleFit : "Potriveşte",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link (Legătură web)",
+DlgLnkInfoTab : "Informaţii despre link (Legătură web)",
+DlgLnkTargetTab : "Ţintă (Target)",
+
+DlgLnkType : "Tipul link-ului (al legăturii web)",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ancoră în această pagină",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protocol",
+DlgLnkProtoOther : "<altul>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Selectaţi o ancoră",
+DlgLnkAnchorByName : "după numele ancorei",
+DlgLnkAnchorById : "după Id-ul elementului",
+DlgLnkNoAnchors : "<Nicio ancoră disponibilă în document>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Adresă de e-mail",
+DlgLnkEMailSubject : "Subiectul mesajului",
+DlgLnkEMailBody : "Conţinutul mesajului",
+DlgLnkUpload : "Încarcă",
+DlgLnkBtnUpload : "Trimite la server",
+
+DlgLnkTarget : "Ţintă (Target)",
+DlgLnkTargetFrame : "<frame>",
+DlgLnkTargetPopup : "<fereastra popup>",
+DlgLnkTargetBlank : "Fereastră nouă (_blank)",
+DlgLnkTargetParent : "Fereastra părinte (_parent)",
+DlgLnkTargetSelf : "Aceeaşi fereastră (_self)",
+DlgLnkTargetTop : "Fereastra din topul ierarhiei (_top)",
+DlgLnkTargetFrameName : "Numele frame-ului ţintă",
+DlgLnkPopWinName : "Numele ferestrei popup",
+DlgLnkPopWinFeat : "Proprietăţile ferestrei popup",
+DlgLnkPopResize : "Scalabilă",
+DlgLnkPopLocation : "Bara de locaţie",
+DlgLnkPopMenu : "Bara de meniu",
+DlgLnkPopScroll : "Scroll Bars",
+DlgLnkPopStatus : "Bara de status",
+DlgLnkPopToolbar : "Bara de opţiuni",
+DlgLnkPopFullScrn : "Tot ecranul (Full Screen)(IE)",
+DlgLnkPopDependent : "Dependent (Netscape)",
+DlgLnkPopWidth : "Lăţime",
+DlgLnkPopHeight : "Înălţime",
+DlgLnkPopLeft : "Poziţia la stânga",
+DlgLnkPopTop : "Poziţia la dreapta",
+
+DlnLnkMsgNoUrl : "Vă rugăm să scrieţi URL-ul",
+DlnLnkMsgNoEMail : "Vă rugăm să scrieţi adresa de e-mail",
+DlnLnkMsgNoAnchor : "Vă rugăm să selectaţi o ancoră",
+DlnLnkMsgInvPopName : "Numele 'popup'-ului trebuie să înceapă cu un caracter alfabetic şi trebuie să nu conţină spaţii",
+
+// Color Dialog
+DlgColorTitle : "Selectează culoare",
+DlgColorBtnClear : "Curăţă",
+DlgColorHighlight : "Subliniază (Highlight)",
+DlgColorSelected : "Selectat",
+
+// Smiley Dialog
+DlgSmileyTitle : "Inserează o figură expresivă (Emoticon)",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Selectează caracter special",
+
+// Table Dialog
+DlgTableTitle : "Proprietăţile tabelului",
+DlgTableRows : "Linii",
+DlgTableColumns : "Coloane",
+DlgTableBorder : "Mărimea marginii",
+DlgTableAlign : "Aliniament",
+DlgTableAlignNotSet : "<Nesetat>",
+DlgTableAlignLeft : "Stânga",
+DlgTableAlignCenter : "Centru",
+DlgTableAlignRight : "Dreapta",
+DlgTableWidth : "Lăţime",
+DlgTableWidthPx : "pixeli",
+DlgTableWidthPc : "procente",
+DlgTableHeight : "Înălţime",
+DlgTableCellSpace : "Spaţiu între celule",
+DlgTableCellPad : "Spaţiu în cadrul celulei",
+DlgTableCaption : "Titlu (Caption)",
+DlgTableSummary : "Rezumat",
+
+// Table Cell Dialog
+DlgCellTitle : "Proprietăţile celulei",
+DlgCellWidth : "Lăţime",
+DlgCellWidthPx : "pixeli",
+DlgCellWidthPc : "procente",
+DlgCellHeight : "Înălţime",
+DlgCellWordWrap : "Desparte cuvintele (Wrap)",
+DlgCellWordWrapNotSet : "<Nesetat>",
+DlgCellWordWrapYes : "Da",
+DlgCellWordWrapNo : "Nu",
+DlgCellHorAlign : "Aliniament orizontal",
+DlgCellHorAlignNotSet : "<Nesetat>",
+DlgCellHorAlignLeft : "Stânga",
+DlgCellHorAlignCenter : "Centru",
+DlgCellHorAlignRight: "Dreapta",
+DlgCellVerAlign : "Aliniament vertical",
+DlgCellVerAlignNotSet : "<Nesetat>",
+DlgCellVerAlignTop : "Sus",
+DlgCellVerAlignMiddle : "Mijloc",
+DlgCellVerAlignBottom : "Jos",
+DlgCellVerAlignBaseline : "Linia de jos (Baseline)",
+DlgCellRowSpan : "Lungimea în linii (Span)",
+DlgCellCollSpan : "Lungimea în coloane (Span)",
+DlgCellBackColor : "Culoarea fundalului",
+DlgCellBorderColor : "Culoarea marginii",
+DlgCellBtnSelect : "Selectaţi...",
+
+// Find Dialog
+DlgFindTitle : "Găseşte",
+DlgFindFindBtn : "Găseşte",
+DlgFindNotFoundMsg : "Textul specificat nu a fost găsit.",
+
+// Replace Dialog
+DlgReplaceTitle : "Replace",
+DlgReplaceFindLbl : "Găseşte:",
+DlgReplaceReplaceLbl : "Înlocuieşte cu:",
+DlgReplaceCaseChk : "Deosebeşte majuscule de minuscule (Match case)",
+DlgReplaceReplaceBtn : "Înlocuieşte",
+DlgReplaceReplAllBtn : "Înlocuieşte tot",
+DlgReplaceWordChk : "Doar cuvintele întregi",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl+X).",
+PasteErrorCopy : "Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de copiere. Vă rugăm folosiţi tastatura (Ctrl+C).",
+
+PasteAsText : "Adaugă ca text simplu (Plain Text)",
+PasteFromWord : "Adaugă din Word",
+
+DlgPasteMsg2 : "Vă rugăm adăugaţi în căsuţa următoare folosind tastatura (<STRONG>Ctrl+V</STRONG>) şi apăsaţi <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoră definiţiile Font Face",
+DlgPasteRemoveStyles : "Şterge definiţiile stilurilor",
+DlgPasteCleanBox : "Şterge căsuţa",
+
+// Color Picker
+ColorAutomatic : "Automatic",
+ColorMoreColors : "Mai multe culori...",
+
+// Document Properties
+DocProps : "Proprietăţile documentului",
+
+// Anchor Dialog
+DlgAnchorTitle : "Proprietăţile ancorei",
+DlgAnchorName : "Numele ancorei",
+DlgAnchorErrorName : "Vă rugăm scrieţi numele ancorei",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nu e în dicţionar",
+DlgSpellChangeTo : "Schimbă în",
+DlgSpellBtnIgnore : "Ignoră",
+DlgSpellBtnIgnoreAll : "Ignoră toate",
+DlgSpellBtnReplace : "Înlocuieşte",
+DlgSpellBtnReplaceAll : "Înlocuieşte tot",
+DlgSpellBtnUndo : "Starea anterioară (undo)",
+DlgSpellNoSuggestions : "- Fără sugestii -",
+DlgSpellProgress : "Verificarea textului în desfăşurare...",
+DlgSpellNoMispell : "Verificarea textului terminată: Nicio greşeală găsită",
+DlgSpellNoChanges : "Verificarea textului terminată: Niciun cuvânt modificat",
+DlgSpellOneChange : "Verificarea textului terminată: Un cuvânt modificat",
+DlgSpellManyChanges : "Verificarea textului terminată: 1% cuvinte modificate",
+
+IeSpellDownload : "Unealta pentru verificat textul (Spell checker) neinstalată. Doriţi să o descărcaţi acum?",
+
+// Button Dialog
+DlgButtonText : "Text (Valoare)",
+DlgButtonType : "Tip",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Nume",
+DlgCheckboxValue : "Valoare",
+DlgCheckboxSelected : "Selectat",
+
+// Form Dialog
+DlgFormName : "Nume",
+DlgFormAction : "Acţiune",
+DlgFormMethod : "Metodă",
+
+// Select Field Dialog
+DlgSelectName : "Nume",
+DlgSelectValue : "Valoare",
+DlgSelectSize : "Mărime",
+DlgSelectLines : "linii",
+DlgSelectChkMulti : "Permite selecţii multiple",
+DlgSelectOpAvail : "Opţiuni disponibile",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Valoare",
+DlgSelectBtnAdd : "Adaugă",
+DlgSelectBtnModify : "Modifică",
+DlgSelectBtnUp : "Sus",
+DlgSelectBtnDown : "Jos",
+DlgSelectBtnSetValue : "Setează ca valoare selectată",
+DlgSelectBtnDelete : "Şterge",
+
+// Textarea Dialog
+DlgTextareaName : "Nume",
+DlgTextareaCols : "Coloane",
+DlgTextareaRows : "Linii",
+
+// Text Field Dialog
+DlgTextName : "Nume",
+DlgTextValue : "Valoare",
+DlgTextCharWidth : "Lărgimea caracterului",
+DlgTextMaxChars : "Caractere maxime",
+DlgTextType : "Tip",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Parolă",
+
+// Hidden Field Dialog
+DlgHiddenName : "Nume",
+DlgHiddenValue : "Valoare",
+
+// Bulleted List Dialog
+BulletedListProp : "Proprietăţile listei punctate (Bulleted List)",
+NumberedListProp : "Proprietăţile listei numerotate (Numbered List)",
+DlgLstStart : "Start",
+DlgLstType : "Tip",
+DlgLstTypeCircle : "Cerc",
+DlgLstTypeDisc : "Disc",
+DlgLstTypeSquare : "Pătrat",
+DlgLstTypeNumbers : "Numere (1, 2, 3)",
+DlgLstTypeLCase : "Minuscule-litere mici (a, b, c)",
+DlgLstTypeUCase : "Majuscule (A, B, C)",
+DlgLstTypeSRoman : "Cifre romane mici (i, ii, iii)",
+DlgLstTypeLRoman : "Cifre romane mari (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "General",
+DlgDocBackTab : "Fundal",
+DlgDocColorsTab : "Culori si margini",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Titlul paginii",
+DlgDocLangDir : "Descrierea limbii",
+DlgDocLangDirLTR : "stânga-dreapta (LTR)",
+DlgDocLangDirRTL : "dreapta-stânga (RTL)",
+DlgDocLangCode : "Codul limbii",
+DlgDocCharSet : "Encoding setului de caractere",
+DlgDocCharSetCE : "Central european",
+DlgDocCharSetCT : "Chinezesc tradiţional (Big5)",
+DlgDocCharSetCR : "Chirilic",
+DlgDocCharSetGR : "Grecesc",
+DlgDocCharSetJP : "Japonez",
+DlgDocCharSetKR : "Corean",
+DlgDocCharSetTR : "Turcesc",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Vest european",
+DlgDocCharSetOther : "Alt encoding al setului de caractere",
+
+DlgDocDocType : "Document Type Heading",
+DlgDocDocTypeOther : "Alt Document Type Heading",
+DlgDocIncXHTML : "Include declaraţii XHTML",
+DlgDocBgColor : "Culoarea fundalului (Background Color)",
+DlgDocBgImage : "URL-ul imaginii din fundal (Background Image URL)",
+DlgDocBgNoScroll : "Fundal neflotant, fix (Nonscrolling Background)",
+DlgDocCText : "Text",
+DlgDocCLink : "Link (Legătură web)",
+DlgDocCVisited : "Link (Legătură web) vizitat",
+DlgDocCActive : "Link (Legătură web) activ",
+DlgDocMargins : "Marginile paginii",
+DlgDocMaTop : "Sus",
+DlgDocMaLeft : "Stânga",
+DlgDocMaRight : "Dreapta",
+DlgDocMaBottom : "Jos",
+DlgDocMeIndex : "Cuvinte cheie după care se va indexa documentul (separate prin virgulă)",
+DlgDocMeDescr : "Descrierea documentului",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Drepturi de autor",
+DlgDocPreview : "Previzualizare",
+
+// Templates Dialog
+Templates : "Template-uri (şabloane)",
+DlgTemplatesTitle : "Template-uri (şabloane) de conţinut",
+DlgTemplatesSelMsg : "Vă rugăm selectaţi template-ul (şablonul) ce se va deschide în editor<br>(conţinutul actual va fi pierdut):",
+DlgTemplatesLoading : "Se încarcă lista cu template-uri (şabloane). Vă rugăm aşteptaţi...",
+DlgTemplatesNoTpl : "(Niciun template (şablon) definit)",
+DlgTemplatesReplace : "Înlocuieşte cuprinsul actual",
+
+// About Dialog
+DlgAboutAboutTab : "Despre",
+DlgAboutBrowserInfoTab : "Informaţii browser",
+DlgAboutLicenseTab : "Licenţă",
+DlgAboutVersion : "versiune",
+DlgAboutInfo : "Pentru informaţii amănunţite, vizitaţi"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/ru.js b/httemplate/elements/fckeditor/editor/lang/ru.js
new file mode 100644
index 000000000..fdf151b90
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/ru.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Russian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Свернуть панель инструментов",
+ToolbarExpand : "Развернуть панель инструментов",
+
+// Toolbar Items and Context Menu
+Save : "Сохранить",
+NewPage : "Новая страница",
+Preview : "Предварительный просмотр",
+Cut : "Вырезать",
+Copy : "Копировать",
+Paste : "Вставить",
+PasteText : "Вставить только текст",
+PasteWord : "Вставить из Word",
+Print : "Печать",
+SelectAll : "Выделить все",
+RemoveFormat : "Убрать форматирование",
+InsertLinkLbl : "Ссылка",
+InsertLink : "Вставить/Редактировать ссылку",
+RemoveLink : "Убрать ссылку",
+Anchor : "Вставить/Редактировать якорь",
+InsertImageLbl : "Изображение",
+InsertImage : "Вставить/Редактировать изображение",
+InsertFlashLbl : "Flash",
+InsertFlash : "Вставить/Редактировать Flash",
+InsertTableLbl : "Таблица",
+InsertTable : "Вставить/Редактировать таблицу",
+InsertLineLbl : "Линия",
+InsertLine : "Вставить горизонтальную линию",
+InsertSpecialCharLbl: "Специальный символ",
+InsertSpecialChar : "Вставить специальный символ",
+InsertSmileyLbl : "Смайлик",
+InsertSmiley : "Вставить смайлик",
+About : "О FCKeditor",
+Bold : "Жирный",
+Italic : "Курсив",
+Underline : "Подчеркнутый",
+StrikeThrough : "Зачеркнутый",
+Subscript : "Подстрочный индекс",
+Superscript : "Надстрочный индекс",
+LeftJustify : "По левому краю",
+CenterJustify : "По центру",
+RightJustify : "По правому краю",
+BlockJustify : "По ширине",
+DecreaseIndent : "Уменьшить отступ",
+IncreaseIndent : "Увеличить отступ",
+Undo : "Отменить",
+Redo : "Повторить",
+NumberedListLbl : "Нумерованный список",
+NumberedList : "Вставить/Удалить нумерованный список",
+BulletedListLbl : "Маркированный список",
+BulletedList : "Вставить/Удалить маркированный список",
+ShowTableBorders : "Показать бордюры таблицы",
+ShowDetails : "Показать детали",
+Style : "Стиль",
+FontFormat : "Форматирование",
+Font : "Шрифт",
+FontSize : "Размер",
+TextColor : "Цвет текста",
+BGColor : "Цвет фона",
+Source : "Источник",
+Find : "Найти",
+Replace : "Заменить",
+SpellCheck : "Проверить орфографию",
+UniversalKeyboard : "Универсальная клавиатура",
+PageBreakLbl : "Разрыв страницы",
+PageBreak : "Вставить разрыв страницы",
+
+Form : "Форма",
+Checkbox : "Флаговая кнопка",
+RadioButton : "Кнопка выбора",
+TextField : "Текстовое поле",
+Textarea : "Текстовая область",
+HiddenField : "Скрытое поле",
+Button : "Кнопка",
+SelectionField : "Список",
+ImageButton : "Кнопка с изображением",
+
+FitWindow : "Развернуть окно редактора",
+
+// Context Menu
+EditLink : "Вставить ссылку",
+CellCM : "Ячейка",
+RowCM : "Строка",
+ColumnCM : "Колонка",
+InsertRow : "Вставить строку",
+DeleteRows : "Удалить строки",
+InsertColumn : "Вставить колонку",
+DeleteColumns : "Удалить колонки",
+InsertCell : "Вставить ячейку",
+DeleteCells : "Удалить ячейки",
+MergeCells : "Соединить ячейки",
+SplitCell : "Разбить ячейку",
+TableDelete : "Удалить таблицу",
+CellProperties : "Свойства ячейки",
+TableProperties : "Свойства таблицы",
+ImageProperties : "Свойства изображения",
+FlashProperties : "Свойства Flash",
+
+AnchorProp : "Свойства якоря",
+ButtonProp : "Свойства кнопки",
+CheckboxProp : "Свойства флаговой кнопки",
+HiddenFieldProp : "Свойства скрытого поля",
+RadioButtonProp : "Свойства кнопки выбора",
+ImageButtonProp : "Свойства кнопки с изображением",
+TextFieldProp : "Свойства текстового поля",
+SelectionFieldProp : "Свойства списка",
+TextareaProp : "Свойства текстовой области",
+FormProp : "Свойства формы",
+
+FontFormats : "Нормальный;Форматированный;Адрес;Заголовок 1;Заголовок 2;Заголовок 3;Заголовок 4;Заголовок 5;Заголовок 6;Нормальный (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Обработка XHTML. Пожалуйста подождите...",
+Done : "Сделано",
+PasteWordConfirm : "Текст, который вы хотите вставить, похож на копируемый из Word. Вы хотите очистить его перед вставкой?",
+NotCompatiblePaste : "Эта команда доступна для Internet Explorer версии 5.5 или выше. Вы хотите вставить без очистки?",
+UnknownToolbarItem : "Не известный элемент панели инструментов \"%1\"",
+UnknownCommand : "Не известное имя команды \"%1\"",
+NotImplemented : "Команда не реализована",
+UnknownToolbarSet : "Панель инструментов \"%1\" не существует",
+NoActiveX : "Настройки безопасности вашего браузера могут ограничивать некоторые свойства редактора. Вы должны включить опцию \"Запускать элементы управления ActiveX и плугины\". Вы можете видеть ошибки и замечать отсутствие возможностей.",
+BrowseServerBlocked : "Ресурсы браузера не могут быть открыты. Проверьте что блокировки всплывающих окон выключены.",
+DialogBlocked : "Не возможно открыть окно диалога. Проверьте что блокировки всплывающих окон выключены.",
+
+// Dialogs
+DlgBtnOK : "ОК",
+DlgBtnCancel : "Отмена",
+DlgBtnClose : "Закрыть",
+DlgBtnBrowseServer : "Просмотреть на сервере",
+DlgAdvancedTag : "Расширенный",
+DlgOpOther : "<Другое>",
+DlgInfoTab : "Информация",
+DlgAlertUrl : "Пожалуйста вставьте URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<не определено>",
+DlgGenId : "Идентификатор",
+DlgGenLangDir : "Направление языка",
+DlgGenLangDirLtr : "Слева на право (LTR)",
+DlgGenLangDirRtl : "Справа на лево (RTL)",
+DlgGenLangCode : "Язык",
+DlgGenAccessKey : "Горячая клавиша",
+DlgGenName : "Имя",
+DlgGenTabIndex : "Последовательность перехода",
+DlgGenLongDescr : "Длинное описание URL",
+DlgGenClass : "Класс CSS",
+DlgGenTitle : "Заголовок",
+DlgGenContType : "Тип содержимого",
+DlgGenLinkCharset : "Кодировка",
+DlgGenStyle : "Стиль CSS",
+
+// Image Dialog
+DlgImgTitle : "Свойства изображения",
+DlgImgInfoTab : "Информация о изображении",
+DlgImgBtnUpload : "Послать на сервер",
+DlgImgURL : "URL",
+DlgImgUpload : "Закачать",
+DlgImgAlt : "Альтернативный текст",
+DlgImgWidth : "Ширина",
+DlgImgHeight : "Высота",
+DlgImgLockRatio : "Сохранять пропорции",
+DlgBtnResetSize : "Сбросить размер",
+DlgImgBorder : "Бордюр",
+DlgImgHSpace : "Горизонтальный отступ",
+DlgImgVSpace : "Вертикальный отступ",
+DlgImgAlign : "Выравнивание",
+DlgImgAlignLeft : "По левому краю",
+DlgImgAlignAbsBottom: "Абс понизу",
+DlgImgAlignAbsMiddle: "Абс посередине",
+DlgImgAlignBaseline : "По базовой линии",
+DlgImgAlignBottom : "Понизу",
+DlgImgAlignMiddle : "Посередине",
+DlgImgAlignRight : "По правому краю",
+DlgImgAlignTextTop : "Текст наверху",
+DlgImgAlignTop : "По верху",
+DlgImgPreview : "Предварительный просмотр",
+DlgImgAlertUrl : "Пожалуйста введите URL изображения",
+DlgImgLinkTab : "Ссылка",
+
+// Flash Dialog
+DlgFlashTitle : "Свойства Flash",
+DlgFlashChkPlay : "Авто проигрывание",
+DlgFlashChkLoop : "Повтор",
+DlgFlashChkMenu : "Включить меню Flash",
+DlgFlashScale : "Масштабировать",
+DlgFlashScaleAll : "Показывать все",
+DlgFlashScaleNoBorder : "Без бордюра",
+DlgFlashScaleFit : "Точное совпадение",
+
+// Link Dialog
+DlgLnkWindowTitle : "Ссылка",
+DlgLnkInfoTab : "Информация ссылки",
+DlgLnkTargetTab : "Цель",
+
+DlgLnkType : "Тип ссылки",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Якорь на эту страницу",
+DlgLnkTypeEMail : "Эл. почта",
+DlgLnkProto : "Протокол",
+DlgLnkProtoOther : "<другое>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Выберите якорь",
+DlgLnkAnchorByName : "По имени якоря",
+DlgLnkAnchorById : "По идентификатору элемента",
+DlgLnkNoAnchors : "<Нет якорей доступных в этом документе>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Адрес эл. почты",
+DlgLnkEMailSubject : "Заголовок сообщения",
+DlgLnkEMailBody : "Тело сообщения",
+DlgLnkUpload : "Закачать",
+DlgLnkBtnUpload : "Послать на сервер",
+
+DlgLnkTarget : "Цель",
+DlgLnkTargetFrame : "<фрейм>",
+DlgLnkTargetPopup : "<всплывающее окно>",
+DlgLnkTargetBlank : "Новое окно (_blank)",
+DlgLnkTargetParent : "Родительское окно (_parent)",
+DlgLnkTargetSelf : "Тоже окно (_self)",
+DlgLnkTargetTop : "Самое верхнее окно (_top)",
+DlgLnkTargetFrameName : "Имя целевого фрейма",
+DlgLnkPopWinName : "Имя всплывающего окна",
+DlgLnkPopWinFeat : "Свойства всплывающего окна",
+DlgLnkPopResize : "Изменяющееся в размерах",
+DlgLnkPopLocation : "Панель локации",
+DlgLnkPopMenu : "Панель меню",
+DlgLnkPopScroll : "Полосы прокрутки",
+DlgLnkPopStatus : "Строка состояния",
+DlgLnkPopToolbar : "Панель инструментов",
+DlgLnkPopFullScrn : "Полный экран (IE)",
+DlgLnkPopDependent : "Зависимый (Netscape)",
+DlgLnkPopWidth : "Ширина",
+DlgLnkPopHeight : "Высота",
+DlgLnkPopLeft : "Позиция слева",
+DlgLnkPopTop : "Позиция сверху",
+
+DlnLnkMsgNoUrl : "Пожалуйста введите URL ссылки",
+DlnLnkMsgNoEMail : "Пожалуйста введите адрес эл. почты",
+DlnLnkMsgNoAnchor : "Пожалуйста выберете якорь",
+DlnLnkMsgInvPopName : "Название вспывающего окна должно начинаться буквы и не может содержать пробелов",
+
+// Color Dialog
+DlgColorTitle : "Выберите цвет",
+DlgColorBtnClear : "Очистить",
+DlgColorHighlight : "Подсвеченный",
+DlgColorSelected : "Выбранный",
+
+// Smiley Dialog
+DlgSmileyTitle : "Вставить смайлик",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Выберите специальный символ",
+
+// Table Dialog
+DlgTableTitle : "Свойства таблицы",
+DlgTableRows : "Строки",
+DlgTableColumns : "Колонки",
+DlgTableBorder : "Размер бордюра",
+DlgTableAlign : "Выравнивание",
+DlgTableAlignNotSet : "<Не уст.>",
+DlgTableAlignLeft : "Слева",
+DlgTableAlignCenter : "По центру",
+DlgTableAlignRight : "Справа",
+DlgTableWidth : "Ширина",
+DlgTableWidthPx : "пикселей",
+DlgTableWidthPc : "процентов",
+DlgTableHeight : "Высота",
+DlgTableCellSpace : "Промежуток (spacing)",
+DlgTableCellPad : "Отступ (padding)",
+DlgTableCaption : "Заголовок",
+DlgTableSummary : "Резюме",
+
+// Table Cell Dialog
+DlgCellTitle : "Свойства ячейки",
+DlgCellWidth : "Ширина",
+DlgCellWidthPx : "пикселей",
+DlgCellWidthPc : "процентов",
+DlgCellHeight : "Высота",
+DlgCellWordWrap : "Заворачивание текста",
+DlgCellWordWrapNotSet : "<Не уст.>",
+DlgCellWordWrapYes : "Да",
+DlgCellWordWrapNo : "Нет",
+DlgCellHorAlign : "Гор. выравнивание",
+DlgCellHorAlignNotSet : "<Не уст.>",
+DlgCellHorAlignLeft : "Слева",
+DlgCellHorAlignCenter : "По центру",
+DlgCellHorAlignRight: "Справа",
+DlgCellVerAlign : "Верт. выравнивание",
+DlgCellVerAlignNotSet : "<Не уст.>",
+DlgCellVerAlignTop : "Сверху",
+DlgCellVerAlignMiddle : "Посередине",
+DlgCellVerAlignBottom : "Снизу",
+DlgCellVerAlignBaseline : "По базовой линии",
+DlgCellRowSpan : "Диапазон строк (span)",
+DlgCellCollSpan : "Диапазон колонок (span)",
+DlgCellBackColor : "Цвет фона",
+DlgCellBorderColor : "Цвет бордюра",
+DlgCellBtnSelect : "Выберите...",
+
+// Find Dialog
+DlgFindTitle : "Найти",
+DlgFindFindBtn : "Найти",
+DlgFindNotFoundMsg : "Указанный текст не найден.",
+
+// Replace Dialog
+DlgReplaceTitle : "Заменить",
+DlgReplaceFindLbl : "Найти:",
+DlgReplaceReplaceLbl : "Заменить на:",
+DlgReplaceCaseChk : "Учитывать регистр",
+DlgReplaceReplaceBtn : "Заменить",
+DlgReplaceReplAllBtn : "Заменить все",
+DlgReplaceWordChk : "Совпадение целых слов",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Настройки безопасности вашего браузера не позволяют редактору автоматически выполнять операции вырезания. Пожалуйста используйте клавиатуру для этого (Ctrl+X).",
+PasteErrorCopy : "Настройки безопасности вашего браузера не позволяют редактору автоматически выполнять операции копирования. Пожалуйста используйте клавиатуру для этого (Ctrl+C).",
+
+PasteAsText : "Вставить только текст",
+PasteFromWord : "Вставить из Word",
+
+DlgPasteMsg2 : "Пожалуйста вставьте текст в прямоугольник используя сочетание клавиш (<STRONG>Ctrl+V</STRONG>) и нажмите <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Игнорировать определения гарнитуры",
+DlgPasteRemoveStyles : "Убрать определения стилей",
+DlgPasteCleanBox : "Очистить",
+
+// Color Picker
+ColorAutomatic : "Автоматический",
+ColorMoreColors : "Цвета...",
+
+// Document Properties
+DocProps : "Свойства документа",
+
+// Anchor Dialog
+DlgAnchorTitle : "Свойства якоря",
+DlgAnchorName : "Имя якоря",
+DlgAnchorErrorName : "Пожалуйста введите имя якоря",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Нет в словаре",
+DlgSpellChangeTo : "Заменить на",
+DlgSpellBtnIgnore : "Игнорировать",
+DlgSpellBtnIgnoreAll : "Игнорировать все",
+DlgSpellBtnReplace : "Заменить",
+DlgSpellBtnReplaceAll : "Заменить все",
+DlgSpellBtnUndo : "Отменить",
+DlgSpellNoSuggestions : "- Нет предположений -",
+DlgSpellProgress : "Идет проверка орфографии...",
+DlgSpellNoMispell : "Проверка орфографии закончена: ошибок не найдено",
+DlgSpellNoChanges : "Проверка орфографии закончена: ни одного слова не изменено",
+DlgSpellOneChange : "Проверка орфографии закончена: одно слово изменено",
+DlgSpellManyChanges : "Проверка орфографии закончена: 1% слов изменен",
+
+IeSpellDownload : "Модуль проверки орфографии не установлен. Хотите скачать его сейчас?",
+
+// Button Dialog
+DlgButtonText : "Текст (Значение)",
+DlgButtonType : "Тип",
+DlgButtonTypeBtn : "Кнопка",
+DlgButtonTypeSbm : "Отправить",
+DlgButtonTypeRst : "Сбросить",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Имя",
+DlgCheckboxValue : "Значение",
+DlgCheckboxSelected : "Выбранная",
+
+// Form Dialog
+DlgFormName : "Имя",
+DlgFormAction : "Действие",
+DlgFormMethod : "Метод",
+
+// Select Field Dialog
+DlgSelectName : "Имя",
+DlgSelectValue : "Значение",
+DlgSelectSize : "Размер",
+DlgSelectLines : "линии",
+DlgSelectChkMulti : "Разрешить множественный выбор",
+DlgSelectOpAvail : "Доступные варианты",
+DlgSelectOpText : "Текст",
+DlgSelectOpValue : "Значение",
+DlgSelectBtnAdd : "Добавить",
+DlgSelectBtnModify : "Модифицировать",
+DlgSelectBtnUp : "Вверх",
+DlgSelectBtnDown : "Вниз",
+DlgSelectBtnSetValue : "Установить как выбранное значение",
+DlgSelectBtnDelete : "Удалить",
+
+// Textarea Dialog
+DlgTextareaName : "Имя",
+DlgTextareaCols : "Колонки",
+DlgTextareaRows : "Строки",
+
+// Text Field Dialog
+DlgTextName : "Имя",
+DlgTextValue : "Значение",
+DlgTextCharWidth : "Ширина",
+DlgTextMaxChars : "Макс. кол-во символов",
+DlgTextType : "Тип",
+DlgTextTypeText : "Текст",
+DlgTextTypePass : "Пароль",
+
+// Hidden Field Dialog
+DlgHiddenName : "Имя",
+DlgHiddenValue : "Значение",
+
+// Bulleted List Dialog
+BulletedListProp : "Свойства маркированного списка",
+NumberedListProp : "Свойства нумерованного списка",
+DlgLstStart : "Начало",
+DlgLstType : "Тип",
+DlgLstTypeCircle : "Круг",
+DlgLstTypeDisc : "Диск",
+DlgLstTypeSquare : "Квадрат",
+DlgLstTypeNumbers : "Номера (1, 2, 3)",
+DlgLstTypeLCase : "Буквы нижнего регистра (a, b, c)",
+DlgLstTypeUCase : "Буквы верхнего регистра (A, B, C)",
+DlgLstTypeSRoman : "Малые римские буквы (i, ii, iii)",
+DlgLstTypeLRoman : "Большие римские буквы (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Общие",
+DlgDocBackTab : "Задний фон",
+DlgDocColorsTab : "Цвета и отступы",
+DlgDocMetaTab : "Мета данные",
+
+DlgDocPageTitle : "Заголовок страницы",
+DlgDocLangDir : "Направление текста",
+DlgDocLangDirLTR : "Слева на право (LTR)",
+DlgDocLangDirRTL : "Справа на лево (RTL)",
+DlgDocLangCode : "Код языка",
+DlgDocCharSet : "Кодировка набора символов",
+DlgDocCharSetCE : "Центрально-европейская",
+DlgDocCharSetCT : "Китайская традиционная (Big5)",
+DlgDocCharSetCR : "Кириллица",
+DlgDocCharSetGR : "Греческая",
+DlgDocCharSetJP : "Японская",
+DlgDocCharSetKR : "Корейская",
+DlgDocCharSetTR : "Турецкая",
+DlgDocCharSetUN : "Юникод (UTF-8)",
+DlgDocCharSetWE : "Западно-европейская",
+DlgDocCharSetOther : "Другая кодировка набора символов",
+
+DlgDocDocType : "Заголовок типа документа",
+DlgDocDocTypeOther : "Другой заголовок типа документа",
+DlgDocIncXHTML : "Включить XHTML объявления",
+DlgDocBgColor : "Цвет фона",
+DlgDocBgImage : "URL изображения фона",
+DlgDocBgNoScroll : "Нескроллируемый фон",
+DlgDocCText : "Текст",
+DlgDocCLink : "Ссылка",
+DlgDocCVisited : "Посещенная ссылка",
+DlgDocCActive : "Активная ссылка",
+DlgDocMargins : "Отступы страницы",
+DlgDocMaTop : "Верхний",
+DlgDocMaLeft : "Левый",
+DlgDocMaRight : "Правый",
+DlgDocMaBottom : "Нижний",
+DlgDocMeIndex : "Ключевые слова документа (разделенные запятой)",
+DlgDocMeDescr : "Описание документа",
+DlgDocMeAuthor : "Автор",
+DlgDocMeCopy : "Авторские права",
+DlgDocPreview : "Предварительный просмотр",
+
+// Templates Dialog
+Templates : "Шаблоны",
+DlgTemplatesTitle : "Шаблоны содержимого",
+DlgTemplatesSelMsg : "Пожалуйста выберете шаблон для открытия в редакторе<br>(текущее содержимое будет потеряно):",
+DlgTemplatesLoading : "Загрузка списка шаблонов. Пожалуйста подождите...",
+DlgTemplatesNoTpl : "(Ни одного шаблона не определено)",
+DlgTemplatesReplace : "Заменить текущее содержание",
+
+// About Dialog
+DlgAboutAboutTab : "О программе",
+DlgAboutBrowserInfoTab : "Информация браузера",
+DlgAboutLicenseTab : "Лицензия",
+DlgAboutVersion : "Версия",
+DlgAboutInfo : "Для большей информации, посетите"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/sk.js b/httemplate/elements/fckeditor/editor/lang/sk.js
new file mode 100644
index 000000000..83d00bac3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/sk.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Slovak language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Skryť panel nástrojov",
+ToolbarExpand : "Zobraziť panel nástrojov",
+
+// Toolbar Items and Context Menu
+Save : "Uložit",
+NewPage : "Nová stránka",
+Preview : "Náhľad",
+Cut : "Vystrihnúť",
+Copy : "Kopírovať",
+Paste : "Vložiť",
+PasteText : "Vložiť ako čistý text",
+PasteWord : "Vložiť z Wordu",
+Print : "Tlač",
+SelectAll : "Vybrať všetko",
+RemoveFormat : "Odstrániť formátovanie",
+InsertLinkLbl : "Odkaz",
+InsertLink : "Vložiť/zmeniť odkaz",
+RemoveLink : "Odstrániť odkaz",
+Anchor : "Vložiť/zmeniť kotvu",
+InsertImageLbl : "Obrázok",
+InsertImage : "Vložiť/zmeniť obrázok",
+InsertFlashLbl : "Flash",
+InsertFlash : "Vložiť/zmeniť Flash",
+InsertTableLbl : "Tabuľka",
+InsertTable : "Vložiť/zmeniť tabuľku",
+InsertLineLbl : "Čiara",
+InsertLine : "Vložiť vodorovnú čiaru",
+InsertSpecialCharLbl: "Špeciálne znaky",
+InsertSpecialChar : "Vložiť špeciálne znaky",
+InsertSmileyLbl : "Smajlíky",
+InsertSmiley : "Vložiť smajlíka",
+About : "O aplikáci FCKeditor",
+Bold : "Tučné",
+Italic : "Kurzíva",
+Underline : "Podčiarknuté",
+StrikeThrough : "Prečiarknuté",
+Subscript : "Dolný index",
+Superscript : "Horný index",
+LeftJustify : "Zarovnať vľavo",
+CenterJustify : "Zarovnať na stred",
+RightJustify : "Zarovnať vpravo",
+BlockJustify : "Zarovnať do bloku",
+DecreaseIndent : "Zmenšiť odsadenie",
+IncreaseIndent : "Zväčšiť odsadenie",
+Undo : "Späť",
+Redo : "Znovu",
+NumberedListLbl : "Číslovanie",
+NumberedList : "Vložiť/odstrániť číslovaný zoznam",
+BulletedListLbl : "Odrážky",
+BulletedList : "Vložiť/odstraniť odrážky",
+ShowTableBorders : "Zobraziť okraje tabuliek",
+ShowDetails : "Zobraziť podrobnosti",
+Style : "Štýl",
+FontFormat : "Formát",
+Font : "Písmo",
+FontSize : "Veľkosť",
+TextColor : "Farba textu",
+BGColor : "Farba pozadia",
+Source : "Zdroj",
+Find : "Hľadať",
+Replace : "Nahradiť",
+SpellCheck : "Kontrola pravopisu",
+UniversalKeyboard : "Univerzálna klávesnica",
+PageBreakLbl : "Oddeľovač stránky",
+PageBreak : "Vložiť oddeľovač stránky",
+
+Form : "Formulár",
+Checkbox : "Zaškrtávacie políčko",
+RadioButton : "Prepínač",
+TextField : "Textové pole",
+Textarea : "Textová oblasť",
+HiddenField : "Skryté pole",
+Button : "Tlačíidlo",
+SelectionField : "Rozbaľovací zoznam",
+ImageButton : "Obrázkové tlačidlo",
+
+FitWindow : "Maximalizovať veľkosť okna editora",
+
+// Context Menu
+EditLink : "Zmeniť odkaz",
+CellCM : "Bunka",
+RowCM : "Riadok",
+ColumnCM : "Stĺpec",
+InsertRow : "Vložiť riadok",
+DeleteRows : "Vymazať riadok",
+InsertColumn : "Vložiť stĺpec",
+DeleteColumns : "Zmazať stĺpec",
+InsertCell : "Vložiť bunku",
+DeleteCells : "Vymazať bunky",
+MergeCells : "Zlúčiť bunky",
+SplitCell : "Rozdeliť bunku",
+TableDelete : "Vymazať tabuľku",
+CellProperties : "Vlastnosti bunky",
+TableProperties : "Vlastnosti tabuľky",
+ImageProperties : "Vlastnosti obrázku",
+FlashProperties : "Vlastnosti Flashu",
+
+AnchorProp : "Vlastnosti kotvy",
+ButtonProp : "Vlastnosti tlačidla",
+CheckboxProp : "Vlastnosti zaškrtávacieho políčka",
+HiddenFieldProp : "Vlastnosti skrytého poľa",
+RadioButtonProp : "Vlastnosti prepínača",
+ImageButtonProp : "Vlastnosti obrázkového tlačidla",
+TextFieldProp : "Vlastnosti textového poľa",
+SelectionFieldProp : "Vlastnosti rozbaľovacieho zoznamu",
+TextareaProp : "Vlastnosti textovej oblasti",
+FormProp : "Vlastnosti formulára",
+
+FontFormats : "Normálny;Formátovaný;Adresa;Nadpis 1;Nadpis 2;Nadpis 3;Nadpis 4;Nadpis 5;Nadpis 6;Odsek (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Prebieha spracovanie XHTML. Čakajte prosím...",
+Done : "Dokončené.",
+PasteWordConfirm : "Vyzerá to tak, že vkladaný text je kopírovaný z Wordu. Chcete ho pred vložením vyčistiť?",
+NotCompatiblePaste : "Tento príkaz je dostupný len v prehliadači Internet Explorer verzie 5.5 alebo vyššej. Chcete vložiť text bez vyčistenia?",
+UnknownToolbarItem : "Neznáma položka panela nástrojov \"%1\"",
+UnknownCommand : "Neznámy príkaz \"%1\"",
+NotImplemented : "Príkaz nie je implementovaný",
+UnknownToolbarSet : "Panel nástrojov \"%1\" neexistuje",
+NoActiveX : "Bezpečnostné nastavenia vášho prehliadača môžu obmedzovať niektoré funkcie editora. Pre ich plnú funkčnosť musíte zapnúť voľbu \"Spúšťať ActiveX moduly a zásuvné moduly\", inak sa môžete stretnúť s chybami a nefunkčnosťou niektorých funkcií.",
+BrowseServerBlocked : "Prehliadač zdrojových prvkov nebolo možné otvoriť. Uistite sa, že máte vypnuté všetky blokovače vyskakujúcich okien.",
+DialogBlocked : "Dialógové okno nebolo možné otvoriť. Uistite sa, že máte vypnuté všetky blokovače vyskakujúcich okien.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Zrušiť",
+DlgBtnClose : "Zavrieť",
+DlgBtnBrowseServer : "Prechádzať server",
+DlgAdvancedTag : "Rozšírené",
+DlgOpOther : "<Ďalšie>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Prosím vložte URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nenastavené>",
+DlgGenId : "Id",
+DlgGenLangDir : "Orientácia jazyka",
+DlgGenLangDirLtr : "Zľava doprava (LTR)",
+DlgGenLangDirRtl : "Sprava doľava (RTL)",
+DlgGenLangCode : "Kód jazyka",
+DlgGenAccessKey : "Prístupový kľúč",
+DlgGenName : "Meno",
+DlgGenTabIndex : "Poradie prvku",
+DlgGenLongDescr : "Dlhý popis URL",
+DlgGenClass : "Trieda štýlu",
+DlgGenTitle : "Pomocný titulok",
+DlgGenContType : "Pomocný typ obsahu",
+DlgGenLinkCharset : "Priradená znaková sada",
+DlgGenStyle : "Štýl",
+
+// Image Dialog
+DlgImgTitle : "Vlastnosti obrázku",
+DlgImgInfoTab : "Informácie o obrázku",
+DlgImgBtnUpload : "Odoslať na server",
+DlgImgURL : "URL",
+DlgImgUpload : "Odoslať",
+DlgImgAlt : "Alternatívny text",
+DlgImgWidth : "Šírka",
+DlgImgHeight : "Výška",
+DlgImgLockRatio : "Zámok",
+DlgBtnResetSize : "Pôvodná veľkosť",
+DlgImgBorder : "Okraje",
+DlgImgHSpace : "H-medzera",
+DlgImgVSpace : "V-medzera",
+DlgImgAlign : "Zarovnanie",
+DlgImgAlignLeft : "Vľavo",
+DlgImgAlignAbsBottom: "Úplne dole",
+DlgImgAlignAbsMiddle: "Do stredu",
+DlgImgAlignBaseline : "Na základňu",
+DlgImgAlignBottom : "Dole",
+DlgImgAlignMiddle : "Na stred",
+DlgImgAlignRight : "Vpravo",
+DlgImgAlignTextTop : "Na horný okraj textu",
+DlgImgAlignTop : "Nahor",
+DlgImgPreview : "Náhľad",
+DlgImgAlertUrl : "Zadajte prosím URL obrázku",
+DlgImgLinkTab : "Odkaz",
+
+// Flash Dialog
+DlgFlashTitle : "Vlastnosti Flashu",
+DlgFlashChkPlay : "Automatické prehrávanie",
+DlgFlashChkLoop : "Opakovanie",
+DlgFlashChkMenu : "Povoliť Flash Menu",
+DlgFlashScale : "Mierka",
+DlgFlashScaleAll : "Zobraziť mierku",
+DlgFlashScaleNoBorder : "Bez okrajov",
+DlgFlashScaleFit : "Roztiahnuť na celé",
+
+// Link Dialog
+DlgLnkWindowTitle : "Odkaz",
+DlgLnkInfoTab : "Informácie o odkaze",
+DlgLnkTargetTab : "Cieľ",
+
+DlgLnkType : "Typ odkazu",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Kotva v tejto stránke",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<iný>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Vybrať kotvu",
+DlgLnkAnchorByName : "Podľa mena kotvy",
+DlgLnkAnchorById : "Podľa Id objektu",
+DlgLnkNoAnchors : "<V stránke nie je definovaná žiadna kotva>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mailová adresa",
+DlgLnkEMailSubject : "Predmet správy",
+DlgLnkEMailBody : "Telo správy",
+DlgLnkUpload : "Odoslať",
+DlgLnkBtnUpload : "Odoslať na server",
+
+DlgLnkTarget : "Cieľ",
+DlgLnkTargetFrame : "<rámec>",
+DlgLnkTargetPopup : "<vyskakovacie okno>",
+DlgLnkTargetBlank : "Nové okno (_blank)",
+DlgLnkTargetParent : "Rodičovské okno (_parent)",
+DlgLnkTargetSelf : "Rovnaké okno (_self)",
+DlgLnkTargetTop : "Hlavné okno (_top)",
+DlgLnkTargetFrameName : "Meno rámu cieľa",
+DlgLnkPopWinName : "Názov vyskakovacieho okna",
+DlgLnkPopWinFeat : "Vlastnosti vyskakovacieho okna",
+DlgLnkPopResize : "Meniteľná veľkosť",
+DlgLnkPopLocation : "Panel umiestnenia",
+DlgLnkPopMenu : "Panel ponuky",
+DlgLnkPopScroll : "Posuvníky",
+DlgLnkPopStatus : "Stavový riadok",
+DlgLnkPopToolbar : "Panel nástrojov",
+DlgLnkPopFullScrn : "Celá obrazovka (IE)",
+DlgLnkPopDependent : "Závislosť (Netscape)",
+DlgLnkPopWidth : "Šírka",
+DlgLnkPopHeight : "Výška",
+DlgLnkPopLeft : "Ľavý okraj",
+DlgLnkPopTop : "Horný okraj",
+
+DlnLnkMsgNoUrl : "Zadajte prosím URL odkazu",
+DlnLnkMsgNoEMail : "Zadajte prosím e-mailovú adresu",
+DlnLnkMsgNoAnchor : "Vyberte prosím kotvu",
+DlnLnkMsgInvPopName : "Názov vyskakovacieho okna sa musá začínať písmenom a nemôže obsahovať medzery",
+
+// Color Dialog
+DlgColorTitle : "Výber farby",
+DlgColorBtnClear : "Vymazať",
+DlgColorHighlight : "Zvýraznená",
+DlgColorSelected : "Vybraná",
+
+// Smiley Dialog
+DlgSmileyTitle : "Vkladanie smajlíkov",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Výber špeciálneho znaku",
+
+// Table Dialog
+DlgTableTitle : "Vlastnosti tabuľky",
+DlgTableRows : "Riadky",
+DlgTableColumns : "Stĺpce",
+DlgTableBorder : "Ohraničenie",
+DlgTableAlign : "Zarovnanie",
+DlgTableAlignNotSet : "<nenastavené>",
+DlgTableAlignLeft : "Vľavo",
+DlgTableAlignCenter : "Na stred",
+DlgTableAlignRight : "Vpravo",
+DlgTableWidth : "Šírka",
+DlgTableWidthPx : "pixelov",
+DlgTableWidthPc : "percent",
+DlgTableHeight : "Výška",
+DlgTableCellSpace : "Vzdialenosť buniek",
+DlgTableCellPad : "Odsadenie obsahu",
+DlgTableCaption : "Popis",
+DlgTableSummary : "Prehľad",
+
+// Table Cell Dialog
+DlgCellTitle : "Vlastnosti bunky",
+DlgCellWidth : "Šírka",
+DlgCellWidthPx : "bodov",
+DlgCellWidthPc : "percent",
+DlgCellHeight : "Výška",
+DlgCellWordWrap : "Zalamovannie",
+DlgCellWordWrapNotSet : "<nenastavené>",
+DlgCellWordWrapYes : "Áno",
+DlgCellWordWrapNo : "Nie",
+DlgCellHorAlign : "Vodorovné zarovnanie",
+DlgCellHorAlignNotSet : "<nenastavené>",
+DlgCellHorAlignLeft : "Vľavo",
+DlgCellHorAlignCenter : "Na stred",
+DlgCellHorAlignRight: "Vpravo",
+DlgCellVerAlign : "Zvislé zarovnanie",
+DlgCellVerAlignNotSet : "<nenastavené>",
+DlgCellVerAlignTop : "Nahor",
+DlgCellVerAlignMiddle : "Doprostred",
+DlgCellVerAlignBottom : "Dole",
+DlgCellVerAlignBaseline : "Na základňu",
+DlgCellRowSpan : "Zlúčené riadky",
+DlgCellCollSpan : "Zlúčené stĺpce",
+DlgCellBackColor : "Farba pozadia",
+DlgCellBorderColor : "Farba ohraničenia",
+DlgCellBtnSelect : "Výber...",
+
+// Find Dialog
+DlgFindTitle : "Hľadať",
+DlgFindFindBtn : "Hľadať",
+DlgFindNotFoundMsg : "Hľadaný text nebol nájdený.",
+
+// Replace Dialog
+DlgReplaceTitle : "Nahradiť",
+DlgReplaceFindLbl : "Čo hľadať:",
+DlgReplaceReplaceLbl : "Čím nahradiť:",
+DlgReplaceCaseChk : "Rozlišovať malé/veľké písmená",
+DlgReplaceReplaceBtn : "Nahradiť",
+DlgReplaceReplAllBtn : "Nahradiť všetko",
+DlgReplaceWordChk : "Len celé slová",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Bezpečnostné nastavenie Vášho prehliadača nedovoľujú editoru spustiť funkciu pre vystrihnutie zvoleného textu do schránky. Prosím vystrihnite zvolený text do schránky pomocou klávesnice (Ctrl+X).",
+PasteErrorCopy : "Bezpečnostné nastavenie Vášho prehliadača nedovoľujú editoru spustiť funkciu pre kopírovanie zvoleného textu do schránky. Prosím skopírujte zvolený text do schránky pomocou klávesnice (Ctrl+C).",
+
+PasteAsText : "Vložiť ako čistý text",
+PasteFromWord : "Vložiť text z Wordu",
+
+DlgPasteMsg2 : "Prosím vložte nasledovný rámček použitím klávesnice (<STRONG>Ctrl+V</STRONG>) a stlačte <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignorovať nastavenia typu písma",
+DlgPasteRemoveStyles : "Odstrániť formátovanie",
+DlgPasteCleanBox : "Vyčistiť schránku",
+
+// Color Picker
+ColorAutomatic : "Automaticky",
+ColorMoreColors : "Viac farieb...",
+
+// Document Properties
+DocProps : "Vlastnosti dokumentu",
+
+// Anchor Dialog
+DlgAnchorTitle : "Vlastnosti kotvy",
+DlgAnchorName : "Meno kotvy",
+DlgAnchorErrorName : "Zadajte prosím meno kotvy",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nie je v slovníku",
+DlgSpellChangeTo : "Zmeniť na",
+DlgSpellBtnIgnore : "Ignorovať",
+DlgSpellBtnIgnoreAll : "Ignorovať všetko",
+DlgSpellBtnReplace : "Prepísat",
+DlgSpellBtnReplaceAll : "Prepísat všetko",
+DlgSpellBtnUndo : "Späť",
+DlgSpellNoSuggestions : "- Žiadny návrh -",
+DlgSpellProgress : "Prebieha kontrola pravopisu...",
+DlgSpellNoMispell : "Kontrola pravopisu dokončená: bez chýb",
+DlgSpellNoChanges : "Kontrola pravopisu dokončená: žiadne slová nezmenené",
+DlgSpellOneChange : "Kontrola pravopisu dokončená: zmenené jedno slovo",
+DlgSpellManyChanges : "Kontrola pravopisu dokončená: zmenených %1 slov",
+
+IeSpellDownload : "Kontrola pravopisu nie je naištalovaná. Chcete ju hneď stiahnuť?",
+
+// Button Dialog
+DlgButtonText : "Text",
+DlgButtonType : "Typ",
+DlgButtonTypeBtn : "Tlačidlo",
+DlgButtonTypeSbm : "Odoslať",
+DlgButtonTypeRst : "Vymazať",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Názov",
+DlgCheckboxValue : "Hodnota",
+DlgCheckboxSelected : "Vybrané",
+
+// Form Dialog
+DlgFormName : "Názov",
+DlgFormAction : "Akcie",
+DlgFormMethod : "Metóda",
+
+// Select Field Dialog
+DlgSelectName : "Názov",
+DlgSelectValue : "Hodnota",
+DlgSelectSize : "Veľkosť",
+DlgSelectLines : "riadkov",
+DlgSelectChkMulti : "Povoliť viacnásobný výber",
+DlgSelectOpAvail : "Dostupné možnosti",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Hodnota",
+DlgSelectBtnAdd : "Pridať",
+DlgSelectBtnModify : "Zmeniť",
+DlgSelectBtnUp : "Hore",
+DlgSelectBtnDown : "Dole",
+DlgSelectBtnSetValue : "Nastaviť ako vybranú hodnotu",
+DlgSelectBtnDelete : "Zmazať",
+
+// Textarea Dialog
+DlgTextareaName : "Názov",
+DlgTextareaCols : "Stĺpce",
+DlgTextareaRows : "Riadky",
+
+// Text Field Dialog
+DlgTextName : "Názov",
+DlgTextValue : "Hodnota",
+DlgTextCharWidth : "Šírka pola (znakov)",
+DlgTextMaxChars : "Maximálny počet znakov",
+DlgTextType : "Typ",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Heslo",
+
+// Hidden Field Dialog
+DlgHiddenName : "Názov",
+DlgHiddenValue : "Hodnota",
+
+// Bulleted List Dialog
+BulletedListProp : "Vlastnosti odrážok",
+NumberedListProp : "Vlastnosti číslovania",
+DlgLstStart : "Štart",
+DlgLstType : "Typ",
+DlgLstTypeCircle : "Krúžok",
+DlgLstTypeDisc : "Disk",
+DlgLstTypeSquare : "Štvorec",
+DlgLstTypeNumbers : "Číslovanie (1, 2, 3)",
+DlgLstTypeLCase : "Malé písmená (a, b, c)",
+DlgLstTypeUCase : "Veľké písmená (A, B, C)",
+DlgLstTypeSRoman : "Malé rímske číslice (i, ii, iii)",
+DlgLstTypeLRoman : "Veľké rímske číslice (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Všeobecné",
+DlgDocBackTab : "Pozadie",
+DlgDocColorsTab : "Farby a okraje",
+DlgDocMetaTab : "Meta Data",
+
+DlgDocPageTitle : "Titulok",
+DlgDocLangDir : "Orientácie jazyka",
+DlgDocLangDirLTR : "Zľava doprava (LTR)",
+DlgDocLangDirRTL : "Sprava doľava (RTL)",
+DlgDocLangCode : "Kód jazyka",
+DlgDocCharSet : "Kódová stránka",
+DlgDocCharSetCE : "Stredoeurópske",
+DlgDocCharSetCT : "Čínština tradičná (Big5)",
+DlgDocCharSetCR : "Cyrillika",
+DlgDocCharSetGR : "Gréčtina",
+DlgDocCharSetJP : "Japončina",
+DlgDocCharSetKR : "Korejčina",
+DlgDocCharSetTR : "Turečtina",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Západná európa",
+DlgDocCharSetOther : "Iná kódová stránka",
+
+DlgDocDocType : "Typ záhlavia dokumentu",
+DlgDocDocTypeOther : "Iný typ záhlavia dokumentu",
+DlgDocIncXHTML : "Obsahuje deklarácie XHTML",
+DlgDocBgColor : "Farba pozadia",
+DlgDocBgImage : "URL adresa obrázku na pozadí",
+DlgDocBgNoScroll : "Fixné pozadie",
+DlgDocCText : "Text",
+DlgDocCLink : "Odkaz",
+DlgDocCVisited : "Navštívený odkaz",
+DlgDocCActive : "Aktívny odkaz",
+DlgDocMargins : "Okraje stránky",
+DlgDocMaTop : "Horný",
+DlgDocMaLeft : "Ľavý",
+DlgDocMaRight : "Pravý",
+DlgDocMaBottom : "Dolný",
+DlgDocMeIndex : "Kľúčové slová pre indexovanie (oddelené čiarkou)",
+DlgDocMeDescr : "Popis stránky",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Autorské práva",
+DlgDocPreview : "Náhľad",
+
+// Templates Dialog
+Templates : "Šablóny",
+DlgTemplatesTitle : "Šablóny obsahu",
+DlgTemplatesSelMsg : "Prosím vyberte šablóny na otvorenie v editore<br>(súšasný obsah bude stratený):",
+DlgTemplatesLoading : "Nahrávam zoznam šablón. Čakajte prosím...",
+DlgTemplatesNoTpl : "(žiadne šablóny nenájdené)",
+DlgTemplatesReplace : "Nahradiť aktuálny obsah",
+
+// About Dialog
+DlgAboutAboutTab : "O aplikáci",
+DlgAboutBrowserInfoTab : "Informácie o prehliadači",
+DlgAboutLicenseTab : "Licencia",
+DlgAboutVersion : "verzia",
+DlgAboutInfo : "Viac informácií získate na"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/sl.js b/httemplate/elements/fckeditor/editor/lang/sl.js
new file mode 100644
index 000000000..95cde15f0
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/sl.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Slovenian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Zloži orodno vrstico",
+ToolbarExpand : "Razširi orodno vrstico",
+
+// Toolbar Items and Context Menu
+Save : "Shrani",
+NewPage : "Nova stran",
+Preview : "Predogled",
+Cut : "Izreži",
+Copy : "Kopiraj",
+Paste : "Prilepi",
+PasteText : "Prilepi kot golo besedilo",
+PasteWord : "Prilepi iz Worda",
+Print : "Natisni",
+SelectAll : "Izberi vse",
+RemoveFormat : "Odstrani oblikovanje",
+InsertLinkLbl : "Povezava",
+InsertLink : "Vstavi/uredi povezavo",
+RemoveLink : "Odstrani povezavo",
+Anchor : "Vstavi/uredi zaznamek",
+InsertImageLbl : "Slika",
+InsertImage : "Vstavi/uredi sliko",
+InsertFlashLbl : "Flash",
+InsertFlash : "Vstavi/Uredi Flash",
+InsertTableLbl : "Tabela",
+InsertTable : "Vstavi/uredi tabelo",
+InsertLineLbl : "Črta",
+InsertLine : "Vstavi vodoravno črto",
+InsertSpecialCharLbl: "Posebni znak",
+InsertSpecialChar : "Vstavi posebni znak",
+InsertSmileyLbl : "Smeško",
+InsertSmiley : "Vstavi smeška",
+About : "O FCKeditorju",
+Bold : "Krepko",
+Italic : "Ležeče",
+Underline : "Podčrtano",
+StrikeThrough : "Prečrtano",
+Subscript : "Podpisano",
+Superscript : "Nadpisano",
+LeftJustify : "Leva poravnava",
+CenterJustify : "Sredinska poravnava",
+RightJustify : "Desna poravnava",
+BlockJustify : "Obojestranska poravnava",
+DecreaseIndent : "Zmanjšaj zamik",
+IncreaseIndent : "Povečaj zamik",
+Undo : "Razveljavi",
+Redo : "Ponovi",
+NumberedListLbl : "Oštevilčen seznam",
+NumberedList : "Vstavi/odstrani oštevilčevanje",
+BulletedListLbl : "Označen seznam",
+BulletedList : "Vstavi/odstrani označevanje",
+ShowTableBorders : "Pokaži meje tabele",
+ShowDetails : "Pokaži podrobnosti",
+Style : "Slog",
+FontFormat : "Oblika",
+Font : "Pisava",
+FontSize : "Velikost",
+TextColor : "Barva besedila",
+BGColor : "Barva ozadja",
+Source : "Izvorna koda",
+Find : "Najdi",
+Replace : "Zamenjaj",
+SpellCheck : "Preveri črkovanje",
+UniversalKeyboard : "Večjezična tipkovnica",
+PageBreakLbl : "Prelom strani",
+PageBreak : "Vstavi prelom strani",
+
+Form : "Obrazec",
+Checkbox : "Potrditveno polje",
+RadioButton : "Izbirno polje",
+TextField : "Vnosno polje",
+Textarea : "Vnosno območje",
+HiddenField : "Skrito polje",
+Button : "Gumb",
+SelectionField : "Spustni seznam",
+ImageButton : "Gumb s sliko",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Uredi povezavo",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Vstavi vrstico",
+DeleteRows : "Izbriši vrstice",
+InsertColumn : "Vstavi stolpec",
+DeleteColumns : "Izbriši stolpce",
+InsertCell : "Vstavi celico",
+DeleteCells : "Izbriši celice",
+MergeCells : "Združi celice",
+SplitCell : "Razdeli celico",
+TableDelete : "Izbriši tabelo",
+CellProperties : "Lastnosti celice",
+TableProperties : "Lastnosti tabele",
+ImageProperties : "Lastnosti slike",
+FlashProperties : "Lastnosti Flash",
+
+AnchorProp : "Lastnosti zaznamka",
+ButtonProp : "Lastnosti gumba",
+CheckboxProp : "Lastnosti potrditvenega polja",
+HiddenFieldProp : "Lastnosti skritega polja",
+RadioButtonProp : "Lastnosti izbirnega polja",
+ImageButtonProp : "Lastnosti gumba s sliko",
+TextFieldProp : "Lastnosti vnosnega polja",
+SelectionFieldProp : "Lastnosti spustnega seznama",
+TextareaProp : "Lastnosti vnosnega območja",
+FormProp : "Lastnosti obrazca",
+
+FontFormats : "Navaden;Oblikovan;Napis;Naslov 1;Naslov 2;Naslov 3;Naslov 4;Naslov 5;Naslov 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Obdelujem XHTML. Prosim počakajte...",
+Done : "Narejeno",
+PasteWordConfirm : "Izgleda, da želite prilepiti besedilo iz Worda. Ali ga želite očistiti, preden ga prilepite?",
+NotCompatiblePaste : "Ta ukaz deluje le v Internet Explorerje različice 5.5 ali višje. Ali želite prilepiti brez čiščenja?",
+UnknownToolbarItem : "Neznan element orodne vrstice \"%1\"",
+UnknownCommand : "Neznano ime ukaza \"%1\"",
+NotImplemented : "Ukaz ni izdelan",
+UnknownToolbarSet : "Skupina orodnih vrstic \"%1\" ne obstoja",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "V redu",
+DlgBtnCancel : "Prekliči",
+DlgBtnClose : "Zapri",
+DlgBtnBrowseServer : "Prebrskaj na strežniku",
+DlgAdvancedTag : "Napredno",
+DlgOpOther : "<Ostalo>",
+DlgInfoTab : "Podatki",
+DlgAlertUrl : "Prosim vpiši spletni naslov",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ni postavljen>",
+DlgGenId : "Id",
+DlgGenLangDir : "Smer jezika",
+DlgGenLangDirLtr : "Od leve proti desni (LTR)",
+DlgGenLangDirRtl : "Od desne proti levi (RTL)",
+DlgGenLangCode : "Oznaka jezika",
+DlgGenAccessKey : "Vstopno geslo",
+DlgGenName : "Ime",
+DlgGenTabIndex : "Številka tabulatorja",
+DlgGenLongDescr : "Dolg opis URL-ja",
+DlgGenClass : "Razred stilne predloge",
+DlgGenTitle : "Predlagani naslov",
+DlgGenContType : "Predlagani tip vsebine (content-type)",
+DlgGenLinkCharset : "Kodna tabela povezanega vira",
+DlgGenStyle : "Slog",
+
+// Image Dialog
+DlgImgTitle : "Lastnosti slike",
+DlgImgInfoTab : "Podatki o sliki",
+DlgImgBtnUpload : "Pošlji na strežnik",
+DlgImgURL : "URL",
+DlgImgUpload : "Pošlji",
+DlgImgAlt : "Nadomestno besedilo",
+DlgImgWidth : "Širina",
+DlgImgHeight : "Višina",
+DlgImgLockRatio : "Zakleni razmerje",
+DlgBtnResetSize : "Ponastavi velikost",
+DlgImgBorder : "Obroba",
+DlgImgHSpace : "Vodoravni razmik",
+DlgImgVSpace : "Navpični razmik",
+DlgImgAlign : "Poravnava",
+DlgImgAlignLeft : "Levo",
+DlgImgAlignAbsBottom: "Popolnoma na dno",
+DlgImgAlignAbsMiddle: "Popolnoma v sredino",
+DlgImgAlignBaseline : "Na osnovno črto",
+DlgImgAlignBottom : "Na dno",
+DlgImgAlignMiddle : "V sredino",
+DlgImgAlignRight : "Desno",
+DlgImgAlignTextTop : "Besedilo na vrh",
+DlgImgAlignTop : "Na vrh",
+DlgImgPreview : "Predogled",
+DlgImgAlertUrl : "Vnesite URL slike",
+DlgImgLinkTab : "Povezava",
+
+// Flash Dialog
+DlgFlashTitle : "Lastnosti Flash",
+DlgFlashChkPlay : "Samodejno predvajaj",
+DlgFlashChkLoop : "Ponavljanje",
+DlgFlashChkMenu : "Omogoči Flash Meni",
+DlgFlashScale : "Povečava",
+DlgFlashScaleAll : "Pokaži vse",
+DlgFlashScaleNoBorder : "Brez obrobe",
+DlgFlashScaleFit : "Natančno prileganje",
+
+// Link Dialog
+DlgLnkWindowTitle : "Povezava",
+DlgLnkInfoTab : "Podatki o povezavi",
+DlgLnkTargetTab : "Cilj",
+
+DlgLnkType : "Vrsta povezave",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Zaznamek na tej strani",
+DlgLnkTypeEMail : "Elektronski naslov",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<drugo>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Izberi zaznamek",
+DlgLnkAnchorByName : "Po imenu zaznamka",
+DlgLnkAnchorById : "Po ID-ju elementa",
+DlgLnkNoAnchors : "<V tem dokumentu ni zaznamkov>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Elektronski naslov",
+DlgLnkEMailSubject : "Predmet sporočila",
+DlgLnkEMailBody : "Vsebina sporočila",
+DlgLnkUpload : "Prenesi",
+DlgLnkBtnUpload : "Pošlji na strežnik",
+
+DlgLnkTarget : "Cilj",
+DlgLnkTargetFrame : "<okvir>",
+DlgLnkTargetPopup : "<pojavno okno>",
+DlgLnkTargetBlank : "Novo okno (_blank)",
+DlgLnkTargetParent : "Starševsko okno (_parent)",
+DlgLnkTargetSelf : "Isto okno (_self)",
+DlgLnkTargetTop : "Najvišje okno (_top)",
+DlgLnkTargetFrameName : "Ime ciljnega okvirja",
+DlgLnkPopWinName : "Ime pojavnega okna",
+DlgLnkPopWinFeat : "Značilnosti pojavnega okna",
+DlgLnkPopResize : "Spremenljive velikosti",
+DlgLnkPopLocation : "Naslovna vrstica",
+DlgLnkPopMenu : "Menijska vrstica",
+DlgLnkPopScroll : "Drsniki",
+DlgLnkPopStatus : "Vrstica stanja",
+DlgLnkPopToolbar : "Orodna vrstica",
+DlgLnkPopFullScrn : "Celozaslonska slika (IE)",
+DlgLnkPopDependent : "Podokno (Netscape)",
+DlgLnkPopWidth : "Širina",
+DlgLnkPopHeight : "Višina",
+DlgLnkPopLeft : "Lega levo",
+DlgLnkPopTop : "Lega na vrhu",
+
+DlnLnkMsgNoUrl : "Vnesite URL povezave",
+DlnLnkMsgNoEMail : "Vnesite elektronski naslov",
+DlnLnkMsgNoAnchor : "Izberite zaznamek",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Izberite barvo",
+DlgColorBtnClear : "Počisti",
+DlgColorHighlight : "Označi",
+DlgColorSelected : "Izbrano",
+
+// Smiley Dialog
+DlgSmileyTitle : "Vstavi smeška",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Izberi posebni znak",
+
+// Table Dialog
+DlgTableTitle : "Lastnosti tabele",
+DlgTableRows : "Vrstice",
+DlgTableColumns : "Stolpci",
+DlgTableBorder : "Velikost obrobe",
+DlgTableAlign : "Poravnava",
+DlgTableAlignNotSet : "<Ni nastavljeno>",
+DlgTableAlignLeft : "Levo",
+DlgTableAlignCenter : "Sredinsko",
+DlgTableAlignRight : "Desno",
+DlgTableWidth : "Širina",
+DlgTableWidthPx : "pik",
+DlgTableWidthPc : "procentov",
+DlgTableHeight : "Višina",
+DlgTableCellSpace : "Razmik med celicami",
+DlgTableCellPad : "Polnilo med celicami",
+DlgTableCaption : "Naslov",
+DlgTableSummary : "Povzetek",
+
+// Table Cell Dialog
+DlgCellTitle : "Lastnosti celice",
+DlgCellWidth : "Širina",
+DlgCellWidthPx : "pik",
+DlgCellWidthPc : "procentov",
+DlgCellHeight : "Višina",
+DlgCellWordWrap : "Pomikanje besedila",
+DlgCellWordWrapNotSet : "<Ni nastavljeno>",
+DlgCellWordWrapYes : "Da",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Vodoravna poravnava",
+DlgCellHorAlignNotSet : "<Ni nastavljeno>",
+DlgCellHorAlignLeft : "Levo",
+DlgCellHorAlignCenter : "Sredinsko",
+DlgCellHorAlignRight: "Desno",
+DlgCellVerAlign : "Navpična poravnava",
+DlgCellVerAlignNotSet : "<Ni nastavljeno>",
+DlgCellVerAlignTop : "Na vrh",
+DlgCellVerAlignMiddle : "V sredino",
+DlgCellVerAlignBottom : "Na dno",
+DlgCellVerAlignBaseline : "Na osnovno črto",
+DlgCellRowSpan : "Spojenih vrstic (row-span)",
+DlgCellCollSpan : "Spojenih stolpcev (col-span)",
+DlgCellBackColor : "Barva ozadja",
+DlgCellBorderColor : "Barva obrobe",
+DlgCellBtnSelect : "Izberi...",
+
+// Find Dialog
+DlgFindTitle : "Najdi",
+DlgFindFindBtn : "Najdi",
+DlgFindNotFoundMsg : "Navedeno besedilo ni bilo najdeno.",
+
+// Replace Dialog
+DlgReplaceTitle : "Zamenjaj",
+DlgReplaceFindLbl : "Najdi:",
+DlgReplaceReplaceLbl : "Zamenjaj z:",
+DlgReplaceCaseChk : "Razlikuj velike in male črke",
+DlgReplaceReplaceBtn : "Zamenjaj",
+DlgReplaceReplAllBtn : "Zamenjaj vse",
+DlgReplaceWordChk : "Samo cele besede",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Varnostne nastavitve brskalnika ne dopuščajo samodejnega izrezovanja. Uporabite kombinacijo tipk na tipkovnici (Ctrl+X).",
+PasteErrorCopy : "Varnostne nastavitve brskalnika ne dopuščajo samodejnega kopiranja. Uporabite kombinacijo tipk na tipkovnici (Ctrl+C).",
+
+PasteAsText : "Prilepi kot golo besedilo",
+PasteFromWord : "Prilepi iz Worda",
+
+DlgPasteMsg2 : "Prosim prilepite v sleči okvir s pomočjo tipkovnice (<STRONG>Ctrl+V</STRONG>) in pritisnite <STRONG>V redu</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Prezri obliko pisave",
+DlgPasteRemoveStyles : "Odstrani nastavitve stila",
+DlgPasteCleanBox : "Počisti okvir",
+
+// Color Picker
+ColorAutomatic : "Samodejno",
+ColorMoreColors : "Več barv...",
+
+// Document Properties
+DocProps : "Lastnosti dokumenta",
+
+// Anchor Dialog
+DlgAnchorTitle : "Lastnosti zaznamka",
+DlgAnchorName : "Ime zaznamka",
+DlgAnchorErrorName : "Prosim vnesite ime zaznamka",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Ni v slovarju",
+DlgSpellChangeTo : "Spremeni v",
+DlgSpellBtnIgnore : "Prezri",
+DlgSpellBtnIgnoreAll : "Prezri vse",
+DlgSpellBtnReplace : "Zamenjaj",
+DlgSpellBtnReplaceAll : "Zamenjaj vse",
+DlgSpellBtnUndo : "Razveljavi",
+DlgSpellNoSuggestions : "- Ni predlogov -",
+DlgSpellProgress : "Preverjanje črkovanja se izvaja...",
+DlgSpellNoMispell : "Črkovanje je končano: Brez napak",
+DlgSpellNoChanges : "Črkovanje je končano: Nobena beseda ni bila spremenjena",
+DlgSpellOneChange : "Črkovanje je končano: Spremenjena je bila ena beseda",
+DlgSpellManyChanges : "Črkovanje je končano: Spremenjenih je bilo %1 besed",
+
+IeSpellDownload : "Črkovalnik ni nameščen. Ali ga želite prenesti sedaj?",
+
+// Button Dialog
+DlgButtonText : "Besedilo (Vrednost)",
+DlgButtonType : "Tip",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Ime",
+DlgCheckboxValue : "Vrednost",
+DlgCheckboxSelected : "Izbrano",
+
+// Form Dialog
+DlgFormName : "Ime",
+DlgFormAction : "Akcija",
+DlgFormMethod : "Metoda",
+
+// Select Field Dialog
+DlgSelectName : "Ime",
+DlgSelectValue : "Vrednost",
+DlgSelectSize : "Velikost",
+DlgSelectLines : "vrstic",
+DlgSelectChkMulti : "Dovoli izbor večih vrstic",
+DlgSelectOpAvail : "Razpoložljive izbire",
+DlgSelectOpText : "Besedilo",
+DlgSelectOpValue : "Vrednost",
+DlgSelectBtnAdd : "Dodaj",
+DlgSelectBtnModify : "Spremeni",
+DlgSelectBtnUp : "Gor",
+DlgSelectBtnDown : "Dol",
+DlgSelectBtnSetValue : "Postavi kot privzeto izbiro",
+DlgSelectBtnDelete : "Izbriši",
+
+// Textarea Dialog
+DlgTextareaName : "Ime",
+DlgTextareaCols : "Stolpcev",
+DlgTextareaRows : "Vrstic",
+
+// Text Field Dialog
+DlgTextName : "Ime",
+DlgTextValue : "Vrednost",
+DlgTextCharWidth : "Dolžina",
+DlgTextMaxChars : "Največje število znakov",
+DlgTextType : "Tip",
+DlgTextTypeText : "Besedilo",
+DlgTextTypePass : "Geslo",
+
+// Hidden Field Dialog
+DlgHiddenName : "Ime",
+DlgHiddenValue : "Vrednost",
+
+// Bulleted List Dialog
+BulletedListProp : "Lastnosti označenega seznama",
+NumberedListProp : "Lastnosti oštevilčenega seznama",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tip",
+DlgLstTypeCircle : "Pikica",
+DlgLstTypeDisc : "Kroglica",
+DlgLstTypeSquare : "Kvadratek",
+DlgLstTypeNumbers : "Številke (1, 2, 3)",
+DlgLstTypeLCase : "Male črke (a, b, c)",
+DlgLstTypeUCase : "Velike črke (A, B, C)",
+DlgLstTypeSRoman : "Male rimske številke (i, ii, iii)",
+DlgLstTypeLRoman : "Velike rimske številke (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Splošno",
+DlgDocBackTab : "Ozadje",
+DlgDocColorsTab : "Barve in zamiki",
+DlgDocMetaTab : "Meta podatki",
+
+DlgDocPageTitle : "Naslov strani",
+DlgDocLangDir : "Smer jezika",
+DlgDocLangDirLTR : "Od leve proti desni (LTR)",
+DlgDocLangDirRTL : "Od desne proti levi (RTL)",
+DlgDocLangCode : "Oznaka jezika",
+DlgDocCharSet : "Kodna tabela",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Druga kodna tabela",
+
+DlgDocDocType : "Glava tipa dokumenta",
+DlgDocDocTypeOther : "Druga glava tipa dokumenta",
+DlgDocIncXHTML : "Vstavi XHTML deklaracije",
+DlgDocBgColor : "Barva ozadja",
+DlgDocBgImage : "URL slike za ozadje",
+DlgDocBgNoScroll : "Nepremično ozadje",
+DlgDocCText : "Besedilo",
+DlgDocCLink : "Povezava",
+DlgDocCVisited : "Obiskana povezava",
+DlgDocCActive : "Aktivna povezava",
+DlgDocMargins : "Zamiki strani",
+DlgDocMaTop : "Na vrhu",
+DlgDocMaLeft : "Levo",
+DlgDocMaRight : "Desno",
+DlgDocMaBottom : "Spodaj",
+DlgDocMeIndex : "Ključne besede (ločene z vejicami)",
+DlgDocMeDescr : "Opis strani",
+DlgDocMeAuthor : "Avtor",
+DlgDocMeCopy : "Avtorske pravice",
+DlgDocPreview : "Predogled",
+
+// Templates Dialog
+Templates : "Predloge",
+DlgTemplatesTitle : "Vsebinske predloge",
+DlgTemplatesSelMsg : "Izberite predlogo, ki jo želite odpreti v urejevalniku<br>(trenutna vsebina bo izgubljena):",
+DlgTemplatesLoading : "Nalagam seznam predlog. Prosim počakajte...",
+DlgTemplatesNoTpl : "(Ni pripravljenih predlog)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "Vizitka",
+DlgAboutBrowserInfoTab : "Informacije o brskalniku",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "različica",
+DlgAboutInfo : "Za več informacij obiščite"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/sr-latn.js b/httemplate/elements/fckeditor/editor/lang/sr-latn.js
new file mode 100644
index 000000000..5fa8154e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/sr-latn.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Serbian (Latin) language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Smanji liniju sa alatkama",
+ToolbarExpand : "Proiri liniju sa alatkama",
+
+// Toolbar Items and Context Menu
+Save : "Sačuvaj",
+NewPage : "Nova stranica",
+Preview : "Izgled stranice",
+Cut : "Iseci",
+Copy : "Kopiraj",
+Paste : "Zalepi",
+PasteText : "Zalepi kao neformatiran tekst",
+PasteWord : "Zalepi iz Worda",
+Print : "Štampa",
+SelectAll : "Označi sve",
+RemoveFormat : "Ukloni formatiranje",
+InsertLinkLbl : "Link",
+InsertLink : "Unesi/izmeni link",
+RemoveLink : "Ukloni link",
+Anchor : "Unesi/izmeni sidro",
+InsertImageLbl : "Slika",
+InsertImage : "Unesi/izmeni sliku",
+InsertFlashLbl : "Fleš",
+InsertFlash : "Unesi/izmeni fleš",
+InsertTableLbl : "Tabela",
+InsertTable : "Unesi/izmeni tabelu",
+InsertLineLbl : "Linija",
+InsertLine : "Unesi horizontalnu liniju",
+InsertSpecialCharLbl: "Specijalni karakteri",
+InsertSpecialChar : "Unesi specijalni karakter",
+InsertSmileyLbl : "Smajli",
+InsertSmiley : "Unesi smajlija",
+About : "O FCKeditoru",
+Bold : "Podebljano",
+Italic : "Kurziv",
+Underline : "Podvučeno",
+StrikeThrough : "Precrtano",
+Subscript : "Indeks",
+Superscript : "Stepen",
+LeftJustify : "Levo ravnanje",
+CenterJustify : "Centriran tekst",
+RightJustify : "Desno ravnanje",
+BlockJustify : "Obostrano ravnanje",
+DecreaseIndent : "Smanji levu marginu",
+IncreaseIndent : "Uvećaj levu marginu",
+Undo : "Poni�ti akciju",
+Redo : "Ponovi akciju",
+NumberedListLbl : "Nabrojiva lista",
+NumberedList : "Unesi/ukloni nabrojivu listu",
+BulletedListLbl : "Nenabrojiva lista",
+BulletedList : "Unesi/ukloni nenabrojivu listu",
+ShowTableBorders : "Prikaži okvir tabele",
+ShowDetails : "Prikaži detalje",
+Style : "Stil",
+FontFormat : "Format",
+Font : "Font",
+FontSize : "Veličina fonta",
+TextColor : "Boja teksta",
+BGColor : "Boja pozadine",
+Source : "Kôd",
+Find : "Pretraga",
+Replace : "Zamena",
+SpellCheck : "Proveri spelovanje",
+UniversalKeyboard : "Univerzalna tastatura",
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Forma",
+Checkbox : "Polje za potvrdu",
+RadioButton : "Radio-dugme",
+TextField : "Tekstualno polje",
+Textarea : "Zona teksta",
+HiddenField : "Skriveno polje",
+Button : "Dugme",
+SelectionField : "Izborno polje",
+ImageButton : "Dugme sa slikom",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Izmeni link",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Unesi red",
+DeleteRows : "Obriši redove",
+InsertColumn : "Unesi kolonu",
+DeleteColumns : "Obriši kolone",
+InsertCell : "Unesi ćelije",
+DeleteCells : "Obriši ćelije",
+MergeCells : "Spoj celije",
+SplitCell : "Razdvoji celije",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Osobine celije",
+TableProperties : "Osobine tabele",
+ImageProperties : "Osobine slike",
+FlashProperties : "Osobine fleša",
+
+AnchorProp : "Osobine sidra",
+ButtonProp : "Osobine dugmeta",
+CheckboxProp : "Osobine polja za potvrdu",
+HiddenFieldProp : "Osobine skrivenog polja",
+RadioButtonProp : "Osobine radio-dugmeta",
+ImageButtonProp : "Osobine dugmeta sa slikom",
+TextFieldProp : "Osobine tekstualnog polja",
+SelectionFieldProp : "Osobine izbornog polja",
+TextareaProp : "Osobine zone teksta",
+FormProp : "Osobine forme",
+
+FontFormats : "Normal;Formatirano;Adresa;Naslov 1;Naslov 2;Naslov 3;Naslov 4;Naslov 5;Naslov 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Obradujem XHTML. Malo strpljenja...",
+Done : "Završio",
+PasteWordConfirm : "Tekst koji želite da nalepite kopiran je iz Worda. Da li želite da bude očišćen od formata pre lepljenja?",
+NotCompatiblePaste : "Ova komanda je dostupna samo za Internet Explorer od verzije 5.5. Da li želite da nalepim tekst bez čišćenja?",
+UnknownToolbarItem : "Nepoznata stavka toolbara \"%1\"",
+UnknownCommand : "Nepoznata naredba \"%1\"",
+NotImplemented : "Naredba nije implementirana",
+UnknownToolbarSet : "Toolbar \"%1\" ne postoji",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Otkaži",
+DlgBtnClose : "Zatvori",
+DlgBtnBrowseServer : "Pretraži server",
+DlgAdvancedTag : "Napredni tagovi",
+DlgOpOther : "<Ostali>",
+DlgInfoTab : "Info",
+DlgAlertUrl : "Molimo Vas, unesite URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<nije postavljeno>",
+DlgGenId : "Id",
+DlgGenLangDir : "Smer jezika",
+DlgGenLangDirLtr : "S leva na desno (LTR)",
+DlgGenLangDirRtl : "S desna na levo (RTL)",
+DlgGenLangCode : "Kôd jezika",
+DlgGenAccessKey : "Pristupni taster",
+DlgGenName : "Naziv",
+DlgGenTabIndex : "Tab indeks",
+DlgGenLongDescr : "Pun opis URL",
+DlgGenClass : "Stylesheet klase",
+DlgGenTitle : "Advisory naslov",
+DlgGenContType : "Advisory vrsta sadržaja",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Stil",
+
+// Image Dialog
+DlgImgTitle : "Osobine slika",
+DlgImgInfoTab : "Info slike",
+DlgImgBtnUpload : "Pošalji na server",
+DlgImgURL : "URL",
+DlgImgUpload : "Pošalji",
+DlgImgAlt : "Alternativni tekst",
+DlgImgWidth : "Širina",
+DlgImgHeight : "Visina",
+DlgImgLockRatio : "Zaključaj odnos",
+DlgBtnResetSize : "Resetuj veličinu",
+DlgImgBorder : "Okvir",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Ravnanje",
+DlgImgAlignLeft : "Levo",
+DlgImgAlignAbsBottom: "Abs dole",
+DlgImgAlignAbsMiddle: "Abs sredina",
+DlgImgAlignBaseline : "Bazno",
+DlgImgAlignBottom : "Dole",
+DlgImgAlignMiddle : "Sredina",
+DlgImgAlignRight : "Desno",
+DlgImgAlignTextTop : "Vrh teksta",
+DlgImgAlignTop : "Vrh",
+DlgImgPreview : "Izgled",
+DlgImgAlertUrl : "Unesite URL slike",
+DlgImgLinkTab : "Link",
+
+// Flash Dialog
+DlgFlashTitle : "Osobine fleša",
+DlgFlashChkPlay : "Automatski start",
+DlgFlashChkLoop : "Ponavljaj",
+DlgFlashChkMenu : "Uključi fleš meni",
+DlgFlashScale : "Skaliraj",
+DlgFlashScaleAll : "Prikaži sve",
+DlgFlashScaleNoBorder : "Bez ivice",
+DlgFlashScaleFit : "Popuni površinu",
+
+// Link Dialog
+DlgLnkWindowTitle : "Link",
+DlgLnkInfoTab : "Link Info",
+DlgLnkTargetTab : "Meta",
+
+DlgLnkType : "Vrsta linka",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Sidro na ovoj stranici",
+DlgLnkTypeEMail : "E-Mail",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<drugo>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Odaberi sidro",
+DlgLnkAnchorByName : "Po nazivu sidra",
+DlgLnkAnchorById : "Po Id-ju elementa",
+DlgLnkNoAnchors : "<Nema dostupnih sidra>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Mail adresa",
+DlgLnkEMailSubject : "Naslov",
+DlgLnkEMailBody : "Sadržaj poruke",
+DlgLnkUpload : "Pošalji",
+DlgLnkBtnUpload : "Pošalji na server",
+
+DlgLnkTarget : "Meta",
+DlgLnkTargetFrame : "<okvir>",
+DlgLnkTargetPopup : "<popup prozor>",
+DlgLnkTargetBlank : "Novi prozor (_blank)",
+DlgLnkTargetParent : "Roditeljski prozor (_parent)",
+DlgLnkTargetSelf : "Isti prozor (_self)",
+DlgLnkTargetTop : "Prozor na vrhu (_top)",
+DlgLnkTargetFrameName : "Naziv odredišnog frejma",
+DlgLnkPopWinName : "Naziv popup prozora",
+DlgLnkPopWinFeat : "Mogućnosti popup prozora",
+DlgLnkPopResize : "Promenljiva velicina",
+DlgLnkPopLocation : "Lokacija",
+DlgLnkPopMenu : "Kontekstni meni",
+DlgLnkPopScroll : "Scroll bar",
+DlgLnkPopStatus : "Statusna linija",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Prikaz preko celog ekrana (IE)",
+DlgLnkPopDependent : "Zavisno (Netscape)",
+DlgLnkPopWidth : "Širina",
+DlgLnkPopHeight : "Visina",
+DlgLnkPopLeft : "Od leve ivice ekrana (px)",
+DlgLnkPopTop : "Od vrha ekrana (px)",
+
+DlnLnkMsgNoUrl : "Unesite URL linka",
+DlnLnkMsgNoEMail : "Otkucajte adresu elektronske pote",
+DlnLnkMsgNoAnchor : "Odaberite sidro",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Odaberite boju",
+DlgColorBtnClear : "Obriši",
+DlgColorHighlight : "Posvetli",
+DlgColorSelected : "Odaberi",
+
+// Smiley Dialog
+DlgSmileyTitle : "Unesi smajlija",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Odaberite specijalni karakter",
+
+// Table Dialog
+DlgTableTitle : "Osobine tabele",
+DlgTableRows : "Redova",
+DlgTableColumns : "Kolona",
+DlgTableBorder : "Veličina okvira",
+DlgTableAlign : "Ravnanje",
+DlgTableAlignNotSet : "<nije postavljeno>",
+DlgTableAlignLeft : "Levo",
+DlgTableAlignCenter : "Sredina",
+DlgTableAlignRight : "Desno",
+DlgTableWidth : "Širina",
+DlgTableWidthPx : "piksela",
+DlgTableWidthPc : "procenata",
+DlgTableHeight : "Visina",
+DlgTableCellSpace : "Ćelijski prostor",
+DlgTableCellPad : "Razmak ćelija",
+DlgTableCaption : "Naslov tabele",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Osobine ćelije",
+DlgCellWidth : "Širina",
+DlgCellWidthPx : "piksela",
+DlgCellWidthPc : "procenata",
+DlgCellHeight : "Visina",
+DlgCellWordWrap : "Deljenje reči",
+DlgCellWordWrapNotSet : "<nije postavljeno>",
+DlgCellWordWrapYes : "Da",
+DlgCellWordWrapNo : "Ne",
+DlgCellHorAlign : "Vodoravno ravnanje",
+DlgCellHorAlignNotSet : "<nije postavljeno>",
+DlgCellHorAlignLeft : "Levo",
+DlgCellHorAlignCenter : "Sredina",
+DlgCellHorAlignRight: "Desno",
+DlgCellVerAlign : "Vertikalno ravnanje",
+DlgCellVerAlignNotSet : "<nije postavljeno>",
+DlgCellVerAlignTop : "Gornje",
+DlgCellVerAlignMiddle : "Sredina",
+DlgCellVerAlignBottom : "Donje",
+DlgCellVerAlignBaseline : "Bazno",
+DlgCellRowSpan : "Spajanje redova",
+DlgCellCollSpan : "Spajanje kolona",
+DlgCellBackColor : "Boja pozadine",
+DlgCellBorderColor : "Boja okvira",
+DlgCellBtnSelect : "Odaberi...",
+
+// Find Dialog
+DlgFindTitle : "Pronađi",
+DlgFindFindBtn : "Pronađi",
+DlgFindNotFoundMsg : "Traženi tekst nije pronađen.",
+
+// Replace Dialog
+DlgReplaceTitle : "Zameni",
+DlgReplaceFindLbl : "Pronadi:",
+DlgReplaceReplaceLbl : "Zameni sa:",
+DlgReplaceCaseChk : "Razlikuj mala i velika slova",
+DlgReplaceReplaceBtn : "Zameni",
+DlgReplaceReplAllBtn : "Zameni sve",
+DlgReplaceWordChk : "Uporedi cele reci",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog isecanja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl+X).",
+PasteErrorCopy : "Sigurnosna podešavanja Vašeg pretraživača ne dozvoljavaju operacije automatskog kopiranja teksta. Molimo Vas da koristite prečicu sa tastature (Ctrl+C).",
+
+PasteAsText : "Zalepi kao čist tekst",
+PasteFromWord : "Zalepi iz Worda",
+
+DlgPasteMsg2 : "Molimo Vas da zalepite unutar donje povrine koristeći tastaturnu prečicu (<STRONG>Ctrl+V</STRONG>) i da pritisnete <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Ignoriši definicije fontova",
+DlgPasteRemoveStyles : "Ukloni definicije stilova",
+DlgPasteCleanBox : "Obriši sve",
+
+// Color Picker
+ColorAutomatic : "Automatski",
+ColorMoreColors : "Više boja...",
+
+// Document Properties
+DocProps : "Osobine dokumenta",
+
+// Anchor Dialog
+DlgAnchorTitle : "Osobine sidra",
+DlgAnchorName : "Ime sidra",
+DlgAnchorErrorName : "Unesite ime sidra",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Nije u rečniku",
+DlgSpellChangeTo : "Izmeni",
+DlgSpellBtnIgnore : "Ignoriši",
+DlgSpellBtnIgnoreAll : "Ignoriši sve",
+DlgSpellBtnReplace : "Zameni",
+DlgSpellBtnReplaceAll : "Zameni sve",
+DlgSpellBtnUndo : "Vrati akciju",
+DlgSpellNoSuggestions : "- Bez sugestija -",
+DlgSpellProgress : "Provera spelovanja u toku...",
+DlgSpellNoMispell : "Provera spelovanja završena: greške nisu pronadene",
+DlgSpellNoChanges : "Provera spelovanja završena: Nije izmenjena nijedna rec",
+DlgSpellOneChange : "Provera spelovanja završena: Izmenjena je jedna reč",
+DlgSpellManyChanges : "Provera spelovanja završena: %1 reč(i) je izmenjeno",
+
+IeSpellDownload : "Provera spelovanja nije instalirana. Da li želite da je skinete sa Interneta?",
+
+// Button Dialog
+DlgButtonText : "Tekst (vrednost)",
+DlgButtonType : "Tip",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Naziv",
+DlgCheckboxValue : "Vrednost",
+DlgCheckboxSelected : "Označeno",
+
+// Form Dialog
+DlgFormName : "Naziv",
+DlgFormAction : "Akcija",
+DlgFormMethod : "Metoda",
+
+// Select Field Dialog
+DlgSelectName : "Naziv",
+DlgSelectValue : "Vrednost",
+DlgSelectSize : "Veličina",
+DlgSelectLines : "linija",
+DlgSelectChkMulti : "Dozvoli višestruku selekciju",
+DlgSelectOpAvail : "Dostupne opcije",
+DlgSelectOpText : "Tekst",
+DlgSelectOpValue : "Vrednost",
+DlgSelectBtnAdd : "Dodaj",
+DlgSelectBtnModify : "Izmeni",
+DlgSelectBtnUp : "Gore",
+DlgSelectBtnDown : "Dole",
+DlgSelectBtnSetValue : "Podesi kao označenu vrednost",
+DlgSelectBtnDelete : "Obriši",
+
+// Textarea Dialog
+DlgTextareaName : "Naziv",
+DlgTextareaCols : "Broj kolona",
+DlgTextareaRows : "Broj redova",
+
+// Text Field Dialog
+DlgTextName : "Naziv",
+DlgTextValue : "Vrednost",
+DlgTextCharWidth : "Širina (karaktera)",
+DlgTextMaxChars : "Maksimalno karaktera",
+DlgTextType : "Tip",
+DlgTextTypeText : "Tekst",
+DlgTextTypePass : "Lozinka",
+
+// Hidden Field Dialog
+DlgHiddenName : "Naziv",
+DlgHiddenValue : "Vrednost",
+
+// Bulleted List Dialog
+BulletedListProp : "Osobine nenabrojive liste",
+NumberedListProp : "Osobine nabrojive liste",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Tip",
+DlgLstTypeCircle : "Krug",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Kvadrat",
+DlgLstTypeNumbers : "Brojevi (1, 2, 3)",
+DlgLstTypeLCase : "mala slova (a, b, c)",
+DlgLstTypeUCase : "VELIKA slova (A, B, C)",
+DlgLstTypeSRoman : "Male rimske cifre (i, ii, iii)",
+DlgLstTypeLRoman : "Velike rimske cifre (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Opšte osobine",
+DlgDocBackTab : "Pozadina",
+DlgDocColorsTab : "Boje i margine",
+DlgDocMetaTab : "Metapodaci",
+
+DlgDocPageTitle : "Naslov stranice",
+DlgDocLangDir : "Smer jezika",
+DlgDocLangDirLTR : "Sleva nadesno (LTR)",
+DlgDocLangDirRTL : "Zdesna nalevo (RTL)",
+DlgDocLangCode : "Šifra jezika",
+DlgDocCharSet : "Kodiranje skupa karaktera",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Ostala kodiranja skupa karaktera",
+
+DlgDocDocType : "Zaglavlje tipa dokumenta",
+DlgDocDocTypeOther : "Ostala zaglavlja tipa dokumenta",
+DlgDocIncXHTML : "Ukljuci XHTML deklaracije",
+DlgDocBgColor : "Boja pozadine",
+DlgDocBgImage : "URL pozadinske slike",
+DlgDocBgNoScroll : "Fiksirana pozadina",
+DlgDocCText : "Tekst",
+DlgDocCLink : "Link",
+DlgDocCVisited : "Posećeni link",
+DlgDocCActive : "Aktivni link",
+DlgDocMargins : "Margine stranice",
+DlgDocMaTop : "Gornja",
+DlgDocMaLeft : "Leva",
+DlgDocMaRight : "Desna",
+DlgDocMaBottom : "Donja",
+DlgDocMeIndex : "Ključne reci za indeksiranje dokumenta (razdvojene zarezima)",
+DlgDocMeDescr : "Opis dokumenta",
+DlgDocMeAuthor : "Autor",
+DlgDocMeCopy : "Autorska prava",
+DlgDocPreview : "Izgled stranice",
+
+// Templates Dialog
+Templates : "Obrasci",
+DlgTemplatesTitle : "Obrasci za sadržaj",
+DlgTemplatesSelMsg : "Molimo Vas da odaberete obrazac koji ce biti primenjen na stranicu (trenutni sadržaj ce biti obrisan):",
+DlgTemplatesLoading : "Učitavam listu obrazaca. Malo strpljenja...",
+DlgTemplatesNoTpl : "(Nema definisanih obrazaca)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "O editoru",
+DlgAboutBrowserInfoTab : "Informacije o pretraživacu",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "verzija",
+DlgAboutInfo : "Za više informacija posetite"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/sr.js b/httemplate/elements/fckeditor/editor/lang/sr.js
new file mode 100644
index 000000000..e7aac2311
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/sr.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Serbian (Cyrillic) language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Смањи линију са алаткама",
+ToolbarExpand : "Прошири линију са алаткама",
+
+// Toolbar Items and Context Menu
+Save : "Сачувај",
+NewPage : "Нова страница",
+Preview : "Изглед странице",
+Cut : "Исеци",
+Copy : "Копирај",
+Paste : "Залепи",
+PasteText : "Залепи као неформатиран текст",
+PasteWord : "Залепи из Worda",
+Print : "Штампа",
+SelectAll : "Означи све",
+RemoveFormat : "Уклони форматирање",
+InsertLinkLbl : "Линк",
+InsertLink : "Унеси/измени линк",
+RemoveLink : "Уклони линк",
+Anchor : "Унеси/измени сидро",
+InsertImageLbl : "Слика",
+InsertImage : "Унеси/измени слику",
+InsertFlashLbl : "Флеш елемент",
+InsertFlash : "Унеси/измени флеш",
+InsertTableLbl : "Табела",
+InsertTable : "Унеси/измени табелу",
+InsertLineLbl : "Линија",
+InsertLine : "Унеси хоризонталну линију",
+InsertSpecialCharLbl: "Специјални карактери",
+InsertSpecialChar : "Унеси специјални карактер",
+InsertSmileyLbl : "Смајли",
+InsertSmiley : "Унеси смајлија",
+About : "О ФЦКедитору",
+Bold : "Подебљано",
+Italic : "Курзив",
+Underline : "Подвучено",
+StrikeThrough : "Прецртано",
+Subscript : "Индекс",
+Superscript : "Степен",
+LeftJustify : "Лево равнање",
+CenterJustify : "Центриран текст",
+RightJustify : "Десно равнање",
+BlockJustify : "Обострано равнање",
+DecreaseIndent : "Смањи леву маргину",
+IncreaseIndent : "Увећај леву маргину",
+Undo : "Поништи акцију",
+Redo : "Понови акцију",
+NumberedListLbl : "Набројиву листу",
+NumberedList : "Унеси/уклони набројиву листу",
+BulletedListLbl : "Ненабројива листа",
+BulletedList : "Унеси/уклони ненабројиву листу",
+ShowTableBorders : "Прикажи оквир табеле",
+ShowDetails : "Прикажи детаље",
+Style : "Стил",
+FontFormat : "Формат",
+Font : "Фонт",
+FontSize : "Величина фонта",
+TextColor : "Боја текста",
+BGColor : "Боја позадине",
+Source : "Kôд",
+Find : "Претрага",
+Replace : "Замена",
+SpellCheck : "Провери спеловање",
+UniversalKeyboard : "Универзална тастатура",
+PageBreakLbl : "Page Break", //MISSING
+PageBreak : "Insert Page Break", //MISSING
+
+Form : "Форма",
+Checkbox : "Поље за потврду",
+RadioButton : "Радио-дугме",
+TextField : "Текстуално поље",
+Textarea : "Зона текста",
+HiddenField : "Скривено поље",
+Button : "Дугме",
+SelectionField : "Изборно поље",
+ImageButton : "Дугме са сликом",
+
+FitWindow : "Maximize the editor size", //MISSING
+
+// Context Menu
+EditLink : "Промени линк",
+CellCM : "Cell", //MISSING
+RowCM : "Row", //MISSING
+ColumnCM : "Column", //MISSING
+InsertRow : "Унеси ред",
+DeleteRows : "Обриши редове",
+InsertColumn : "Унеси колону",
+DeleteColumns : "Обриши колоне",
+InsertCell : "Унеси ћелије",
+DeleteCells : "Обриши ћелије",
+MergeCells : "Спој ћелије",
+SplitCell : "Раздвоји ћелије",
+TableDelete : "Delete Table", //MISSING
+CellProperties : "Особине ћелије",
+TableProperties : "Особине табеле",
+ImageProperties : "Особине слике",
+FlashProperties : "Особине Флеша",
+
+AnchorProp : "Особине сидра",
+ButtonProp : "Особине дугмета",
+CheckboxProp : "Особине поља за потврду",
+HiddenFieldProp : "Особине скривеног поља",
+RadioButtonProp : "Особине радио-дугмета",
+ImageButtonProp : "Особине дугмета са сликом",
+TextFieldProp : "Особине текстуалног поља",
+SelectionFieldProp : "Особине изборног поља",
+TextareaProp : "Особине зоне текста",
+FormProp : "Особине форме",
+
+FontFormats : "Normal;Formatirano;Adresa;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Обрађујем XHTML. Maлo стрпљења...",
+Done : "Завршио",
+PasteWordConfirm : "Текст који желите да налепите копиран је из Worda. Да ли желите да буде очишћен од формата пре лепљења?",
+NotCompatiblePaste : "Ова команда је доступна само за Интернет Екплорер од верзије 5.5. Да ли желите да налепим текст без чишћења?",
+UnknownToolbarItem : "Непозната ставка toolbara \"%1\"",
+UnknownCommand : "Непозната наредба \"%1\"",
+NotImplemented : "Наредба није имплементирана",
+UnknownToolbarSet : "Toolbar \"%1\" не постоји",
+NoActiveX : "Your browser's security settings could limit some features of the editor. You must enable the option \"Run ActiveX controls and plug-ins\". You may experience errors and notice missing features.", //MISSING
+BrowseServerBlocked : "The resources browser could not be opened. Make sure that all popup blockers are disabled.", //MISSING
+DialogBlocked : "It was not possible to open the dialog window. Make sure all popup blockers are disabled.", //MISSING
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Oткажи",
+DlgBtnClose : "Затвори",
+DlgBtnBrowseServer : "Претражи сервер",
+DlgAdvancedTag : "Напредни тагови",
+DlgOpOther : "<Остали>",
+DlgInfoTab : "Инфо",
+DlgAlertUrl : "Молимо Вас, унесите УРЛ",
+
+// General Dialogs Labels
+DlgGenNotSet : "<није постављено>",
+DlgGenId : "Ид",
+DlgGenLangDir : "Смер језика",
+DlgGenLangDirLtr : "С лева на десно (LTR)",
+DlgGenLangDirRtl : "С десна на лево (RTL)",
+DlgGenLangCode : "Kôд језика",
+DlgGenAccessKey : "Приступни тастер",
+DlgGenName : "Назив",
+DlgGenTabIndex : "Таб индекс",
+DlgGenLongDescr : "Пун опис УРЛ",
+DlgGenClass : "Stylesheet класе",
+DlgGenTitle : "Advisory наслов",
+DlgGenContType : "Advisory врста садржаја",
+DlgGenLinkCharset : "Linked Resource Charset",
+DlgGenStyle : "Стил",
+
+// Image Dialog
+DlgImgTitle : "Особине слика",
+DlgImgInfoTab : "Инфо слике",
+DlgImgBtnUpload : "Пошаљи на сервер",
+DlgImgURL : "УРЛ",
+DlgImgUpload : "Пошаљи",
+DlgImgAlt : "Алтернативни текст",
+DlgImgWidth : "Ширина",
+DlgImgHeight : "Висина",
+DlgImgLockRatio : "Закључај однос",
+DlgBtnResetSize : "Ресетуј величину",
+DlgImgBorder : "Оквир",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Равнање",
+DlgImgAlignLeft : "Лево",
+DlgImgAlignAbsBottom: "Abs доле",
+DlgImgAlignAbsMiddle: "Abs средина",
+DlgImgAlignBaseline : "Базно",
+DlgImgAlignBottom : "Доле",
+DlgImgAlignMiddle : "Средина",
+DlgImgAlignRight : "Десно",
+DlgImgAlignTextTop : "Врх текста",
+DlgImgAlignTop : "Врх",
+DlgImgPreview : "Изглед",
+DlgImgAlertUrl : "Унесите УРЛ слике",
+DlgImgLinkTab : "Линк",
+
+// Flash Dialog
+DlgFlashTitle : "Особине флеша",
+DlgFlashChkPlay : "Аутоматски старт",
+DlgFlashChkLoop : "Понављај",
+DlgFlashChkMenu : "Укључи флеш мени",
+DlgFlashScale : "Скалирај",
+DlgFlashScaleAll : "Прикажи све",
+DlgFlashScaleNoBorder : "Без ивице",
+DlgFlashScaleFit : "Попуни површину",
+
+// Link Dialog
+DlgLnkWindowTitle : "Линк",
+DlgLnkInfoTab : "Линк инфо",
+DlgLnkTargetTab : "Мета",
+
+DlgLnkType : "Врста линка",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Сидро на овој страници",
+DlgLnkTypeEMail : "Eлектронска пошта",
+DlgLnkProto : "Протокол",
+DlgLnkProtoOther : "<друго>",
+DlgLnkURL : "УРЛ",
+DlgLnkAnchorSel : "Одабери сидро",
+DlgLnkAnchorByName : "По називу сидра",
+DlgLnkAnchorById : "Пo Ид-jу елемента",
+DlgLnkNoAnchors : "<Нема доступних сидра>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Адреса електронске поште",
+DlgLnkEMailSubject : "Наслов",
+DlgLnkEMailBody : "Садржај поруке",
+DlgLnkUpload : "Пошаљи",
+DlgLnkBtnUpload : "Пошаљи на сервер",
+
+DlgLnkTarget : "Meтa",
+DlgLnkTargetFrame : "<оквир>",
+DlgLnkTargetPopup : "<искачући прозор>",
+DlgLnkTargetBlank : "Нови прозор (_blank)",
+DlgLnkTargetParent : "Родитељски прозор (_parent)",
+DlgLnkTargetSelf : "Исти прозор (_self)",
+DlgLnkTargetTop : "Прозор на врху (_top)",
+DlgLnkTargetFrameName : "Назив одредишног фрејма",
+DlgLnkPopWinName : "Назив искачућег прозора",
+DlgLnkPopWinFeat : "Могућности искачућег прозора",
+DlgLnkPopResize : "Променљива величина",
+DlgLnkPopLocation : "Локација",
+DlgLnkPopMenu : "Контекстни мени",
+DlgLnkPopScroll : "Скрол бар",
+DlgLnkPopStatus : "Статусна линија",
+DlgLnkPopToolbar : "Toolbar",
+DlgLnkPopFullScrn : "Приказ преко целог екрана (ИE)",
+DlgLnkPopDependent : "Зависно (Netscape)",
+DlgLnkPopWidth : "Ширина",
+DlgLnkPopHeight : "Висина",
+DlgLnkPopLeft : "Од леве ивице екрана (пиксела)",
+DlgLnkPopTop : "Од врха екрана (пиксела)",
+
+DlnLnkMsgNoUrl : "Унесите УРЛ линка",
+DlnLnkMsgNoEMail : "Откуцајте адресу електронске поште",
+DlnLnkMsgNoAnchor : "Одаберите сидро",
+DlnLnkMsgInvPopName : "The popup name must begin with an alphabetic character and must not contain spaces", //MISSING
+
+// Color Dialog
+DlgColorTitle : "Одаберите боју",
+DlgColorBtnClear : "Обриши",
+DlgColorHighlight : "Посветли",
+DlgColorSelected : "Одабери",
+
+// Smiley Dialog
+DlgSmileyTitle : "Унеси смајлија",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Одаберите специјални карактер",
+
+// Table Dialog
+DlgTableTitle : "Особине табеле",
+DlgTableRows : "Редова",
+DlgTableColumns : "Kолона",
+DlgTableBorder : "Величина оквира",
+DlgTableAlign : "Равнање",
+DlgTableAlignNotSet : "<није постављено>",
+DlgTableAlignLeft : "Лево",
+DlgTableAlignCenter : "Средина",
+DlgTableAlignRight : "Десно",
+DlgTableWidth : "Ширина",
+DlgTableWidthPx : "пиксела",
+DlgTableWidthPc : "процената",
+DlgTableHeight : "Висина",
+DlgTableCellSpace : "Ћелијски простор",
+DlgTableCellPad : "Размак ћелија",
+DlgTableCaption : "Наслов табеле",
+DlgTableSummary : "Summary", //MISSING
+
+// Table Cell Dialog
+DlgCellTitle : "Особине ћелије",
+DlgCellWidth : "Ширина",
+DlgCellWidthPx : "пиксела",
+DlgCellWidthPc : "процената",
+DlgCellHeight : "Висина",
+DlgCellWordWrap : "Дељење речи",
+DlgCellWordWrapNotSet : "<није постављено>",
+DlgCellWordWrapYes : "Да",
+DlgCellWordWrapNo : "Не",
+DlgCellHorAlign : "Водоравно равнање",
+DlgCellHorAlignNotSet : "<није постављено>",
+DlgCellHorAlignLeft : "Лево",
+DlgCellHorAlignCenter : "Средина",
+DlgCellHorAlignRight: "Десно",
+DlgCellVerAlign : "Вертикално равнање",
+DlgCellVerAlignNotSet : "<није постављено>",
+DlgCellVerAlignTop : "Горње",
+DlgCellVerAlignMiddle : "Средина",
+DlgCellVerAlignBottom : "Доње",
+DlgCellVerAlignBaseline : "Базно",
+DlgCellRowSpan : "Спајање редова",
+DlgCellCollSpan : "Спајање колона",
+DlgCellBackColor : "Боја позадине",
+DlgCellBorderColor : "Боја оквира",
+DlgCellBtnSelect : "Oдабери...",
+
+// Find Dialog
+DlgFindTitle : "Пронађи",
+DlgFindFindBtn : "Пронађи",
+DlgFindNotFoundMsg : "Тражени текст није пронађен.",
+
+// Replace Dialog
+DlgReplaceTitle : "Замени",
+DlgReplaceFindLbl : "Пронађи:",
+DlgReplaceReplaceLbl : "Замени са:",
+DlgReplaceCaseChk : "Разликуј велика и мала слова",
+DlgReplaceReplaceBtn : "Замени",
+DlgReplaceReplAllBtn : "Замени све",
+DlgReplaceWordChk : "Упореди целе речи",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског исецања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl+X).",
+PasteErrorCopy : "Сигурносна подешавања Вашег претраживача не дозвољавају операције аутоматског копирања текста. Молимо Вас да користите пречицу са тастатуре (Ctrl+C).",
+
+PasteAsText : "Залепи као чист текст",
+PasteFromWord : "Залепи из Worda",
+
+DlgPasteMsg2 : "Молимо Вас да залепите унутар доње површине користећи тастатурну пречицу (<STRONG>Ctrl+V</STRONG>) и да притиснете <STRONG>OK</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Игнориши Font Face дефиниције",
+DlgPasteRemoveStyles : "Уклони дефиниције стилова",
+DlgPasteCleanBox : "Обриши све",
+
+// Color Picker
+ColorAutomatic : "Аутоматски",
+ColorMoreColors : "Више боја...",
+
+// Document Properties
+DocProps : "Особине документа",
+
+// Anchor Dialog
+DlgAnchorTitle : "Особине сидра",
+DlgAnchorName : "Име сидра",
+DlgAnchorErrorName : "Молимо Вас да унесете име сидра",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Није у речнику",
+DlgSpellChangeTo : "Измени",
+DlgSpellBtnIgnore : "Игнориши",
+DlgSpellBtnIgnoreAll : "Игнориши све",
+DlgSpellBtnReplace : "Замени",
+DlgSpellBtnReplaceAll : "Замени све",
+DlgSpellBtnUndo : "Врати акцију",
+DlgSpellNoSuggestions : "- Без сугестија -",
+DlgSpellProgress : "Провера спеловања у току...",
+DlgSpellNoMispell : "Провера спеловања завршена: грешке нису пронађене",
+DlgSpellNoChanges : "Провера спеловања завршена: Није измењена ниједна реч",
+DlgSpellOneChange : "Провера спеловања завршена: Измењена је једна реч",
+DlgSpellManyChanges : "Провера спеловања завршена: %1 реч(и) је измењено",
+
+IeSpellDownload : "Провера спеловања није инсталирана. Да ли желите да је скинете са Интернета?",
+
+// Button Dialog
+DlgButtonText : "Текст (вредност)",
+DlgButtonType : "Tип",
+DlgButtonTypeBtn : "Button", //MISSING
+DlgButtonTypeSbm : "Submit", //MISSING
+DlgButtonTypeRst : "Reset", //MISSING
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Назив",
+DlgCheckboxValue : "Вредност",
+DlgCheckboxSelected : "Означено",
+
+// Form Dialog
+DlgFormName : "Назив",
+DlgFormAction : "Aкција",
+DlgFormMethod : "Mетода",
+
+// Select Field Dialog
+DlgSelectName : "Назив",
+DlgSelectValue : "Вредност",
+DlgSelectSize : "Величина",
+DlgSelectLines : "линија",
+DlgSelectChkMulti : "Дозволи вишеструку селекцију",
+DlgSelectOpAvail : "Доступне опције",
+DlgSelectOpText : "Текст",
+DlgSelectOpValue : "Вредност",
+DlgSelectBtnAdd : "Додај",
+DlgSelectBtnModify : "Измени",
+DlgSelectBtnUp : "Горе",
+DlgSelectBtnDown : "Доле",
+DlgSelectBtnSetValue : "Подеси као означену вредност",
+DlgSelectBtnDelete : "Обриши",
+
+// Textarea Dialog
+DlgTextareaName : "Назив",
+DlgTextareaCols : "Број колона",
+DlgTextareaRows : "Број редова",
+
+// Text Field Dialog
+DlgTextName : "Назив",
+DlgTextValue : "Вредност",
+DlgTextCharWidth : "Ширина (карактера)",
+DlgTextMaxChars : "Максимално карактера",
+DlgTextType : "Тип",
+DlgTextTypeText : "Текст",
+DlgTextTypePass : "Лозинка",
+
+// Hidden Field Dialog
+DlgHiddenName : "Назив",
+DlgHiddenValue : "Вредност",
+
+// Bulleted List Dialog
+BulletedListProp : "Особине Bulleted листе",
+NumberedListProp : "Особине набројиве листе",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Тип",
+DlgLstTypeCircle : "Круг",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "Квадрат",
+DlgLstTypeNumbers : "Бројеви (1, 2, 3)",
+DlgLstTypeLCase : "мала слова (a, b, c)",
+DlgLstTypeUCase : "ВЕЛИКА СЛОВА (A, B, C)",
+DlgLstTypeSRoman : "Мале римске цифре (i, ii, iii)",
+DlgLstTypeLRoman : "Велике римске цифре (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Опште особине",
+DlgDocBackTab : "Позадина",
+DlgDocColorsTab : "Боје и маргине",
+DlgDocMetaTab : "Метаподаци",
+
+DlgDocPageTitle : "Наслов странице",
+DlgDocLangDir : "Смер језика",
+DlgDocLangDirLTR : "Слева надесно (LTR)",
+DlgDocLangDirRTL : "Здесна налево (RTL)",
+DlgDocLangCode : "Шифра језика",
+DlgDocCharSet : "Кодирање скупа карактера",
+DlgDocCharSetCE : "Central European", //MISSING
+DlgDocCharSetCT : "Chinese Traditional (Big5)", //MISSING
+DlgDocCharSetCR : "Cyrillic", //MISSING
+DlgDocCharSetGR : "Greek", //MISSING
+DlgDocCharSetJP : "Japanese", //MISSING
+DlgDocCharSetKR : "Korean", //MISSING
+DlgDocCharSetTR : "Turkish", //MISSING
+DlgDocCharSetUN : "Unicode (UTF-8)", //MISSING
+DlgDocCharSetWE : "Western European", //MISSING
+DlgDocCharSetOther : "Остала кодирања скупа карактера",
+
+DlgDocDocType : "Заглавље типа документа",
+DlgDocDocTypeOther : "Остала заглавља типа документа",
+DlgDocIncXHTML : "Улључи XHTML декларације",
+DlgDocBgColor : "Боја позадине",
+DlgDocBgImage : "УРЛ позадинске слике",
+DlgDocBgNoScroll : "Фиксирана позадина",
+DlgDocCText : "Текст",
+DlgDocCLink : "Линк",
+DlgDocCVisited : "Посећени линк",
+DlgDocCActive : "Активни линк",
+DlgDocMargins : "Маргине странице",
+DlgDocMaTop : "Горња",
+DlgDocMaLeft : "Лева",
+DlgDocMaRight : "Десна",
+DlgDocMaBottom : "Доња",
+DlgDocMeIndex : "Кључне речи за индексирање документа (раздвојене зарезом)",
+DlgDocMeDescr : "Опис документа",
+DlgDocMeAuthor : "Аутор",
+DlgDocMeCopy : "Ауторска права",
+DlgDocPreview : "Изглед странице",
+
+// Templates Dialog
+Templates : "Обрасци",
+DlgTemplatesTitle : "Обрасци за садржај",
+DlgTemplatesSelMsg : "Молимо Вас да одаберете образац који ће бити примењен на страницу (тренутни садржај ће бити обрисан):",
+DlgTemplatesLoading : "Учитавам листу образаца. Мало стрпљења...",
+DlgTemplatesNoTpl : "(Нема дефинисаних образаца)",
+DlgTemplatesReplace : "Replace actual contents", //MISSING
+
+// About Dialog
+DlgAboutAboutTab : "О едитору",
+DlgAboutBrowserInfoTab : "Информације о претраживачу",
+DlgAboutLicenseTab : "License", //MISSING
+DlgAboutVersion : "верзија",
+DlgAboutInfo : "За више информација посетите"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/sv.js b/httemplate/elements/fckeditor/editor/lang/sv.js
new file mode 100644
index 000000000..a301a0335
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/sv.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Swedish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Dölj verktygsfält",
+ToolbarExpand : "Visa verktygsfält",
+
+// Toolbar Items and Context Menu
+Save : "Spara",
+NewPage : "Ny sida",
+Preview : "Förhandsgranska",
+Cut : "Klipp ut",
+Copy : "Kopiera",
+Paste : "Klistra in",
+PasteText : "Klistra in som text",
+PasteWord : "Klistra in från Word",
+Print : "Skriv ut",
+SelectAll : "Markera allt",
+RemoveFormat : "Radera formatering",
+InsertLinkLbl : "Länk",
+InsertLink : "Infoga/Redigera länk",
+RemoveLink : "Radera länk",
+Anchor : "Infoga/Redigera ankarlänk",
+InsertImageLbl : "Bild",
+InsertImage : "Infoga/Redigera bild",
+InsertFlashLbl : "Flash",
+InsertFlash : "Infoga/Redigera Flash",
+InsertTableLbl : "Tabell",
+InsertTable : "Infoga/Redigera tabell",
+InsertLineLbl : "Linje",
+InsertLine : "Infoga horisontal linje",
+InsertSpecialCharLbl: "Utökade tecken",
+InsertSpecialChar : "Klistra in utökat tecken",
+InsertSmileyLbl : "Smiley",
+InsertSmiley : "Infoga Smiley",
+About : "Om FCKeditor",
+Bold : "Fet",
+Italic : "Kursiv",
+Underline : "Understruken",
+StrikeThrough : "Genomstruken",
+Subscript : "Nedsänkta tecken",
+Superscript : "Upphöjda tecken",
+LeftJustify : "Vänsterjustera",
+CenterJustify : "Centrera",
+RightJustify : "Högerjustera",
+BlockJustify : "Justera till marginaler",
+DecreaseIndent : "Minska indrag",
+IncreaseIndent : "Öka indrag",
+Undo : "Ångra",
+Redo : "Gör om",
+NumberedListLbl : "Numrerad lista",
+NumberedList : "Infoga/Radera numrerad lista",
+BulletedListLbl : "Punktlista",
+BulletedList : "Infoga/Radera punktlista",
+ShowTableBorders : "Visa tabellkant",
+ShowDetails : "Visa radbrytningar",
+Style : "Anpassad stil",
+FontFormat : "Teckenformat",
+Font : "Typsnitt",
+FontSize : "Storlek",
+TextColor : "Textfärg",
+BGColor : "Bakgrundsfärg",
+Source : "Källa",
+Find : "Sök",
+Replace : "Ersätt",
+SpellCheck : "Stavningskontroll",
+UniversalKeyboard : "Universellt tangentbord",
+PageBreakLbl : "Sidbrytning",
+PageBreak : "Infoga sidbrytning",
+
+Form : "Formulär",
+Checkbox : "Kryssruta",
+RadioButton : "Alternativknapp",
+TextField : "Textfält",
+Textarea : "Textruta",
+HiddenField : "Dolt fält",
+Button : "Knapp",
+SelectionField : "Flervalslista",
+ImageButton : "Bildknapp",
+
+FitWindow : "Anpassa till fönstrets storlek",
+
+// Context Menu
+EditLink : "Redigera länk",
+CellCM : "Cell",
+RowCM : "Rad",
+ColumnCM : "Kolumn",
+InsertRow : "Infoga rad",
+DeleteRows : "Radera rad",
+InsertColumn : "Infoga kolumn",
+DeleteColumns : "Radera kolumn",
+InsertCell : "Infoga cell",
+DeleteCells : "Radera celler",
+MergeCells : "Sammanfoga celler",
+SplitCell : "Separera celler",
+TableDelete : "Radera tabell",
+CellProperties : "Cellegenskaper",
+TableProperties : "Tabellegenskaper",
+ImageProperties : "Bildegenskaper",
+FlashProperties : "Flashegenskaper",
+
+AnchorProp : "Egenskaper för ankarlänk",
+ButtonProp : "Egenskaper för knapp",
+CheckboxProp : "Egenskaper för kryssruta",
+HiddenFieldProp : "Egenskaper för dolt fält",
+RadioButtonProp : "Egenskaper för alternativknapp",
+ImageButtonProp : "Egenskaper för bildknapp",
+TextFieldProp : "Egenskaper för textfält",
+SelectionFieldProp : "Egenskaper för flervalslista",
+TextareaProp : "Egenskaper för textruta",
+FormProp : "Egenskaper för formulär",
+
+FontFormats : "Normal;Formaterad;Adress;Rubrik 1;Rubrik 2;Rubrik 3;Rubrik 4;Rubrik 5;Rubrik 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Bearbetar XHTML. Var god vänta...",
+Done : "Klar",
+PasteWordConfirm : "Texten du vill klistra in verkar vara kopierad från Word. Vill du rensa innan du klistar in?",
+NotCompatiblePaste : "Denna åtgärd är inte tillgängligt för Internet Explorer version 5.5 eller högre. Vill du klistra in utan att rensa?",
+UnknownToolbarItem : "Okänt verktygsfält \"%1\"",
+UnknownCommand : "Okänt kommando \"%1\"",
+NotImplemented : "Kommandot finns ej",
+UnknownToolbarSet : "Verktygsfält \"%1\" finns ej",
+NoActiveX : "Din webläsares säkerhetsinställningar kan begränsa funktionaliteten. Du bör aktivera \"Kör ActiveX kontroller och plug-ins\". Fel och avsaknad av funktioner kan annars uppstå.",
+BrowseServerBlocked : "Kunde Ej öppna resursfönstret. Var god och avaktivera alla popup-blockerare.",
+DialogBlocked : "Kunde Ej öppna dialogfönstret. Var god och avaktivera alla popup-blockerare.",
+
+// Dialogs
+DlgBtnOK : "OK",
+DlgBtnCancel : "Avbryt",
+DlgBtnClose : "Stäng",
+DlgBtnBrowseServer : "Bläddra på server",
+DlgAdvancedTag : "Avancerad",
+DlgOpOther : "Övrigt",
+DlgInfoTab : "Information",
+DlgAlertUrl : "Var god och ange en URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ej angivet>",
+DlgGenId : "Id",
+DlgGenLangDir : "Språkriktning",
+DlgGenLangDirLtr : "Vänster till Höger (VTH)",
+DlgGenLangDirRtl : "Höger till Vänster (HTV)",
+DlgGenLangCode : "Språkkod",
+DlgGenAccessKey : "Behörighetsnyckel",
+DlgGenName : "Namn",
+DlgGenTabIndex : "Tabindex",
+DlgGenLongDescr : "URL-beskrivning",
+DlgGenClass : "Stylesheet class",
+DlgGenTitle : "Titel",
+DlgGenContType : "Innehållstyp",
+DlgGenLinkCharset : "Teckenuppställning",
+DlgGenStyle : "Style",
+
+// Image Dialog
+DlgImgTitle : "Bildegenskaper",
+DlgImgInfoTab : "Bildinformation",
+DlgImgBtnUpload : "Skicka till server",
+DlgImgURL : "URL",
+DlgImgUpload : "Ladda upp",
+DlgImgAlt : "Alternativ text",
+DlgImgWidth : "Bredd",
+DlgImgHeight : "Höjd",
+DlgImgLockRatio : "Lås höjd/bredd förhållanden",
+DlgBtnResetSize : "Återställ storlek",
+DlgImgBorder : "Kant",
+DlgImgHSpace : "Horis. marginal",
+DlgImgVSpace : "Vert. marginal",
+DlgImgAlign : "Justering",
+DlgImgAlignLeft : "Vänster",
+DlgImgAlignAbsBottom: "Absolut nederkant",
+DlgImgAlignAbsMiddle: "Absolut centrering",
+DlgImgAlignBaseline : "Baslinje",
+DlgImgAlignBottom : "Nederkant",
+DlgImgAlignMiddle : "Mitten",
+DlgImgAlignRight : "Höger",
+DlgImgAlignTextTop : "Text överkant",
+DlgImgAlignTop : "Överkant",
+DlgImgPreview : "Förhandsgranska",
+DlgImgAlertUrl : "Var god och ange bildens URL",
+DlgImgLinkTab : "Länk",
+
+// Flash Dialog
+DlgFlashTitle : "Flashegenskaper",
+DlgFlashChkPlay : "Automatisk uppspelning",
+DlgFlashChkLoop : "Upprepa/Loopa",
+DlgFlashChkMenu : "Aktivera Flashmeny",
+DlgFlashScale : "Skala",
+DlgFlashScaleAll : "Visa allt",
+DlgFlashScaleNoBorder : "Ingen ram",
+DlgFlashScaleFit : "Exakt passning",
+
+// Link Dialog
+DlgLnkWindowTitle : "Länk",
+DlgLnkInfoTab : "Länkinformation",
+DlgLnkTargetTab : "Mål",
+
+DlgLnkType : "Länktyp",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Ankare i sidan",
+DlgLnkTypeEMail : "E-post",
+DlgLnkProto : "Protokoll",
+DlgLnkProtoOther : "<övrigt>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Välj ett ankare",
+DlgLnkAnchorByName : "efter ankarnamn",
+DlgLnkAnchorById : "efter objektid",
+DlgLnkNoAnchors : "(Inga ankare kunde hittas)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-postadress",
+DlgLnkEMailSubject : "Ämne",
+DlgLnkEMailBody : "Innehåll",
+DlgLnkUpload : "Ladda upp",
+DlgLnkBtnUpload : "Skicka till servern",
+
+DlgLnkTarget : "Mål",
+DlgLnkTargetFrame : "<ram>",
+DlgLnkTargetPopup : "<popup-fönster>",
+DlgLnkTargetBlank : "Nytt fönster (_blank)",
+DlgLnkTargetParent : "Föregående Window (_parent)",
+DlgLnkTargetSelf : "Detta fönstret (_self)",
+DlgLnkTargetTop : "Översta fönstret (_top)",
+DlgLnkTargetFrameName : "Målets ramnamn",
+DlgLnkPopWinName : "Popup-fönstrets namn",
+DlgLnkPopWinFeat : "Popup-fönstrets egenskaper",
+DlgLnkPopResize : "Kan ändra storlek",
+DlgLnkPopLocation : "Adressfält",
+DlgLnkPopMenu : "Menyfält",
+DlgLnkPopScroll : "Scrolllista",
+DlgLnkPopStatus : "Statusfält",
+DlgLnkPopToolbar : "Verktygsfält",
+DlgLnkPopFullScrn : "Helskärm (endast IE)",
+DlgLnkPopDependent : "Beroende (endest Netscape)",
+DlgLnkPopWidth : "Bredd",
+DlgLnkPopHeight : "Höjd",
+DlgLnkPopLeft : "Position från vänster",
+DlgLnkPopTop : "Position från sidans topp",
+
+DlnLnkMsgNoUrl : "Var god ange länkens URL",
+DlnLnkMsgNoEMail : "Var god ange E-postadress",
+DlnLnkMsgNoAnchor : "Var god ange ett ankare",
+DlnLnkMsgInvPopName : "Popup-rutans namn måste börja med en alfabetisk bokstav och får inte innehålla mellanslag",
+
+// Color Dialog
+DlgColorTitle : "Välj färg",
+DlgColorBtnClear : "Rensa",
+DlgColorHighlight : "Markera",
+DlgColorSelected : "Vald",
+
+// Smiley Dialog
+DlgSmileyTitle : "Infoga smiley",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Välj utökat tecken",
+
+// Table Dialog
+DlgTableTitle : "Tabellegenskaper",
+DlgTableRows : "Rader",
+DlgTableColumns : "Kolumner",
+DlgTableBorder : "Kantstorlek",
+DlgTableAlign : "Justering",
+DlgTableAlignNotSet : "<ej angivet>",
+DlgTableAlignLeft : "Vänster",
+DlgTableAlignCenter : "Centrerad",
+DlgTableAlignRight : "Höger",
+DlgTableWidth : "Bredd",
+DlgTableWidthPx : "pixlar",
+DlgTableWidthPc : "procent",
+DlgTableHeight : "Höjd",
+DlgTableCellSpace : "Cellavstånd",
+DlgTableCellPad : "Cellutfyllnad",
+DlgTableCaption : "Rubrik",
+DlgTableSummary : "Sammanfattning",
+
+// Table Cell Dialog
+DlgCellTitle : "Cellegenskaper",
+DlgCellWidth : "Bredd",
+DlgCellWidthPx : "pixlar",
+DlgCellWidthPc : "procent",
+DlgCellHeight : "Höjd",
+DlgCellWordWrap : "Automatisk radbrytning",
+DlgCellWordWrapNotSet : "<Ej angivet>",
+DlgCellWordWrapYes : "Ja",
+DlgCellWordWrapNo : "Nej",
+DlgCellHorAlign : "Horisontal justering",
+DlgCellHorAlignNotSet : "<Ej angivet>",
+DlgCellHorAlignLeft : "Vänster",
+DlgCellHorAlignCenter : "Centrerad",
+DlgCellHorAlignRight: "Höger",
+DlgCellVerAlign : "Vertikal justering",
+DlgCellVerAlignNotSet : "<Ej angivet>",
+DlgCellVerAlignTop : "Topp",
+DlgCellVerAlignMiddle : "Mitten",
+DlgCellVerAlignBottom : "Nederkant",
+DlgCellVerAlignBaseline : "Underst",
+DlgCellRowSpan : "Radomfång",
+DlgCellCollSpan : "Kolumnomfång",
+DlgCellBackColor : "Bakgrundsfärg",
+DlgCellBorderColor : "Kantfärg",
+DlgCellBtnSelect : "Välj...",
+
+// Find Dialog
+DlgFindTitle : "Sök",
+DlgFindFindBtn : "Sök",
+DlgFindNotFoundMsg : "Angiven text kunde ej hittas.",
+
+// Replace Dialog
+DlgReplaceTitle : "Ersätt",
+DlgReplaceFindLbl : "Sök efter:",
+DlgReplaceReplaceLbl : "Ersätt med:",
+DlgReplaceCaseChk : "Skiftläge",
+DlgReplaceReplaceBtn : "Ersätt",
+DlgReplaceReplAllBtn : "Ersätt alla",
+DlgReplaceWordChk : "Inkludera hela ord",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Säkerhetsinställningar i Er webläsare tillåter inte åtgården Klipp ut. Använd (Ctrl+X) istället.",
+PasteErrorCopy : "Säkerhetsinställningar i Er webläsare tillåter inte åtgården Kopiera. Använd (Ctrl+C) istället",
+
+PasteAsText : "Klistra in som vanlig text",
+PasteFromWord : "Klistra in från Word",
+
+DlgPasteMsg2 : "Var god och klistra in Er text i rutan nedan genom att använda (<STRONG>Ctrl+V</STRONG>) klicka sen på <STRONG>OK</STRONG>.",
+DlgPasteSec : "På grund av din webläsares säkerhetsinställningar kan verktyget inte få åtkomst till urklippsdatan. Var god och använd detta fönster istället.",
+DlgPasteIgnoreFont : "Ignorera typsnittsdefinitioner",
+DlgPasteRemoveStyles : "Radera Stildefinitioner",
+DlgPasteCleanBox : "Töm rutans innehåll",
+
+// Color Picker
+ColorAutomatic : "Automatisk",
+ColorMoreColors : "Fler färger...",
+
+// Document Properties
+DocProps : "Dokumentegenskaper",
+
+// Anchor Dialog
+DlgAnchorTitle : "Ankaregenskaper",
+DlgAnchorName : "Ankarnamn",
+DlgAnchorErrorName : "Var god ange ett ankarnamn",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Saknas i ordlistan",
+DlgSpellChangeTo : "Ändra till",
+DlgSpellBtnIgnore : "Ignorera",
+DlgSpellBtnIgnoreAll : "Ignorera alla",
+DlgSpellBtnReplace : "Ersätt",
+DlgSpellBtnReplaceAll : "Ersätt alla",
+DlgSpellBtnUndo : "Ångra",
+DlgSpellNoSuggestions : "- Förslag saknas -",
+DlgSpellProgress : "Stavningskontroll pågår...",
+DlgSpellNoMispell : "Stavningskontroll slutförd: Inga stavfel påträffades.",
+DlgSpellNoChanges : "Stavningskontroll slutförd: Inga ord rättades.",
+DlgSpellOneChange : "Stavningskontroll slutförd: Ett ord rättades.",
+DlgSpellManyChanges : "Stavningskontroll slutförd: %1 ord rättades.",
+
+IeSpellDownload : "Stavningskontrollen är ej installerad. Vill du göra det nu?",
+
+// Button Dialog
+DlgButtonText : "Text (Värde)",
+DlgButtonType : "Typ",
+DlgButtonTypeBtn : "Knapp",
+DlgButtonTypeSbm : "Skicka",
+DlgButtonTypeRst : "Återställ",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Namn",
+DlgCheckboxValue : "Värde",
+DlgCheckboxSelected : "Vald",
+
+// Form Dialog
+DlgFormName : "Namn",
+DlgFormAction : "Funktion",
+DlgFormMethod : "Metod",
+
+// Select Field Dialog
+DlgSelectName : "Namn",
+DlgSelectValue : "Värde",
+DlgSelectSize : "Storlek",
+DlgSelectLines : "Linjer",
+DlgSelectChkMulti : "Tillåt flerval",
+DlgSelectOpAvail : "Befintliga val",
+DlgSelectOpText : "Text",
+DlgSelectOpValue : "Värde",
+DlgSelectBtnAdd : "Lägg till",
+DlgSelectBtnModify : "Redigera",
+DlgSelectBtnUp : "Upp",
+DlgSelectBtnDown : "Ner",
+DlgSelectBtnSetValue : "Markera som valt värde",
+DlgSelectBtnDelete : "Radera",
+
+// Textarea Dialog
+DlgTextareaName : "Namn",
+DlgTextareaCols : "Kolumner",
+DlgTextareaRows : "Rader",
+
+// Text Field Dialog
+DlgTextName : "Namn",
+DlgTextValue : "Värde",
+DlgTextCharWidth : "Teckenbredd",
+DlgTextMaxChars : "Max antal tecken",
+DlgTextType : "Typ",
+DlgTextTypeText : "Text",
+DlgTextTypePass : "Lösenord",
+
+// Hidden Field Dialog
+DlgHiddenName : "Namn",
+DlgHiddenValue : "Värde",
+
+// Bulleted List Dialog
+BulletedListProp : "Egenskaper för punktlista",
+NumberedListProp : "Egenskaper för numrerad lista",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "Typ",
+DlgLstTypeCircle : "Cirkel",
+DlgLstTypeDisc : "Punkt",
+DlgLstTypeSquare : "Ruta",
+DlgLstTypeNumbers : "Nummer (1, 2, 3)",
+DlgLstTypeLCase : "Gemener (a, b, c)",
+DlgLstTypeUCase : "Versaler (A, B, C)",
+DlgLstTypeSRoman : "Små romerska siffror (i, ii, iii)",
+DlgLstTypeLRoman : "Stora romerska siffror (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Allmän",
+DlgDocBackTab : "Bakgrund",
+DlgDocColorsTab : "Färg och marginal",
+DlgDocMetaTab : "Metadata",
+
+DlgDocPageTitle : "Sidtitel",
+DlgDocLangDir : "Språkriktning",
+DlgDocLangDirLTR : "Vänster till Höger",
+DlgDocLangDirRTL : "Höger till Vänster",
+DlgDocLangCode : "Språkkod",
+DlgDocCharSet : "Teckenuppsättningar",
+DlgDocCharSetCE : "Central Europa",
+DlgDocCharSetCT : "Traditionell Kinesisk (Big5)",
+DlgDocCharSetCR : "Kyrillisk",
+DlgDocCharSetGR : "Grekiska",
+DlgDocCharSetJP : "Japanska",
+DlgDocCharSetKR : "Koreanska",
+DlgDocCharSetTR : "Turkiska",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Väst Europa",
+DlgDocCharSetOther : "Övriga teckenuppsättningar",
+
+DlgDocDocType : "Sidhuvud",
+DlgDocDocTypeOther : "Övriga sidhuvuden",
+DlgDocIncXHTML : "Inkludera XHTML deklaration",
+DlgDocBgColor : "Bakgrundsfärg",
+DlgDocBgImage : "Bakgrundsbildens URL",
+DlgDocBgNoScroll : "Fast bakgrund",
+DlgDocCText : "Text",
+DlgDocCLink : "Länk",
+DlgDocCVisited : "Besökt länk",
+DlgDocCActive : "Aktiv länk",
+DlgDocMargins : "Sidmarginal",
+DlgDocMaTop : "Topp",
+DlgDocMaLeft : "Vänster",
+DlgDocMaRight : "Höger",
+DlgDocMaBottom : "Botten",
+DlgDocMeIndex : "Sidans nyckelord",
+DlgDocMeDescr : "Sidans beskrivning",
+DlgDocMeAuthor : "Författare",
+DlgDocMeCopy : "Upphovsrätt",
+DlgDocPreview : "Förhandsgranska",
+
+// Templates Dialog
+Templates : "Sidmallar",
+DlgTemplatesTitle : "Sidmallar",
+DlgTemplatesSelMsg : "Var god välj en mall att använda med editorn<br>(allt nuvarande innehåll raderas):",
+DlgTemplatesLoading : "Laddar mallar. Var god vänta...",
+DlgTemplatesNoTpl : "(Ingen mall är vald)",
+DlgTemplatesReplace : "Ersätt aktuellt innehåll",
+
+// About Dialog
+DlgAboutAboutTab : "Om",
+DlgAboutBrowserInfoTab : "Webläsare",
+DlgAboutLicenseTab : "Licens",
+DlgAboutVersion : "version",
+DlgAboutInfo : "För mer information se"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/th.js b/httemplate/elements/fckeditor/editor/lang/th.js
new file mode 100644
index 000000000..8c4319a15
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/th.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Thai language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "ซ่อนแถบเครื่องมือ",
+ToolbarExpand : "แสดงแถบเครื่องมือ",
+
+// Toolbar Items and Context Menu
+Save : "บันทึก",
+NewPage : "สร้างหน้าเอกสารใหม่",
+Preview : "ดูหน้าเอกสารตัวอย่าง",
+Cut : "ตัด",
+Copy : "สำเนา",
+Paste : "วาง",
+PasteText : "วางสำเนาจากตัวอักษรธรรมดา",
+PasteWord : "วางสำเนาจากตัวอักษรเวิร์ด",
+Print : "สั่งพิมพ์",
+SelectAll : "เลือกทั้งหมด",
+RemoveFormat : "ล้างรูปแบบ",
+InsertLinkLbl : "ลิงค์เชื่อมโยงเว็บ อีเมล์ รูปภาพ หรือไฟล์อื่นๆ",
+InsertLink : "แทรก/แก้ไข ลิงค์",
+RemoveLink : "ลบ ลิงค์",
+Anchor : "แทรก/แก้ไข Anchor",
+InsertImageLbl : "รูปภาพ",
+InsertImage : "แทรก/แก้ไข รูปภาพ",
+InsertFlashLbl : "ไฟล์ Flash",
+InsertFlash : "แทรก/แก้ไข ไฟล์ Flash",
+InsertTableLbl : "ตาราง",
+InsertTable : "แทรก/แก้ไข ตาราง",
+InsertLineLbl : "เส้นคั่นบรรทัด",
+InsertLine : "แทรกเส้นคั่นบรรทัด",
+InsertSpecialCharLbl: "ตัวอักษรพิเศษ",
+InsertSpecialChar : "แทรกตัวอักษรพิเศษ",
+InsertSmileyLbl : "รูปสื่ออารมณ์",
+InsertSmiley : "แทรกรูปสื่ออารมณ์",
+About : "เกี่ยวกับโปรแกรม FCKeditor",
+Bold : "ตัวหนา",
+Italic : "ตัวเอียง",
+Underline : "ตัวขีดเส้นใต้",
+StrikeThrough : "ตัวขีดเส้นทับ",
+Subscript : "ตัวห้อย",
+Superscript : "ตัวยก",
+LeftJustify : "จัดชิดซ้าย",
+CenterJustify : "จัดกึ่งกลาง",
+RightJustify : "จัดชิดขวา",
+BlockJustify : "จัดพอดีหน้ากระดาษ",
+DecreaseIndent : "ลดระยะย่อหน้า",
+IncreaseIndent : "เพิ่มระยะย่อหน้า",
+Undo : "ยกเลิกคำสั่ง",
+Redo : "ทำซ้ำคำสั่ง",
+NumberedListLbl : "ลำดับรายการแบบตัวเลข",
+NumberedList : "แทรก/แก้ไข ลำดับรายการแบบตัวเลข",
+BulletedListLbl : "ลำดับรายการแบบสัญลักษณ์",
+BulletedList : "แทรก/แก้ไข ลำดับรายการแบบสัญลักษณ์",
+ShowTableBorders : "แสดงขอบของตาราง",
+ShowDetails : "แสดงรายละเอียด",
+Style : "ลักษณะ",
+FontFormat : "รูปแบบ",
+Font : "แบบอักษร",
+FontSize : "ขนาด",
+TextColor : "สีตัวอักษร",
+BGColor : "สีพื้นหลัง",
+Source : "ดูรหัส HTML",
+Find : "ค้นหา",
+Replace : "ค้นหาและแทนที่",
+SpellCheck : "ตรวจการสะกดคำ",
+UniversalKeyboard : "คีย์บอร์ดหลากภาษา",
+PageBreakLbl : "ใส่ตัวแบ่งหน้า Page Break",
+PageBreak : "แทรกตัวแบ่งหน้า Page Break",
+
+Form : "แบบฟอร์ม",
+Checkbox : "เช็คบ๊อก",
+RadioButton : "เรดิโอบัตตอน",
+TextField : "เท็กซ์ฟิลด์",
+Textarea : "เท็กซ์แอเรีย",
+HiddenField : "ฮิดเดนฟิลด์",
+Button : "ปุ่ม",
+SelectionField : "แถบตัวเลือก",
+ImageButton : "ปุ่มแบบรูปภาพ",
+
+FitWindow : "ขยายขนาดตัวอีดิตเตอร์",
+
+// Context Menu
+EditLink : "แก้ไข ลิงค์",
+CellCM : "ช่องตาราง",
+RowCM : "แถว",
+ColumnCM : "คอลัมน์",
+InsertRow : "แทรกแถว",
+DeleteRows : "ลบแถว",
+InsertColumn : "แทรกสดมน์",
+DeleteColumns : "ลบสดมน์",
+InsertCell : "แทรกช่อง",
+DeleteCells : "ลบช่อง",
+MergeCells : "ผสานช่อง",
+SplitCell : "แยกช่อง",
+TableDelete : "ลบตาราง",
+CellProperties : "คุณสมบัติของช่อง",
+TableProperties : "คุณสมบัติของตาราง",
+ImageProperties : "คุณสมบัติของรูปภาพ",
+FlashProperties : "คุณสมบัติของไฟล์ Flash",
+
+AnchorProp : "รายละเอียด Anchor",
+ButtonProp : "รายละเอียดของ ปุ่ม",
+CheckboxProp : "คุณสมบัติของ เช็คบ๊อก",
+HiddenFieldProp : "คุณสมบัติของ ฮิดเดนฟิลด์",
+RadioButtonProp : "คุณสมบัติของ เรดิโอบัตตอน",
+ImageButtonProp : "คุณสมบัติของ ปุ่มแบบรูปภาพ",
+TextFieldProp : "คุณสมบัติของ เท็กซ์ฟิลด์",
+SelectionFieldProp : "คุณสมบัติของ แถบตัวเลือก",
+TextareaProp : "คุณสมบัติของ เท็กแอเรีย",
+FormProp : "คุณสมบัติของ แบบฟอร์ม",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Paragraph (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "โปรแกรมกำลังทำงานด้วยเทคโนโลยี XHTML กรุณารอสักครู่...",
+Done : "โปรแกรมทำงานเสร็จสมบูรณ์",
+PasteWordConfirm : "ข้อมูลที่ท่านต้องการวางลงในแผ่นงาน ถูกจัดรูปแบบจากโปรแกรมเวิร์ด. ท่านต้องการล้างรูปแบบที่มาจากโปรแกรมเวิร์ดหรือไม่?",
+NotCompatiblePaste : "คำสั่งนี้ทำงานในโปรแกรมท่องเว็บ Internet Explorer version รุ่น 5.5 หรือใหม่กว่าเท่านั้น. ท่านต้องการวางตัวอักษรโดยไม่ล้างรูปแบบที่มาจากโปรแกรมเวิร์ดหรือไม่?",
+UnknownToolbarItem : "ไม่สามารถระบุปุ่มเครื่องมือได้ \"%1\"",
+UnknownCommand : "ไม่สามารถระบุชื่อคำสั่งได้ \"%1\"",
+NotImplemented : "ไม่สามารถใช้งานคำสั่งได้",
+UnknownToolbarSet : "ไม่มีการติดตั้งชุดคำสั่งในแถบเครื่องมือ \"%1\" กรุณาติดต่อผู้ดูแลระบบ",
+NoActiveX : "โปรแกรมท่องอินเตอร์เน็ตของท่านไม่อนุญาติให้อีดิตเตอร์ทำงาน \"Run ActiveX controls and plug-ins\". หากไม่อนุญาติให้ใช้งาน ActiveX controls ท่านจะไม่สามารถใช้งานได้อย่างเต็มประสิทธิภาพ.",
+BrowseServerBlocked : "เปิดหน้าต่างป๊อบอัพเพื่อทำงานต่อไม่ได้ กรุณาปิดเครื่องมือป้องกันป๊อบอัพในโปรแกรมท่องอินเตอร์เน็ตของท่านด้วย",
+DialogBlocked : "เปิดหน้าต่างป๊อบอัพเพื่อทำงานต่อไม่ได้ กรุณาปิดเครื่องมือป้องกันป๊อบอัพในโปรแกรมท่องอินเตอร์เน็ตของท่านด้วย",
+
+// Dialogs
+DlgBtnOK : "ตกลง",
+DlgBtnCancel : "ยกเลิก",
+DlgBtnClose : "ปิด",
+DlgBtnBrowseServer : "เปิดหน้าต่างจัดการไฟล์อัพโหลด",
+DlgAdvancedTag : "ขั้นสูง",
+DlgOpOther : "<อื่นๆ>",
+DlgInfoTab : "อินโฟ",
+DlgAlertUrl : "กรุณาระบุ URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<ไม่ระบุ>",
+DlgGenId : "ไอดี",
+DlgGenLangDir : "การเขียน-อ่านภาษา",
+DlgGenLangDirLtr : "จากซ้ายไปขวา (LTR)",
+DlgGenLangDirRtl : "จากขวามาซ้าย (RTL)",
+DlgGenLangCode : "รหัสภาษา",
+DlgGenAccessKey : "แอคเซส คีย์",
+DlgGenName : "ชื่อ",
+DlgGenTabIndex : "ลำดับของ แท็บ",
+DlgGenLongDescr : "คำอธิบายประกอบ URL",
+DlgGenClass : "คลาสของไฟล์กำหนดลักษณะการแสดงผล",
+DlgGenTitle : "คำเกริ่นนำ",
+DlgGenContType : "ชนิดของคำเกริ่นนำ",
+DlgGenLinkCharset : "ลิงค์เชื่อมโยงไปยังชุดตัวอักษร",
+DlgGenStyle : "ลักษณะการแสดงผล",
+
+// Image Dialog
+DlgImgTitle : "คุณสมบัติของ รูปภาพ",
+DlgImgInfoTab : "ข้อมูลของรูปภาพ",
+DlgImgBtnUpload : "อัพโหลดไฟล์ไปเก็บไว้ที่เครื่องแม่ข่าย (เซิร์ฟเวอร์)",
+DlgImgURL : "ที่อยู่อ้างอิง URL",
+DlgImgUpload : "อัพโหลดไฟล์",
+DlgImgAlt : "คำประกอบรูปภาพ",
+DlgImgWidth : "ความกว้าง",
+DlgImgHeight : "ความสูง",
+DlgImgLockRatio : "กำหนดอัตราส่วน กว้าง-สูง แบบคงที่",
+DlgBtnResetSize : "กำหนดรูปเท่าขนาดจริง",
+DlgImgBorder : "ขนาดขอบรูป",
+DlgImgHSpace : "ระยะแนวนอน",
+DlgImgVSpace : "ระยะแนวตั้ง",
+DlgImgAlign : "การจัดวาง",
+DlgImgAlignLeft : "ชิดซ้าย",
+DlgImgAlignAbsBottom: "ชิดด้านล่างสุด",
+DlgImgAlignAbsMiddle: "กึ่งกลาง",
+DlgImgAlignBaseline : "ชิดบรรทัด",
+DlgImgAlignBottom : "ชิดด้านล่าง",
+DlgImgAlignMiddle : "กึ่งกลางแนวตั้ง",
+DlgImgAlignRight : "ชิดขวา",
+DlgImgAlignTextTop : "ใต้ตัวอักษร",
+DlgImgAlignTop : "บนสุด",
+DlgImgPreview : "หน้าเอกสารตัวอย่าง",
+DlgImgAlertUrl : "กรุณาระบุที่อยู่อ้างอิงออนไลน์ของไฟล์รูปภาพ (URL)",
+DlgImgLinkTab : "ลิ้งค์",
+
+// Flash Dialog
+DlgFlashTitle : "คุณสมบัติของไฟล์ Flash",
+DlgFlashChkPlay : "เล่นอัตโนมัติ Auto Play",
+DlgFlashChkLoop : "เล่นวนรอบ Loop",
+DlgFlashChkMenu : "ให้ใช้งานเมนูของ Flash",
+DlgFlashScale : "อัตราส่วน Scale",
+DlgFlashScaleAll : "แสดงให้เห็นทั้งหมด Show all",
+DlgFlashScaleNoBorder : "ไม่แสดงเส้นขอบ No Border",
+DlgFlashScaleFit : "แสดงให้พอดีกับพื้นที่ Exact Fit",
+
+// Link Dialog
+DlgLnkWindowTitle : "ลิงค์เชื่อมโยงเว็บ อีเมล์ รูปภาพ หรือไฟล์อื่นๆ",
+DlgLnkInfoTab : "รายละเอียด",
+DlgLnkTargetTab : "การเปิดหน้าจอ",
+
+DlgLnkType : "ประเภทของลิงค์",
+DlgLnkTypeURL : "ที่อยู่อ้างอิงออนไลน์ (URL)",
+DlgLnkTypeAnchor : "จุดเชื่อมโยง (Anchor)",
+DlgLnkTypeEMail : "ส่งอีเมล์ (E-Mail)",
+DlgLnkProto : "โปรโตคอล",
+DlgLnkProtoOther : "<อื่นๆ>",
+DlgLnkURL : "ที่อยู่อ้างอิงออนไลน์ (URL)",
+DlgLnkAnchorSel : "ระบุข้อมูลของจุดเชื่อมโยง (Anchor)",
+DlgLnkAnchorByName : "ชื่อ",
+DlgLnkAnchorById : "ไอดี",
+DlgLnkNoAnchors : "(ยังไม่มีจุดเชื่อมโยงภายในหน้าเอกสารนี้)", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "อีเมล์ (E-Mail)",
+DlgLnkEMailSubject : "หัวเรื่อง",
+DlgLnkEMailBody : "ข้อความ",
+DlgLnkUpload : "อัพโหลดไฟล์",
+DlgLnkBtnUpload : "บันทึกไฟล์ไว้บนเซิร์ฟเวอร์",
+
+DlgLnkTarget : "การเปิดหน้าลิงค์",
+DlgLnkTargetFrame : "<เปิดในเฟรม>",
+DlgLnkTargetPopup : "<เปิดหน้าจอเล็ก (Pop-up)>",
+DlgLnkTargetBlank : "เปิดหน้าจอใหม่ (_blank)",
+DlgLnkTargetParent : "เปิดในหน้าหลัก (_parent)",
+DlgLnkTargetSelf : "เปิดในหน้าปัจจุบัน (_self)",
+DlgLnkTargetTop : "เปิดในหน้าบนสุด (_top)",
+DlgLnkTargetFrameName : "ชื่อทาร์เก็ตเฟรม",
+DlgLnkPopWinName : "ระบุชื่อหน้าจอเล็ก (Pop-up)",
+DlgLnkPopWinFeat : "คุณสมบัติของหน้าจอเล็ก (Pop-up)",
+DlgLnkPopResize : "ปรับขนาดหน้าจอ",
+DlgLnkPopLocation : "แสดงที่อยู่ของไฟล์",
+DlgLnkPopMenu : "แสดงแถบเมนู",
+DlgLnkPopScroll : "แสดงแถบเลื่อน",
+DlgLnkPopStatus : "แสดงแถบสถานะ",
+DlgLnkPopToolbar : "แสดงแถบเครื่องมือ",
+DlgLnkPopFullScrn : "แสดงเต็มหน้าจอ (IE5.5++ เท่านั้น)",
+DlgLnkPopDependent : "แสดงเต็มหน้าจอ (Netscape)",
+DlgLnkPopWidth : "กว้าง",
+DlgLnkPopHeight : "สูง",
+DlgLnkPopLeft : "พิกัดซ้าย (Left Position)",
+DlgLnkPopTop : "พิกัดบน (Top Position)",
+
+DlnLnkMsgNoUrl : "กรุณาระบุที่อยู่อ้างอิงออนไลน์ (URL)",
+DlnLnkMsgNoEMail : "กรุณาระบุอีเมล์ (E-mail)",
+DlnLnkMsgNoAnchor : "กรุณาระบุจุดเชื่อมโยง (Anchor)",
+DlnLnkMsgInvPopName : "ชื่อของหน้าต่างป๊อบอัพ จะต้องขึ้นต้นด้วยตัวอักษรเท่านั้น และต้องไม่มีช่องว่างในชื่อ",
+
+// Color Dialog
+DlgColorTitle : "เลือกสี",
+DlgColorBtnClear : "ล้างค่ารหัสสี",
+DlgColorHighlight : "ตัวอย่างสี",
+DlgColorSelected : "สีที่เลือก",
+
+// Smiley Dialog
+DlgSmileyTitle : "แทรกสัญลักษณ์สื่ออารมณ์",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "แทรกตัวอักษรพิเศษ",
+
+// Table Dialog
+DlgTableTitle : "คุณสมบัติของ ตาราง",
+DlgTableRows : "แถว",
+DlgTableColumns : "สดมน์",
+DlgTableBorder : "ขนาดเส้นขอบ",
+DlgTableAlign : "การจัดตำแหน่ง",
+DlgTableAlignNotSet : "<ไม่ระบุ>",
+DlgTableAlignLeft : "ชิดซ้าย",
+DlgTableAlignCenter : "กึ่งกลาง",
+DlgTableAlignRight : "ชิดขวา",
+DlgTableWidth : "กว้าง",
+DlgTableWidthPx : "จุดสี",
+DlgTableWidthPc : "เปอร์เซ็น",
+DlgTableHeight : "สูง",
+DlgTableCellSpace : "ระยะแนวนอนน",
+DlgTableCellPad : "ระยะแนวตั้ง",
+DlgTableCaption : "หัวเรื่องของตาราง",
+DlgTableSummary : "สรุปความ",
+
+// Table Cell Dialog
+DlgCellTitle : "คุณสมบัติของ ช่อง",
+DlgCellWidth : "กว้าง",
+DlgCellWidthPx : "จุดสี",
+DlgCellWidthPc : "เปอร์เซ็น",
+DlgCellHeight : "สูง",
+DlgCellWordWrap : "ตัดบรรทัดอัตโนมัติ",
+DlgCellWordWrapNotSet : "<ไม่ระบุ>",
+DlgCellWordWrapYes : "ใ่ช่",
+DlgCellWordWrapNo : "ไม่",
+DlgCellHorAlign : "การจัดวางแนวนอน",
+DlgCellHorAlignNotSet : "<ไม่ระบุ>",
+DlgCellHorAlignLeft : "ชิดซ้าย",
+DlgCellHorAlignCenter : "กึ่งกลาง",
+DlgCellHorAlignRight: "ชิดขวา",
+DlgCellVerAlign : "การจัดวางแนวตั้ง",
+DlgCellVerAlignNotSet : "<ไม่ระบุ>",
+DlgCellVerAlignTop : "บนสุด",
+DlgCellVerAlignMiddle : "กึ่งกลาง",
+DlgCellVerAlignBottom : "ล่างสุด",
+DlgCellVerAlignBaseline : "อิงบรรทัด",
+DlgCellRowSpan : "จำนวนแถวที่คร่อมกัน",
+DlgCellCollSpan : "จำนวนสดมน์ที่คร่อมกัน",
+DlgCellBackColor : "สีพื้นหลัง",
+DlgCellBorderColor : "สีเส้นขอบ",
+DlgCellBtnSelect : "เลือก..",
+
+// Find Dialog
+DlgFindTitle : "ค้นหา",
+DlgFindFindBtn : "ค้นหา",
+DlgFindNotFoundMsg : "ไม่พบคำที่ค้นหา.",
+
+// Replace Dialog
+DlgReplaceTitle : "ค้นหาและแทนที่",
+DlgReplaceFindLbl : "ค้นหาคำว่า:",
+DlgReplaceReplaceLbl : "แทนที่ด้วย:",
+DlgReplaceCaseChk : "ตัวโหญ่-เล็ก ต้องตรงกัน",
+DlgReplaceReplaceBtn : "แทนที่",
+DlgReplaceReplAllBtn : "แทนที่ทั้งหมดที่พบ",
+DlgReplaceWordChk : "ต้องตรงกันทุกคำ",
+
+// Paste Operations / Dialog
+PasteErrorCut : "ไม่สามารถตัดข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl และตัว X พร้อมกัน).",
+PasteErrorCopy : "ไม่สามารถสำเนาข้อความที่เลือกไว้ได้เนื่องจากการกำหนดค่าระดับความปลอดภัย. กรุณาใช้ปุ่มลัดเพื่อวางข้อความแทน (กดปุ่ม Ctrl และตัว C พร้อมกัน).",
+
+PasteAsText : "วางแบบตัวอักษรธรรมดา",
+PasteFromWord : "วางแบบตัวอักษรจากโปรแกรมเวิร์ด",
+
+DlgPasteMsg2 : "กรุณาใช้คีย์บอร์ดเท่านั้น โดยกดปุ๋ม (<strong>Ctrl และ V</strong>)พร้อมๆกัน และกด <strong>OK</strong>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "ไม่สนใจ Font Face definitions",
+DlgPasteRemoveStyles : "ลบ Styles definitions",
+DlgPasteCleanBox : "ล้างข้อมูลใน Box",
+
+// Color Picker
+ColorAutomatic : "สีอัตโนมัติ",
+ColorMoreColors : "เลือกสีอื่นๆ...",
+
+// Document Properties
+DocProps : "คุณสมบัติของเอกสาร",
+
+// Anchor Dialog
+DlgAnchorTitle : "คุณสมบัติของ Anchor",
+DlgAnchorName : "ชื่อ Anchor",
+DlgAnchorErrorName : "กรุณาระบุชื่อของ Anchor",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "ไม่พบในดิกชันนารี",
+DlgSpellChangeTo : "แก้ไขเป็น",
+DlgSpellBtnIgnore : "ยกเว้น",
+DlgSpellBtnIgnoreAll : "ยกเว้นทั้งหมด",
+DlgSpellBtnReplace : "แทนที่",
+DlgSpellBtnReplaceAll : "แทนที่ทั้งหมด",
+DlgSpellBtnUndo : "ยกเลิก",
+DlgSpellNoSuggestions : "- ไม่มีคำแนะนำใดๆ -",
+DlgSpellProgress : "กำลังตรวจสอบคำสะกด...",
+DlgSpellNoMispell : "ตรวจสอบคำสะกดเสร็จสิ้น: ไม่พบคำสะกดผิด",
+DlgSpellNoChanges : "ตรวจสอบคำสะกดเสร็จสิ้น: ไม่มีการแก้คำใดๆ",
+DlgSpellOneChange : "ตรวจสอบคำสะกดเสร็จสิ้น: แก้ไข1คำ",
+DlgSpellManyChanges : "ตรวจสอบคำสะกดเสร็จสิ้น:: แก้ไข %1 คำ",
+
+IeSpellDownload : "ไม่ได้ติดตั้งระบบตรวจสอบคำสะกด. ต้องการติดตั้งไหมครับ?",
+
+// Button Dialog
+DlgButtonText : "ข้อความ (ค่าตัวแปร)",
+DlgButtonType : "ข้อความ",
+DlgButtonTypeBtn : "Button",
+DlgButtonTypeSbm : "Submit",
+DlgButtonTypeRst : "Reset",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "ชื่อ",
+DlgCheckboxValue : "ค่าตัวแปร",
+DlgCheckboxSelected : "เลือกเป็นค่าเริ่มต้น",
+
+// Form Dialog
+DlgFormName : "ชื่อ",
+DlgFormAction : "แอคชั่น",
+DlgFormMethod : "เมธอด",
+
+// Select Field Dialog
+DlgSelectName : "ชื่อ",
+DlgSelectValue : "ค่าตัวแปร",
+DlgSelectSize : "ขนาด",
+DlgSelectLines : "บรรทัด",
+DlgSelectChkMulti : "เลือกหลายค่าได้",
+DlgSelectOpAvail : "รายการตัวเลือก",
+DlgSelectOpText : "ข้อความ",
+DlgSelectOpValue : "ค่าตัวแปร",
+DlgSelectBtnAdd : "เพิ่ม",
+DlgSelectBtnModify : "แก้ไข",
+DlgSelectBtnUp : "บน",
+DlgSelectBtnDown : "ล่าง",
+DlgSelectBtnSetValue : "เลือกเป็นค่าเริ่มต้น",
+DlgSelectBtnDelete : "ลบ",
+
+// Textarea Dialog
+DlgTextareaName : "ชื่อ",
+DlgTextareaCols : "สดมภ์",
+DlgTextareaRows : "แถว",
+
+// Text Field Dialog
+DlgTextName : "ชื่อ",
+DlgTextValue : "ค่าตัวแปร",
+DlgTextCharWidth : "ความกว้าง",
+DlgTextMaxChars : "จำนวนตัวอักษรสูงสุด",
+DlgTextType : "ชนิด",
+DlgTextTypeText : "ข้อความ",
+DlgTextTypePass : "รหัสผ่าน",
+
+// Hidden Field Dialog
+DlgHiddenName : "ชื่อ",
+DlgHiddenValue : "ค่าตัวแปร",
+
+// Bulleted List Dialog
+BulletedListProp : "คุณสมบัติของ บูลเล็ตลิสต์",
+NumberedListProp : "คุณสมบัติของ นัมเบอร์ลิสต์",
+DlgLstStart : "Start", //MISSING
+DlgLstType : "ชนิด",
+DlgLstTypeCircle : "รูปวงกลม",
+DlgLstTypeDisc : "Disc", //MISSING
+DlgLstTypeSquare : "รูปสี่เหลี่ยม",
+DlgLstTypeNumbers : "หมายเลข (1, 2, 3)",
+DlgLstTypeLCase : "ตัวพิมพ์เล็ก (a, b, c)",
+DlgLstTypeUCase : "ตัวพิมพ์ใหญ่ (A, B, C)",
+DlgLstTypeSRoman : "เลขโรมันพิมพ์เล็ก (i, ii, iii)",
+DlgLstTypeLRoman : "เลขโรมันพิมพ์ใหญ่ (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "ลักษณะทั่วไปของเอกสาร",
+DlgDocBackTab : "พื้นหลัง",
+DlgDocColorsTab : "สีและระยะขอบ",
+DlgDocMetaTab : "ข้อมูลสำหรับเสิร์ชเอนจิ้น",
+
+DlgDocPageTitle : "ชื่อไตเติ้ล",
+DlgDocLangDir : "การอ่านภาษา",
+DlgDocLangDirLTR : "จากซ้ายไปขวา (LTR)",
+DlgDocLangDirRTL : "จากขวาไปซ้าย (RTL)",
+DlgDocLangCode : "รหัสภาษา",
+DlgDocCharSet : "ชุดตัวอักษร",
+DlgDocCharSetCE : "Central European",
+DlgDocCharSetCT : "Chinese Traditional (Big5)",
+DlgDocCharSetCR : "Cyrillic",
+DlgDocCharSetGR : "Greek",
+DlgDocCharSetJP : "Japanese",
+DlgDocCharSetKR : "Korean",
+DlgDocCharSetTR : "Turkish",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Western European",
+DlgDocCharSetOther : "ชุดตัวอักษรอื่นๆ",
+
+DlgDocDocType : "ประเภทของเอกสาร",
+DlgDocDocTypeOther : "ประเภทเอกสารอื่นๆ",
+DlgDocIncXHTML : "รวมเอา XHTML Declarations ไว้ด้วย",
+DlgDocBgColor : "สีพื้นหลัง",
+DlgDocBgImage : "ที่อยู่อ้างอิงออนไลน์ของรูปพื้นหลัง (Image URL)",
+DlgDocBgNoScroll : "พื้นหลังแบบไม่มีแถบเลื่อน",
+DlgDocCText : "ข้อความ",
+DlgDocCLink : "ลิงค์",
+DlgDocCVisited : "ลิงค์ที่เคยคลิ้กแล้ว Visited Link",
+DlgDocCActive : "ลิงค์ที่กำลังคลิ้ก Active Link",
+DlgDocMargins : "ระยะขอบของหน้าเอกสาร",
+DlgDocMaTop : "ด้านบน",
+DlgDocMaLeft : "ด้านซ้าย",
+DlgDocMaRight : "ด้านขวา",
+DlgDocMaBottom : "ด้านล่าง",
+DlgDocMeIndex : "คำสำคัญอธิบายเอกสาร (คั่นคำด้วย คอมม่า)",
+DlgDocMeDescr : "ประโยคอธิบายเกี่ยวกับเอกสาร",
+DlgDocMeAuthor : "ผู้สร้างเอกสาร",
+DlgDocMeCopy : "สงวนลิขสิทธิ์",
+DlgDocPreview : "ตัวอย่างหน้าเอกสาร",
+
+// Templates Dialog
+Templates : "เทมเพลต",
+DlgTemplatesTitle : "เทมเพลตของส่วนเนื้อหาเว็บไซต์",
+DlgTemplatesSelMsg : "กรุณาเลือก เทมเพลต เพื่อนำไปแก้ไขในอีดิตเตอร์<br />(เนื้อหาส่วนนี้จะหายไป):",
+DlgTemplatesLoading : "กำลังโหลดรายการเทมเพลตทั้งหมด...",
+DlgTemplatesNoTpl : "(ยังไม่มีการกำหนดเทมเพลต)",
+DlgTemplatesReplace : "แทนที่เนื้อหาเว็บไซต์ที่เลือก",
+
+// About Dialog
+DlgAboutAboutTab : "เกี่ยวกับโปรแกรม",
+DlgAboutBrowserInfoTab : "โปรแกรมท่องเว็บที่ท่านใช้",
+DlgAboutLicenseTab : "ลิขสิทธิ์",
+DlgAboutVersion : "รุ่น",
+DlgAboutInfo : "For further information go to" //MISSING
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/tr.js b/httemplate/elements/fckeditor/editor/lang/tr.js
new file mode 100644
index 000000000..53b371ec7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/tr.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Turkish language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Araç Çubuğunu Kapat",
+ToolbarExpand : "Araç Çubuğunu Aç",
+
+// Toolbar Items and Context Menu
+Save : "Kaydet",
+NewPage : "Yeni Sayfa",
+Preview : "Ön İzleme",
+Cut : "Kes",
+Copy : "Kopyala",
+Paste : "Yapıştır",
+PasteText : "Düzyazı Olarak Yapıştır",
+PasteWord : "Word'den Yapıştır",
+Print : "Yazdır",
+SelectAll : "Tümünü Seç",
+RemoveFormat : "Biçimi Kaldır",
+InsertLinkLbl : "Köprü",
+InsertLink : "Köprü Ekle/Düzenle",
+RemoveLink : "Köprü Kaldır",
+Anchor : "Çapa Ekle/Düzenle",
+InsertImageLbl : "Resim",
+InsertImage : "Resim Ekle/Düzenle",
+InsertFlashLbl : "Flash",
+InsertFlash : "Flash Ekle/Düzenle",
+InsertTableLbl : "Tablo",
+InsertTable : "Tablo Ekle/Düzenle",
+InsertLineLbl : "Satır",
+InsertLine : "Yatay Satır Ekle",
+InsertSpecialCharLbl: "Özel Karakter",
+InsertSpecialChar : "Özel Karakter Ekle",
+InsertSmileyLbl : "İfade",
+InsertSmiley : "İfade Ekle",
+About : "FCKeditor Hakkında",
+Bold : "Kalın",
+Italic : "İtalik",
+Underline : "Altı Çizgili",
+StrikeThrough : "Üstü Çizgili",
+Subscript : "Alt Simge",
+Superscript : "Üst Simge",
+LeftJustify : "Sola Dayalı",
+CenterJustify : "Ortalanmış",
+RightJustify : "Sağa Dayalı",
+BlockJustify : "İki Kenara Yaslanmış",
+DecreaseIndent : "Sekme Azalt",
+IncreaseIndent : "Sekme Arttır",
+Undo : "Geri Al",
+Redo : "Tekrarla",
+NumberedListLbl : "Numaralı Liste",
+NumberedList : "Numaralı Liste Ekle/Kaldır",
+BulletedListLbl : "Simgeli Liste",
+BulletedList : "Simgeli Liste Ekle/Kaldır",
+ShowTableBorders : "Tablo Kenarlarını Göster",
+ShowDetails : "Detayları Göster",
+Style : "Biçem",
+FontFormat : "Biçim",
+Font : "Yazı Türü",
+FontSize : "Boyut",
+TextColor : "Yazı Rengi",
+BGColor : "Arka Renk",
+Source : "Kaynak",
+Find : "Bul",
+Replace : "Değiştir",
+SpellCheck : "Yazım Denetimi",
+UniversalKeyboard : "Evrensel Klavye",
+PageBreakLbl : "Sayfa sonu",
+PageBreak : "Sayfa Sonu Ekle",
+
+Form : "Form",
+Checkbox : "Onay Kutusu",
+RadioButton : "Seçenek Düğmesi",
+TextField : "Metin Girişi",
+Textarea : "Çok Satırlı Metin",
+HiddenField : "Gizli Veri",
+Button : "Düğme",
+SelectionField : "Seçim Menüsü",
+ImageButton : "Resimli Düğme",
+
+FitWindow : "Düzenleyici boyutunu büyüt",
+
+// Context Menu
+EditLink : "Köprü Düzenle",
+CellCM : "Hücre",
+RowCM : "Satır",
+ColumnCM : "Sütun",
+InsertRow : "Satır Ekle",
+DeleteRows : "Satır Sil",
+InsertColumn : "Sütun Ekle",
+DeleteColumns : "Sütun Sil",
+InsertCell : "Hücre Ekle",
+DeleteCells : "Hücre Sil",
+MergeCells : "Hücreleri Birleştir",
+SplitCell : "Hücre Böl",
+TableDelete : "Tabloyu Sil",
+CellProperties : "Hücre Özellikleri",
+TableProperties : "Tablo Özellikleri",
+ImageProperties : "Resim Özellikleri",
+FlashProperties : "Flash Özellikleri",
+
+AnchorProp : "Çapa Özellikleri",
+ButtonProp : "Düğme Özellikleri",
+CheckboxProp : "Onay Kutusu Özellikleri",
+HiddenFieldProp : "Gizli Veri Özellikleri",
+RadioButtonProp : "Seçenek Düğmesi Özellikleri",
+ImageButtonProp : "Resimli Düğme Özellikleri",
+TextFieldProp : "Metin Girişi Özellikleri",
+SelectionFieldProp : "Seçim Menüsü Özellikleri",
+TextareaProp : "Çok Satırlı Metin Özellikleri",
+FormProp : "Form Özellikleri",
+
+FontFormats : "Normal;Biçimli;Adres;Başlık 1;Başlık 2;Başlık 3;Başlık 4;Başlık 5;Başlık 6;Paragraf (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "XHTML işleniyor. Lütfen bekleyin...",
+Done : "Bitti",
+PasteWordConfirm : "Yapıştırdığınız yazı Word'den gelmişe benziyor. Yapıştırmadan önce gereksiz eklentileri silmek ister misiniz?",
+NotCompatiblePaste : "Bu komut Internet Explorer 5.5 ve ileriki sürümleri için mevcuttur. Temizlenmeden yapıştırılmasını ister misiniz ?",
+UnknownToolbarItem : "Bilinmeyen araç çubugu öğesi \"%1\"",
+UnknownCommand : "Bilinmeyen komut \"%1\"",
+NotImplemented : "Komut uyarlanamadı",
+UnknownToolbarSet : "\"%1\" araç çubuğu öğesi mevcut değil",
+NoActiveX : "Kullandığınız tarayıcının güvenlik ayarları bazı özelliklerin kullanılmasını engelliyor. Bu özelliklerin çalışması için \"Run ActiveX controls and plug-ins (Activex ve eklentileri çalıştır)\" seçeneğinin aktif yapılması gerekiyor. Kullanılamayan eklentiler ve hatalar konusunda daha fazla bilgi sahibi olun.",
+BrowseServerBlocked : "Kaynak tarayıcısı açılamadı. Tüm \"popup blocker\" programlarının devre dışı olduğundan emin olun. (Yahoo toolbar, Msn toolbar, Google toolbar gibi)",
+DialogBlocked : "Diyalog açmak mümkün olmadı. Tüm \"Popup Blocker\" programlarının devre dışı olduğundan emin olun.",
+
+// Dialogs
+DlgBtnOK : "Tamam",
+DlgBtnCancel : "İptal",
+DlgBtnClose : "Kapat",
+DlgBtnBrowseServer : "Sunucuyu Gez",
+DlgAdvancedTag : "Gelişmiş",
+DlgOpOther : "<Diğer>",
+DlgInfoTab : "Bilgi",
+DlgAlertUrl : "Lütfen URL girin",
+
+// General Dialogs Labels
+DlgGenNotSet : "<tanımlanmamış>",
+DlgGenId : "Kimlik",
+DlgGenLangDir : "Dil Yönü",
+DlgGenLangDirLtr : "Soldan Sağa (LTR)",
+DlgGenLangDirRtl : "Sağdan Sola (RTL)",
+DlgGenLangCode : "Dil Kodlaması",
+DlgGenAccessKey : "Erişim Tuşu",
+DlgGenName : "Ad",
+DlgGenTabIndex : "Sekme İndeksi",
+DlgGenLongDescr : "Uzun Tanımlı URL",
+DlgGenClass : "Biçem Sayfası Sınıfları",
+DlgGenTitle : "Danışma Başlığı",
+DlgGenContType : "Danışma İçerik Türü",
+DlgGenLinkCharset : "Bağlı Kaynak Karakter Gurubu",
+DlgGenStyle : "Biçem",
+
+// Image Dialog
+DlgImgTitle : "Resim Özellikleri",
+DlgImgInfoTab : "Resim Bilgisi",
+DlgImgBtnUpload : "Sunucuya Yolla",
+DlgImgURL : "URL",
+DlgImgUpload : "Karşıya Yükle",
+DlgImgAlt : "Alternatif Yazı",
+DlgImgWidth : "Genişlik",
+DlgImgHeight : "Yükseklik",
+DlgImgLockRatio : "Oranı Kilitle",
+DlgBtnResetSize : "Boyutu Başa Döndür",
+DlgImgBorder : "Kenar",
+DlgImgHSpace : "Yatay Boşluk",
+DlgImgVSpace : "Dikey Boşluk",
+DlgImgAlign : "Hizalama",
+DlgImgAlignLeft : "Sol",
+DlgImgAlignAbsBottom: "Tam Altı",
+DlgImgAlignAbsMiddle: "Tam Ortası",
+DlgImgAlignBaseline : "Taban Çizgisi",
+DlgImgAlignBottom : "Alt",
+DlgImgAlignMiddle : "Orta",
+DlgImgAlignRight : "Sağ",
+DlgImgAlignTextTop : "Yazı Tepeye",
+DlgImgAlignTop : "Tepe",
+DlgImgPreview : "Ön İzleme",
+DlgImgAlertUrl : "Lütfen resmin URL'sini yazınız",
+DlgImgLinkTab : "Köprü",
+
+// Flash Dialog
+DlgFlashTitle : "Flash Özellikleri",
+DlgFlashChkPlay : "Otomatik Oynat",
+DlgFlashChkLoop : "Döngü",
+DlgFlashChkMenu : "Flash Menüsünü Kullan",
+DlgFlashScale : "Boyutlandır",
+DlgFlashScaleAll : "Hepsini Göster",
+DlgFlashScaleNoBorder : "Kenar Yok",
+DlgFlashScaleFit : "Tam Sığdır",
+
+// Link Dialog
+DlgLnkWindowTitle : "Köprü",
+DlgLnkInfoTab : "Köprü Bilgisi",
+DlgLnkTargetTab : "Hedef",
+
+DlgLnkType : "Köprü Türü",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Bu sayfada çapa",
+DlgLnkTypeEMail : "E-Posta",
+DlgLnkProto : "Protokol",
+DlgLnkProtoOther : "<diğer>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Çapa Seç",
+DlgLnkAnchorByName : "Çapa Adı ile",
+DlgLnkAnchorById : "Eleman Kimlik Numarası ile",
+DlgLnkNoAnchors : "<Bu belgede hiç çapa yok>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "E-Posta Adresi",
+DlgLnkEMailSubject : "İleti Konusu",
+DlgLnkEMailBody : "İleti Gövdesi",
+DlgLnkUpload : "Karşıya Yükle",
+DlgLnkBtnUpload : "Sunucuya Gönder",
+
+DlgLnkTarget : "Hedef",
+DlgLnkTargetFrame : "<çerçeve>",
+DlgLnkTargetPopup : "<yeni açılan pencere>",
+DlgLnkTargetBlank : "Yeni Pencere(_blank)",
+DlgLnkTargetParent : "Anne Pencere (_parent)",
+DlgLnkTargetSelf : "Kendi Penceresi (_self)",
+DlgLnkTargetTop : "En Üst Pencere (_top)",
+DlgLnkTargetFrameName : "Hedef Çerçeve Adı",
+DlgLnkPopWinName : "Yeni Açılan Pencere Adı",
+DlgLnkPopWinFeat : "Yeni Açılan Pencere Özellikleri",
+DlgLnkPopResize : "Boyutlandırılabilir",
+DlgLnkPopLocation : "Yer Çubuğu",
+DlgLnkPopMenu : "Menü Çubuğu",
+DlgLnkPopScroll : "Kaydırma Çubukları",
+DlgLnkPopStatus : "Durum Çubuğu",
+DlgLnkPopToolbar : "Araç Çubuğu",
+DlgLnkPopFullScrn : "Tam Ekran (IE)",
+DlgLnkPopDependent : "Bağımlı (Netscape)",
+DlgLnkPopWidth : "Genişlik",
+DlgLnkPopHeight : "Yükseklik",
+DlgLnkPopLeft : "Sola Göre Konum",
+DlgLnkPopTop : "Yukarıya Göre Konum",
+
+DlnLnkMsgNoUrl : "Lütfen köprü URL'sini yazın",
+DlnLnkMsgNoEMail : "Lütfen E-posta adresini yazın",
+DlnLnkMsgNoAnchor : "Lütfen bir çapa seçin",
+DlnLnkMsgInvPopName : "Açılır pencere adı abecesel bir karakterle başlamalı ve boşluk içermemelidir",
+
+// Color Dialog
+DlgColorTitle : "Renk Seç",
+DlgColorBtnClear : "Temizle",
+DlgColorHighlight : "Vurgula",
+DlgColorSelected : "Seçilmiş",
+
+// Smiley Dialog
+DlgSmileyTitle : "İfade Ekle",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Özel Karakter Seç",
+
+// Table Dialog
+DlgTableTitle : "Tablo Özellikleri",
+DlgTableRows : "Satırlar",
+DlgTableColumns : "Sütunlar",
+DlgTableBorder : "Kenar Kalınlığı",
+DlgTableAlign : "Hizalama",
+DlgTableAlignNotSet : "<Tanımlanmamış>",
+DlgTableAlignLeft : "Sol",
+DlgTableAlignCenter : "Merkez",
+DlgTableAlignRight : "Sağ",
+DlgTableWidth : "Genişlik",
+DlgTableWidthPx : "piksel",
+DlgTableWidthPc : "yüzde",
+DlgTableHeight : "Yükseklik",
+DlgTableCellSpace : "Izgara kalınlığı",
+DlgTableCellPad : "Izgara yazı arası",
+DlgTableCaption : "Başlık",
+DlgTableSummary : "Özet",
+
+// Table Cell Dialog
+DlgCellTitle : "Hücre Özellikleri",
+DlgCellWidth : "Genişlik",
+DlgCellWidthPx : "piksel",
+DlgCellWidthPc : "yüzde",
+DlgCellHeight : "Yükseklik",
+DlgCellWordWrap : "Sözcük Kaydır",
+DlgCellWordWrapNotSet : "<Tanımlanmamış>",
+DlgCellWordWrapYes : "Evet",
+DlgCellWordWrapNo : "Hayır",
+DlgCellHorAlign : "Yatay Hizalama",
+DlgCellHorAlignNotSet : "<Tanımlanmamış>",
+DlgCellHorAlignLeft : "Sol",
+DlgCellHorAlignCenter : "Merkez",
+DlgCellHorAlignRight: "Sağ",
+DlgCellVerAlign : "Dikey Hizalama",
+DlgCellVerAlignNotSet : "<Tanımlanmamış>",
+DlgCellVerAlignTop : "Tepe",
+DlgCellVerAlignMiddle : "Orta",
+DlgCellVerAlignBottom : "Alt",
+DlgCellVerAlignBaseline : "Taban Çizgisi",
+DlgCellRowSpan : "Satır Kapla",
+DlgCellCollSpan : "Sütun Kapla",
+DlgCellBackColor : "Arka Plan Rengi",
+DlgCellBorderColor : "Kenar Rengi",
+DlgCellBtnSelect : "Seç...",
+
+// Find Dialog
+DlgFindTitle : "Bul",
+DlgFindFindBtn : "Bul",
+DlgFindNotFoundMsg : "Belirtilen yazı bulunamadı.",
+
+// Replace Dialog
+DlgReplaceTitle : "Değiştir",
+DlgReplaceFindLbl : "Aranan:",
+DlgReplaceReplaceLbl : "Bununla değiştir:",
+DlgReplaceCaseChk : "Büyük/küçük harf duyarlı",
+DlgReplaceReplaceBtn : "Değiştir",
+DlgReplaceReplAllBtn : "Tümünü Değiştir",
+DlgReplaceWordChk : "Kelimenin tamamı uysun",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kesme işlemine izin vermiyor. İşlem için (Ctrl+X) tuşlarını kullanın.",
+PasteErrorCopy : "Gezgin yazılımınızın güvenlik ayarları düzenleyicinin otomatik kopyalama işlemine izin vermiyor. İşlem için (Ctrl+C) tuşlarını kullanın.",
+
+PasteAsText : "Düz Metin Olarak Yapıştır",
+PasteFromWord : "Word'den yapıştır",
+
+DlgPasteMsg2 : "Lütfen aşağıdaki kutunun içine yapıştırın. (<STRONG>Ctrl+V</STRONG>) ve <STRONG>Tamam</STRONG> butonunu tıklayın.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Yazı Tipi tanımlarını yoksay",
+DlgPasteRemoveStyles : "Biçem Tanımlarını çıkar",
+DlgPasteCleanBox : "Temizlik Kutusu",
+
+// Color Picker
+ColorAutomatic : "Otomatik",
+ColorMoreColors : "Diğer renkler...",
+
+// Document Properties
+DocProps : "Belge Özellikleri",
+
+// Anchor Dialog
+DlgAnchorTitle : "Çapa Özellikleri",
+DlgAnchorName : "Çapa Adı",
+DlgAnchorErrorName : "Lütfen çapa için ad giriniz",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Sözlükte Yok",
+DlgSpellChangeTo : "Şuna değiştir:",
+DlgSpellBtnIgnore : "Yoksay",
+DlgSpellBtnIgnoreAll : "Tümünü Yoksay",
+DlgSpellBtnReplace : "Değiştir",
+DlgSpellBtnReplaceAll : "Tümünü Değiştir",
+DlgSpellBtnUndo : "Geri Al",
+DlgSpellNoSuggestions : "- Öneri Yok -",
+DlgSpellProgress : "Yazım denetimi işlemde...",
+DlgSpellNoMispell : "Yazım denetimi tamamlandı: Yanlış yazıma rastlanmadı",
+DlgSpellNoChanges : "Yazım denetimi tamamlandı: Hiçbir kelime değiştirilmedi",
+DlgSpellOneChange : "Yazım denetimi tamamlandı: Bir kelime değiştirildi",
+DlgSpellManyChanges : "Yazım denetimi tamamlandı: %1 kelime değiştirildi",
+
+IeSpellDownload : "Yazım denetimi yüklenmemiş. Şimdi yüklemek ister misiniz?",
+
+// Button Dialog
+DlgButtonText : "Metin (Değer)",
+DlgButtonType : "Tip",
+DlgButtonTypeBtn : "Düğme",
+DlgButtonTypeSbm : "Gönder",
+DlgButtonTypeRst : "Sıfırla",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Ad",
+DlgCheckboxValue : "Değer",
+DlgCheckboxSelected : "Seçili",
+
+// Form Dialog
+DlgFormName : "Ad",
+DlgFormAction : "İşlem",
+DlgFormMethod : "Yöntem",
+
+// Select Field Dialog
+DlgSelectName : "Ad",
+DlgSelectValue : "Değer",
+DlgSelectSize : "Boyut",
+DlgSelectLines : "satır",
+DlgSelectChkMulti : "Çoklu seçime izin ver",
+DlgSelectOpAvail : "Mevcut Seçenekler",
+DlgSelectOpText : "Metin",
+DlgSelectOpValue : "Değer",
+DlgSelectBtnAdd : "Ekle",
+DlgSelectBtnModify : "Düzenle",
+DlgSelectBtnUp : "Yukarı",
+DlgSelectBtnDown : "Aşağı",
+DlgSelectBtnSetValue : "Seçili değer olarak ata",
+DlgSelectBtnDelete : "Sil",
+
+// Textarea Dialog
+DlgTextareaName : "Ad",
+DlgTextareaCols : "Sütunlar",
+DlgTextareaRows : "Satırlar",
+
+// Text Field Dialog
+DlgTextName : "Ad",
+DlgTextValue : "Değer",
+DlgTextCharWidth : "Karakter Genişliği",
+DlgTextMaxChars : "En Fazla Karakter",
+DlgTextType : "Tür",
+DlgTextTypeText : "Metin",
+DlgTextTypePass : "Parola",
+
+// Hidden Field Dialog
+DlgHiddenName : "Ad",
+DlgHiddenValue : "Değer",
+
+// Bulleted List Dialog
+BulletedListProp : "Simgeli Liste Özellikleri",
+NumberedListProp : "Numaralı Liste Özellikleri",
+DlgLstStart : "Başlangıç",
+DlgLstType : "Tip",
+DlgLstTypeCircle : "Çember",
+DlgLstTypeDisc : "Disk",
+DlgLstTypeSquare : "Kare",
+DlgLstTypeNumbers : "Sayılar (1, 2, 3)",
+DlgLstTypeLCase : "Küçük Harfler (a, b, c)",
+DlgLstTypeUCase : "Büyük Harfler (A, B, C)",
+DlgLstTypeSRoman : "Küçük Romen Rakamları (i, ii, iii)",
+DlgLstTypeLRoman : "Büyük Romen Rakamları (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Genel",
+DlgDocBackTab : "Arka Plan",
+DlgDocColorsTab : "Renkler ve Kenar Boşlukları",
+DlgDocMetaTab : "Tanım Bilgisi (Meta)",
+
+DlgDocPageTitle : "Sayfa Başlığı",
+DlgDocLangDir : "Dil Yönü",
+DlgDocLangDirLTR : "Soldan Sağa (LTR)",
+DlgDocLangDirRTL : "Sağdan Sola (RTL)",
+DlgDocLangCode : "Dil Kodu",
+DlgDocCharSet : "Karakter Kümesi Kodlaması",
+DlgDocCharSetCE : "Orta Avrupa",
+DlgDocCharSetCT : "Geleneksel Çince (Big5)",
+DlgDocCharSetCR : "Kiril",
+DlgDocCharSetGR : "Yunanca",
+DlgDocCharSetJP : "Japonca",
+DlgDocCharSetKR : "Korece",
+DlgDocCharSetTR : "Türkçe",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Batı Avrupa",
+DlgDocCharSetOther : "Diğer Karakter Kümesi Kodlaması",
+
+DlgDocDocType : "Belge Türü Başlığı",
+DlgDocDocTypeOther : "Diğer Belge Türü Başlığı",
+DlgDocIncXHTML : "XHTML Bildirimlerini Dahil Et",
+DlgDocBgColor : "Arka Plan Rengi",
+DlgDocBgImage : "Arka Plan Resim URLsi",
+DlgDocBgNoScroll : "Sabit Arka Plan",
+DlgDocCText : "Metin",
+DlgDocCLink : "Köprü",
+DlgDocCVisited : "Ziyaret Edilmiş Köprü",
+DlgDocCActive : "Etkin Köprü",
+DlgDocMargins : "Kenar Boşlukları",
+DlgDocMaTop : "Tepe",
+DlgDocMaLeft : "Sol",
+DlgDocMaRight : "Sağ",
+DlgDocMaBottom : "Alt",
+DlgDocMeIndex : "Belge Dizinleme Anahtar Kelimeleri (virgülle ayrılmış)",
+DlgDocMeDescr : "Belge Tanımı",
+DlgDocMeAuthor : "Yazar",
+DlgDocMeCopy : "Telif",
+DlgDocPreview : "Ön İzleme",
+
+// Templates Dialog
+Templates : "Şablonlar",
+DlgTemplatesTitle : "İçerik Şablonları",
+DlgTemplatesSelMsg : "Düzenleyicide açmak için lütfen bir şablon seçin.<br>(hali hazırdaki içerik kaybolacaktır.):",
+DlgTemplatesLoading : "Şablon listesi yüklenmekte. Lütfen bekleyiniz...",
+DlgTemplatesNoTpl : "(Belirli bir şablon seçilmedi)",
+DlgTemplatesReplace : "Mevcut içerik ile değiştir",
+
+// About Dialog
+DlgAboutAboutTab : "Hakkında",
+DlgAboutBrowserInfoTab : "Gezgin Bilgisi",
+DlgAboutLicenseTab : "Lisans",
+DlgAboutVersion : "sürüm",
+DlgAboutInfo : "Daha fazla bilgi için:"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/uk.js b/httemplate/elements/fckeditor/editor/lang/uk.js
new file mode 100644
index 000000000..1defaac76
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/uk.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Ukrainian language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Згорнути панель інструментів",
+ToolbarExpand : "Розгорнути панель інструментів",
+
+// Toolbar Items and Context Menu
+Save : "Зберегти",
+NewPage : "Нова сторінка",
+Preview : "Попередній перегляд",
+Cut : "Вирізати",
+Copy : "Копіювати",
+Paste : "Вставити",
+PasteText : "Вставити тільки текст",
+PasteWord : "Вставити з Word",
+Print : "Друк",
+SelectAll : "Виділити все",
+RemoveFormat : "Прибрати форматування",
+InsertLinkLbl : "Посилання",
+InsertLink : "Вставити/Редагувати посилання",
+RemoveLink : "Знищити посилання",
+Anchor : "Вставити/Редагувати якір",
+InsertImageLbl : "Зображення",
+InsertImage : "Вставити/Редагувати зображення",
+InsertFlashLbl : "Flash",
+InsertFlash : "Вставити/Редагувати Flash",
+InsertTableLbl : "Таблиця",
+InsertTable : "Вставити/Редагувати таблицю",
+InsertLineLbl : "Лінія",
+InsertLine : "Вставити горизонтальну лінію",
+InsertSpecialCharLbl: "Спеціальний символ",
+InsertSpecialChar : "Вставити спеціальний символ",
+InsertSmileyLbl : "Смайлик",
+InsertSmiley : "Вставити смайлик",
+About : "Про FCKeditor",
+Bold : "Жирний",
+Italic : "Курсив",
+Underline : "Підкреслений",
+StrikeThrough : "Закреслений",
+Subscript : "Підрядковий індекс",
+Superscript : "Надрядковий индекс",
+LeftJustify : "По лівому краю",
+CenterJustify : "По центру",
+RightJustify : "По правому краю",
+BlockJustify : "По ширині",
+DecreaseIndent : "Зменшити відступ",
+IncreaseIndent : "Збільшити відступ",
+Undo : "Повернути",
+Redo : "Повторити",
+NumberedListLbl : "Нумерований список",
+NumberedList : "Вставити/Видалити нумерований список",
+BulletedListLbl : "Маркований список",
+BulletedList : "Вставити/Видалити маркований список",
+ShowTableBorders : "Показати бордюри таблиці",
+ShowDetails : "Показати деталі",
+Style : "Стиль",
+FontFormat : "Форматування",
+Font : "Шрифт",
+FontSize : "Розмір",
+TextColor : "Колір тексту",
+BGColor : "Колір фону",
+Source : "Джерело",
+Find : "Пошук",
+Replace : "Заміна",
+SpellCheck : "Перевірити орфографію",
+UniversalKeyboard : "Універсальна клавіатура",
+PageBreakLbl : "Розривши сторінки",
+PageBreak : "Вставити розривши сторінки",
+
+Form : "Форма",
+Checkbox : "Флагова кнопка",
+RadioButton : "Кнопка вибору",
+TextField : "Текстове поле",
+Textarea : "Текстова область",
+HiddenField : "Приховане поле",
+Button : "Кнопка",
+SelectionField : "Список",
+ImageButton : "Кнопка із зображенням",
+
+FitWindow : "Розвернути вікно редактора",
+
+// Context Menu
+EditLink : "Вставити посилання",
+CellCM : "Осередок",
+RowCM : "Рядок",
+ColumnCM : "Колонка",
+InsertRow : "Вставити строку",
+DeleteRows : "Видалити строки",
+InsertColumn : "Вставити колонку",
+DeleteColumns : "Видалити колонки",
+InsertCell : "Вставити комірку",
+DeleteCells : "Видалити комірки",
+MergeCells : "Об'єднати комірки",
+SplitCell : "Роз'єднати комірку",
+TableDelete : "Видалити таблицю",
+CellProperties : "Властивості комірки",
+TableProperties : "Властивості таблиці",
+ImageProperties : "Властивості зображення",
+FlashProperties : "Властивості Flash",
+
+AnchorProp : "Властивості якоря",
+ButtonProp : "Властивості кнопки",
+CheckboxProp : "Властивості флагової кнопки",
+HiddenFieldProp : "Властивості прихованого поля",
+RadioButtonProp : "Властивості кнопки вибору",
+ImageButtonProp : "Властивості кнопки із зображенням",
+TextFieldProp : "Властивості текстового поля",
+SelectionFieldProp : "Властивості списку",
+TextareaProp : "Властивості текстової області",
+FormProp : "Властивості форми",
+
+FontFormats : "Нормальний;Форматований;Адреса;Заголовок 1;Заголовок 2;Заголовок 3;Заголовок 4;Заголовок 5;Заголовок 6;Нормальний (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Обробка XHTML. Зачекайте, будь ласка...",
+Done : "Зроблено",
+PasteWordConfirm : "Текст, що ви хочете вставити, схожий на копійований з Word. Ви хочете очистити його перед вставкою?",
+NotCompatiblePaste : "Ця команда доступна для Internet Explorer версії 5.5 або вище. Ви хочете вставити без очищення?",
+UnknownToolbarItem : "Невідомий елемент панелі інструментів \"%1\"",
+UnknownCommand : "Невідоме ім'я команди \"%1\"",
+NotImplemented : "Команда не реалізована",
+UnknownToolbarSet : "Панель інструментів \"%1\" не існує",
+NoActiveX : "Настройки безпеки вашого браузера можуть обмежувати деякі властивості редактора. Ви повинні включити опцію \"Запускати елементи управління ACTIVEX і плугіни\". Ви можете бачити помилки і помічати відсутність можливостей.",
+BrowseServerBlocked : "Ресурси браузера не можуть бути відкриті. Перевірте що блокування спливаючих вікон вимкнені.",
+DialogBlocked : "Не можливо відкрити вікно діалогу. Перевірте що блокування спливаючих вікон вимкнені.",
+
+// Dialogs
+DlgBtnOK : "ОК",
+DlgBtnCancel : "Скасувати",
+DlgBtnClose : "Зачинити",
+DlgBtnBrowseServer : "Передивитися на сервері",
+DlgAdvancedTag : "Розширений",
+DlgOpOther : "<Інше>",
+DlgInfoTab : "Інфо",
+DlgAlertUrl : "Вставте, будь-ласка, URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<не визначено>",
+DlgGenId : "Ідентифікатор",
+DlgGenLangDir : "Напрямок мови",
+DlgGenLangDirLtr : "Зліва на право (LTR)",
+DlgGenLangDirRtl : "Зправа на ліво (RTL)",
+DlgGenLangCode : "Мова",
+DlgGenAccessKey : "Гаряча клавіша",
+DlgGenName : "Им'я",
+DlgGenTabIndex : "Послідовність переходу",
+DlgGenLongDescr : "Довгий опис URL",
+DlgGenClass : "Клас CSS",
+DlgGenTitle : "Заголовок",
+DlgGenContType : "Тип вмісту",
+DlgGenLinkCharset : "Кодировка",
+DlgGenStyle : "Стиль CSS",
+
+// Image Dialog
+DlgImgTitle : "Властивості зображення",
+DlgImgInfoTab : "Інформація про изображении",
+DlgImgBtnUpload : "Надіслати на сервер",
+DlgImgURL : "URL",
+DlgImgUpload : "Закачати",
+DlgImgAlt : "Альтернативний текст",
+DlgImgWidth : "Ширина",
+DlgImgHeight : "Висота",
+DlgImgLockRatio : "Зберегти пропорції",
+DlgBtnResetSize : "Скинути розмір",
+DlgImgBorder : "Бордюр",
+DlgImgHSpace : "Горизонтальний відступ",
+DlgImgVSpace : "Вертикальний відступ",
+DlgImgAlign : "Вирівнювання",
+DlgImgAlignLeft : "По лівому краю",
+DlgImgAlignAbsBottom: "Абс по низу",
+DlgImgAlignAbsMiddle: "Абс по середині",
+DlgImgAlignBaseline : "По базовій лінії",
+DlgImgAlignBottom : "По низу",
+DlgImgAlignMiddle : "По середині",
+DlgImgAlignRight : "По правому краю",
+DlgImgAlignTextTop : "Текст на верху",
+DlgImgAlignTop : "По верху",
+DlgImgPreview : "Попередній перегляд",
+DlgImgAlertUrl : "Будь ласка, введіть URL зображення",
+DlgImgLinkTab : "Посилання",
+
+// Flash Dialog
+DlgFlashTitle : "Властивості Flash",
+DlgFlashChkPlay : "Авто програвання",
+DlgFlashChkLoop : "Зациклити",
+DlgFlashChkMenu : "Дозволити меню Flash",
+DlgFlashScale : "Масштаб",
+DlgFlashScaleAll : "Показати всі",
+DlgFlashScaleNoBorder : "Без рамки",
+DlgFlashScaleFit : "Дійсний розмір",
+
+// Link Dialog
+DlgLnkWindowTitle : "Посилання",
+DlgLnkInfoTab : "Інформація посилання",
+DlgLnkTargetTab : "Ціль",
+
+DlgLnkType : "Тип посилання",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Якір на цю сторінку",
+DlgLnkTypeEMail : "Эл. пошта",
+DlgLnkProto : "Протокол",
+DlgLnkProtoOther : "<інше>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Оберіть якір",
+DlgLnkAnchorByName : "За ім'ям якоря",
+DlgLnkAnchorById : "За ідентифікатором елемента",
+DlgLnkNoAnchors : "<Немає якорів доступних в цьому документі>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Адреса ел. пошти",
+DlgLnkEMailSubject : "Тема листа",
+DlgLnkEMailBody : "Тіло повідомлення",
+DlgLnkUpload : "Закачати",
+DlgLnkBtnUpload : "Переслати на сервер",
+
+DlgLnkTarget : "Ціль",
+DlgLnkTargetFrame : "<фрейм>",
+DlgLnkTargetPopup : "<спливаюче вікно>",
+DlgLnkTargetBlank : "Нове вікно (_blank)",
+DlgLnkTargetParent : "Батьківське вікно (_parent)",
+DlgLnkTargetSelf : "Теж вікно (_self)",
+DlgLnkTargetTop : "Найвище вікно (_top)",
+DlgLnkTargetFrameName : "Ім'я целевого фрейма",
+DlgLnkPopWinName : "Ім'я спливаючого вікна",
+DlgLnkPopWinFeat : "Властивості спливаючого вікна",
+DlgLnkPopResize : "Змінюється в розмірах",
+DlgLnkPopLocation : "Панель локації",
+DlgLnkPopMenu : "Панель меню",
+DlgLnkPopScroll : "Полоси прокрутки",
+DlgLnkPopStatus : "Строка статусу",
+DlgLnkPopToolbar : "Панель інструментів",
+DlgLnkPopFullScrn : "Повний екран (IE)",
+DlgLnkPopDependent : "Залежний (Netscape)",
+DlgLnkPopWidth : "Ширина",
+DlgLnkPopHeight : "Висота",
+DlgLnkPopLeft : "Позиція зліва",
+DlgLnkPopTop : "Позиція зверху",
+
+DlnLnkMsgNoUrl : "Будь ласка, занесіть URL посилання",
+DlnLnkMsgNoEMail : "Будь ласка, занесіть адрес эл. почты",
+DlnLnkMsgNoAnchor : "Будь ласка, оберіть якір",
+DlnLnkMsgInvPopName : "Назва спливаючого вікна повинна починатися букви і не може містити пропусків",
+
+// Color Dialog
+DlgColorTitle : "Оберіть колір",
+DlgColorBtnClear : "Очистити",
+DlgColorHighlight : "Підсвічений",
+DlgColorSelected : "Обраний",
+
+// Smiley Dialog
+DlgSmileyTitle : "Вставити смайлик",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Оберіть спеціальний символ",
+
+// Table Dialog
+DlgTableTitle : "Властивості таблиці",
+DlgTableRows : "Строки",
+DlgTableColumns : "Колонки",
+DlgTableBorder : "Розмір бордюра",
+DlgTableAlign : "Вирівнювання",
+DlgTableAlignNotSet : "<Не вст.>",
+DlgTableAlignLeft : "Зліва",
+DlgTableAlignCenter : "По центру",
+DlgTableAlignRight : "Зправа",
+DlgTableWidth : "Ширина",
+DlgTableWidthPx : "пікселів",
+DlgTableWidthPc : "відсотків",
+DlgTableHeight : "Висота",
+DlgTableCellSpace : "Проміжок (spacing)",
+DlgTableCellPad : "Відступ (padding)",
+DlgTableCaption : "Заголовок",
+DlgTableSummary : "Резюме",
+
+// Table Cell Dialog
+DlgCellTitle : "Властивості комірки",
+DlgCellWidth : "Ширина",
+DlgCellWidthPx : "пікселів",
+DlgCellWidthPc : "відсотків",
+DlgCellHeight : "Висота",
+DlgCellWordWrap : "Згортання текста",
+DlgCellWordWrapNotSet : "<Не вст.>",
+DlgCellWordWrapYes : "Так",
+DlgCellWordWrapNo : "Ні",
+DlgCellHorAlign : "Горизонтальне вирівнювання",
+DlgCellHorAlignNotSet : "<Не вст.>",
+DlgCellHorAlignLeft : "Зліва",
+DlgCellHorAlignCenter : "По центру",
+DlgCellHorAlignRight: "Зправа",
+DlgCellVerAlign : "Вертикальное вирівнювання",
+DlgCellVerAlignNotSet : "<Не вст.>",
+DlgCellVerAlignTop : "Зверху",
+DlgCellVerAlignMiddle : "Посередині",
+DlgCellVerAlignBottom : "Знизу",
+DlgCellVerAlignBaseline : "По базовій лінії",
+DlgCellRowSpan : "Діапазон строк (span)",
+DlgCellCollSpan : "Діапазон колонок (span)",
+DlgCellBackColor : "Колір фона",
+DlgCellBorderColor : "Колір бордюра",
+DlgCellBtnSelect : "Оберіть...",
+
+// Find Dialog
+DlgFindTitle : "Пошук",
+DlgFindFindBtn : "Пошук",
+DlgFindNotFoundMsg : "Вказаний текст не знайдений.",
+
+// Replace Dialog
+DlgReplaceTitle : "Замінити",
+DlgReplaceFindLbl : "Шукати:",
+DlgReplaceReplaceLbl : "Замінити на:",
+DlgReplaceCaseChk : "Учитывать регистр",
+DlgReplaceReplaceBtn : "Замінити",
+DlgReplaceReplAllBtn : "Замінити все",
+DlgReplaceWordChk : "Збіг цілих слів",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Настройки безпеки вашого браузера не дозволяють редактору автоматично виконувати операції вирізування. Будь ласка, використовуйте клавіатуру для цього (Ctrl+X).",
+PasteErrorCopy : "Настройки безпеки вашого браузера не дозволяють редактору автоматично виконувати операції копіювання. Будь ласка, використовуйте клавіатуру для цього (Ctrl+C).",
+
+PasteAsText : "Вставити тільки текст",
+PasteFromWord : "Вставити з Word",
+
+DlgPasteMsg2 : "Будь-ласка, вставте з буфера обміну в цю область, користуючись комбінацією клавіш (<STRONG>Ctrl+V</STRONG>) та натисніть <STRONG>OK</STRONG>.",
+DlgPasteSec : "Редактор не може отримати прямий доступ до буферу обміну у зв'язку з налаштуваннями вашого браузера. Вам потрібно вставити інформацію повторно в це вікно.",
+DlgPasteIgnoreFont : "Ігнорувати налаштування шрифтів",
+DlgPasteRemoveStyles : "Видалити налаштування стилів",
+DlgPasteCleanBox : "Очистити область",
+
+// Color Picker
+ColorAutomatic : "Автоматичний",
+ColorMoreColors : "Кольори...",
+
+// Document Properties
+DocProps : "Властивості документа",
+
+// Anchor Dialog
+DlgAnchorTitle : "Властивості якоря",
+DlgAnchorName : "Ім'я якоря",
+DlgAnchorErrorName : "Будь ласка, занесіть ім'я якоря",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Не має в словнику",
+DlgSpellChangeTo : "Замінити на",
+DlgSpellBtnIgnore : "Ігнорувати",
+DlgSpellBtnIgnoreAll : "Ігнорувати все",
+DlgSpellBtnReplace : "Замінити",
+DlgSpellBtnReplaceAll : "Замінити все",
+DlgSpellBtnUndo : "Назад",
+DlgSpellNoSuggestions : "- Немає припущень -",
+DlgSpellProgress : "Виконується перевірка орфографії...",
+DlgSpellNoMispell : "Перевірку орфографії завершено: помилок не знайдено",
+DlgSpellNoChanges : "Перевірку орфографії завершено: жодне слово не змінено",
+DlgSpellOneChange : "Перевірку орфографії завершено: змінено одно слово",
+DlgSpellManyChanges : "Перевірку орфографії завершено: 1% слів змінено",
+
+IeSpellDownload : "Модуль перевірки орфографії не встановлено. Бажаєтн завантажити його зараз?",
+
+// Button Dialog
+DlgButtonText : "Текст (Значення)",
+DlgButtonType : "Тип",
+DlgButtonTypeBtn : "Кнопка",
+DlgButtonTypeSbm : "Відправити",
+DlgButtonTypeRst : "Скинути",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Ім'я",
+DlgCheckboxValue : "Значення",
+DlgCheckboxSelected : "Обрана",
+
+// Form Dialog
+DlgFormName : "Ім'я",
+DlgFormAction : "Дія",
+DlgFormMethod : "Метод",
+
+// Select Field Dialog
+DlgSelectName : "Ім'я",
+DlgSelectValue : "Значення",
+DlgSelectSize : "Розмір",
+DlgSelectLines : "лінії",
+DlgSelectChkMulti : "Дозволити обрання декількох позицій",
+DlgSelectOpAvail : "Доступні варіанти",
+DlgSelectOpText : "Текст",
+DlgSelectOpValue : "Значення",
+DlgSelectBtnAdd : "Добавити",
+DlgSelectBtnModify : "Змінити",
+DlgSelectBtnUp : "Вгору",
+DlgSelectBtnDown : "Вниз",
+DlgSelectBtnSetValue : "Встановити як вибране значення",
+DlgSelectBtnDelete : "Видалити",
+
+// Textarea Dialog
+DlgTextareaName : "Ім'я",
+DlgTextareaCols : "Колонки",
+DlgTextareaRows : "Строки",
+
+// Text Field Dialog
+DlgTextName : "Ім'я",
+DlgTextValue : "Значення",
+DlgTextCharWidth : "Ширина",
+DlgTextMaxChars : "Макс. кіл-ть символів",
+DlgTextType : "Тип",
+DlgTextTypeText : "Текст",
+DlgTextTypePass : "Пароль",
+
+// Hidden Field Dialog
+DlgHiddenName : "Ім'я",
+DlgHiddenValue : "Значення",
+
+// Bulleted List Dialog
+BulletedListProp : "Властивості маркованого списка",
+NumberedListProp : "Властивості нумерованного списка",
+DlgLstStart : "Початок",
+DlgLstType : "Тип",
+DlgLstTypeCircle : "Коло",
+DlgLstTypeDisc : "Диск",
+DlgLstTypeSquare : "Квадрат",
+DlgLstTypeNumbers : "Номери (1, 2, 3)",
+DlgLstTypeLCase : "Літери нижнього регістра(a, b, c)",
+DlgLstTypeUCase : "Букви верхнього регістра (A, B, C)",
+DlgLstTypeSRoman : "Малі римські літери (i, ii, iii)",
+DlgLstTypeLRoman : "Великі римські літери (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Загальні",
+DlgDocBackTab : "Заднє тло",
+DlgDocColorsTab : "Кольори та відступи",
+DlgDocMetaTab : "Мета дані",
+
+DlgDocPageTitle : "Заголовок сторінки",
+DlgDocLangDir : "Напрямок тексту",
+DlgDocLangDirLTR : "Зліва на право (LTR)",
+DlgDocLangDirRTL : "Зправа на лево (RTL)",
+DlgDocLangCode : "Код мови",
+DlgDocCharSet : "Кодування набору символів",
+DlgDocCharSetCE : "Центрально-європейська",
+DlgDocCharSetCT : "Китайська традиційна (Big5)",
+DlgDocCharSetCR : "Кирилиця",
+DlgDocCharSetGR : "Грецька",
+DlgDocCharSetJP : "Японська",
+DlgDocCharSetKR : "Корейська",
+DlgDocCharSetTR : "Турецька",
+DlgDocCharSetUN : "Юнікод (UTF-8)",
+DlgDocCharSetWE : "Західно-европейская",
+DlgDocCharSetOther : "Інше кодування набору символів",
+
+DlgDocDocType : "Заголовок типу документу",
+DlgDocDocTypeOther : "Інший заголовок типу документу",
+DlgDocIncXHTML : "Ввімкнути XHTML оголошення",
+DlgDocBgColor : "Колір тла",
+DlgDocBgImage : "URL зображення тла",
+DlgDocBgNoScroll : "Тло без прокрутки",
+DlgDocCText : "Текст",
+DlgDocCLink : "Посилання",
+DlgDocCVisited : "Відвідане посилання",
+DlgDocCActive : "Активне посилання",
+DlgDocMargins : "Відступи сторінки",
+DlgDocMaTop : "Верхній",
+DlgDocMaLeft : "Лівий",
+DlgDocMaRight : "Правий",
+DlgDocMaBottom : "Нижній",
+DlgDocMeIndex : "Ключові слова документа (розділені комами)",
+DlgDocMeDescr : "Опис документа",
+DlgDocMeAuthor : "Автор",
+DlgDocMeCopy : "Авторські права",
+DlgDocPreview : "Попередній перегляд",
+
+// Templates Dialog
+Templates : "Шаблони",
+DlgTemplatesTitle : "Шаблони змісту",
+DlgTemplatesSelMsg : "Оберіть, будь ласка, шаблон для відкриття в редакторі<br>(поточний зміст буде втрачено):",
+DlgTemplatesLoading : "Завантаження списку шаблонів. Зачекайте, будь ласка...",
+DlgTemplatesNoTpl : "(Не визначено жодного шаблону)",
+DlgTemplatesReplace : "Замінити поточний вміст",
+
+// About Dialog
+DlgAboutAboutTab : "Про програму",
+DlgAboutBrowserInfoTab : "Інформація браузера",
+DlgAboutLicenseTab : "Ліцензія",
+DlgAboutVersion : "Версія",
+DlgAboutInfo : "Додаткову інформацію дивіться на "
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/vi.js b/httemplate/elements/fckeditor/editor/lang/vi.js
new file mode 100644
index 000000000..5c2c608ec
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/vi.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Vietnamese language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "Thu gọn Thanh công cụ",
+ToolbarExpand : "Mở rộng Thanh công cụ",
+
+// Toolbar Items and Context Menu
+Save : "Lưu",
+NewPage : "Trang mới",
+Preview : "Xem trước",
+Cut : "Cắt",
+Copy : "Sao chép",
+Paste : "Dán",
+PasteText : "Dán theo dạng văn bản thuần",
+PasteWord : "Dán với định dạng Word",
+Print : "In",
+SelectAll : "Chọn Tất cả",
+RemoveFormat : "Xoá Định dạng",
+InsertLinkLbl : "Liên kết",
+InsertLink : "Chèn/Sửa Liên kết",
+RemoveLink : "Xoá Liên kết",
+Anchor : "Chèn/Sửa Neo",
+InsertImageLbl : "Hình ảnh",
+InsertImage : "Chèn/Sửa Hình ảnh",
+InsertFlashLbl : "Flash",
+InsertFlash : "Chèn/Sửa Flash",
+InsertTableLbl : "Bảng",
+InsertTable : "Chèn/Sửa Bảng",
+InsertLineLbl : "Đường phân cách ngang",
+InsertLine : "Chèn Đường phân cách ngang",
+InsertSpecialCharLbl: "Ký tự đặc biệt",
+InsertSpecialChar : "Chèn Ký tự đặc biệt",
+InsertSmileyLbl : "Hình biểu lộ cảm xúc (mặt cười)",
+InsertSmiley : "Chèn Hình biểu lộ cảm xúc (mặt cười)",
+About : "Giới thiệu về FCKeditor",
+Bold : "Đậm",
+Italic : "Nghiêng",
+Underline : "Gạch chân",
+StrikeThrough : "Gạch xuyên ngang",
+Subscript : "Chỉ số dưới",
+Superscript : "Chỉ số trên",
+LeftJustify : "Canh trái",
+CenterJustify : "Canh giữa",
+RightJustify : "Canh phải",
+BlockJustify : "Canh đều",
+DecreaseIndent : "Dịch ra ngoài",
+IncreaseIndent : "Dịch vào trong",
+Undo : "Khôi phục thao tác",
+Redo : "Làm lại thao tác",
+NumberedListLbl : "Danh sách có thứ tự",
+NumberedList : "Chèn/Xoá Danh sách có thứ tự",
+BulletedListLbl : "Danh sách không thứ tự",
+BulletedList : "Chèn/Xoá Danh sách không thứ tự",
+ShowTableBorders : "Hiển thị Đường viền bảng",
+ShowDetails : "Hiển thị Chi tiết",
+Style : "Mẫu",
+FontFormat : "Định dạng",
+Font : "Phông",
+FontSize : "Cỡ chữ",
+TextColor : "Màu chữ",
+BGColor : "Màu nền",
+Source : "Mã HTML",
+Find : "Tìm kiếm",
+Replace : "Thay thế",
+SpellCheck : "Kiểm tra Chính tả",
+UniversalKeyboard : "Bàn phím Quốc tế",
+PageBreakLbl : "Ngắt trang",
+PageBreak : "Chèn Ngắt trang",
+
+Form : "Biểu mẫu",
+Checkbox : "Nút kiểm",
+RadioButton : "Nút chọn",
+TextField : "Trường văn bản",
+Textarea : "Vùng văn bản",
+HiddenField : "Trường ẩn",
+Button : "Nút",
+SelectionField : "Ô chọn",
+ImageButton : "Nút hình ảnh",
+
+FitWindow : "Mở rộng tối đa kích thước trình biên tập",
+
+// Context Menu
+EditLink : "Sửa Liên kết",
+CellCM : "Ô",
+RowCM : "Hàng",
+ColumnCM : "Cột",
+InsertRow : "Chèn Hàng",
+DeleteRows : "Xoá Hàng",
+InsertColumn : "Chèn Cột",
+DeleteColumns : "Xoá Cột",
+InsertCell : "Chèn Ô",
+DeleteCells : "Xoá Ô",
+MergeCells : "Trộn Ô",
+SplitCell : "Chia Ô",
+TableDelete : "Xóa Bảng",
+CellProperties : "Thuộc tính Ô",
+TableProperties : "Thuộc tính Bảng",
+ImageProperties : "Thuộc tính Hình ảnh",
+FlashProperties : "Thuộc tính Flash",
+
+AnchorProp : "Thuộc tính Neo",
+ButtonProp : "Thuộc tính Nút",
+CheckboxProp : "Thuộc tính Nút kiểm",
+HiddenFieldProp : "Thuộc tính Trường ẩn",
+RadioButtonProp : "Thuộc tính Nút chọn",
+ImageButtonProp : "Thuộc tính Nút hình ảnh",
+TextFieldProp : "Thuộc tính Trường văn bản",
+SelectionFieldProp : "Thuộc tính Ô chọn",
+TextareaProp : "Thuộc tính Vùng văn bản",
+FormProp : "Thuộc tính Biểu mẫu",
+
+FontFormats : "Normal;Formatted;Address;Heading 1;Heading 2;Heading 3;Heading 4;Heading 5;Heading 6;Normal (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "Đang xử lý XHTML. Vui lòng đợi trong giây lát...",
+Done : "Đã hoàn thành",
+PasteWordConfirm : "Văn bản bạn muốn dán có kèm định dạng của Word. Bạn có muốn loại bỏ định dạng Word trước khi dán?",
+NotCompatiblePaste : "Lệnh này chỉ được hỗ trợ từ trình duyệt Internet Explorer phiên bản 5.5 hoặc mới hơn. Bạn có muốn dán nguyên mẫu?",
+UnknownToolbarItem : "Không rõ mục trên thanh công cụ \"%1\"",
+UnknownCommand : "Không rõ lệnh \"%1\"",
+NotImplemented : "Lệnh không được thực hiện",
+UnknownToolbarSet : "Thanh công cụ \"%1\" không tồn tại",
+NoActiveX : "Các thiết lập bảo mật của trình duyệt có thể giới hạn một số chức năng của trình biên tập. Bạn phải bật tùy chọn \"Run ActiveX controls and plug-ins\". Bạn có thể gặp một số lỗi và thấy thiếu đi một số chức năng.",
+BrowseServerBlocked : "Không thể mở được bộ duyệt tài nguyên. Hãy đảm bảo chức năng chặn popup đã bị vô hiệu hóa.",
+DialogBlocked : "Không thể mở được cửa sổ hộp thoại. Hãy đảm bảo chức năng chặn popup đã bị vô hiệu hóa.",
+
+// Dialogs
+DlgBtnOK : "Đồng ý",
+DlgBtnCancel : "Bỏ qua",
+DlgBtnClose : "Đóng",
+DlgBtnBrowseServer : "Duyệt trên máy chủ",
+DlgAdvancedTag : "Mở rộng",
+DlgOpOther : "<Khác>",
+DlgInfoTab : "Thông tin",
+DlgAlertUrl : "Hãy nhập vào một URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<không thiết lập>",
+DlgGenId : "Định danh",
+DlgGenLangDir : "Đường dẫn Ngôn ngữ",
+DlgGenLangDirLtr : "Trái sang Phải (LTR)",
+DlgGenLangDirRtl : "Phải sang Trái (RTL)",
+DlgGenLangCode : "Mã Ngôn ngữ",
+DlgGenAccessKey : "Phím Hỗ trợ truy cập",
+DlgGenName : "Tên",
+DlgGenTabIndex : "Chỉ số của Tab",
+DlgGenLongDescr : "Mô tả URL",
+DlgGenClass : "Lớp Stylesheet",
+DlgGenTitle : "Advisory Title",
+DlgGenContType : "Advisory Content Type",
+DlgGenLinkCharset : "Bảng mã của tài nguyên được liên kết đến",
+DlgGenStyle : "Mẫu",
+
+// Image Dialog
+DlgImgTitle : "Thuộc tính Hình ảnh",
+DlgImgInfoTab : "Thông tin Hình ảnh",
+DlgImgBtnUpload : "Tải lên Máy chủ",
+DlgImgURL : "URL",
+DlgImgUpload : "Tải lên",
+DlgImgAlt : "Chú thích Hình ảnh",
+DlgImgWidth : "Rộng",
+DlgImgHeight : "Cao",
+DlgImgLockRatio : "Giữ tỷ lệ",
+DlgBtnResetSize : "Kích thước gốc",
+DlgImgBorder : "Đường viền",
+DlgImgHSpace : "HSpace",
+DlgImgVSpace : "VSpace",
+DlgImgAlign : "Vị trí",
+DlgImgAlignLeft : "Trái",
+DlgImgAlignAbsBottom: "Dưới tuyệt đối",
+DlgImgAlignAbsMiddle: "Giữa tuyệt đối",
+DlgImgAlignBaseline : "Baseline",
+DlgImgAlignBottom : "Dưới",
+DlgImgAlignMiddle : "Giữa",
+DlgImgAlignRight : "Phải",
+DlgImgAlignTextTop : "Phía trên chữ",
+DlgImgAlignTop : "Trên",
+DlgImgPreview : "Xem trước",
+DlgImgAlertUrl : "Hãy đưa vào URL của hình ảnh",
+DlgImgLinkTab : "Liên kết",
+
+// Flash Dialog
+DlgFlashTitle : "Thuộc tính Flash",
+DlgFlashChkPlay : "Tự động chạy",
+DlgFlashChkLoop : "Lặp",
+DlgFlashChkMenu : "Cho phép bật Menu của Flash",
+DlgFlashScale : "Tỷ lệ",
+DlgFlashScaleAll : "Hiển thị tất cả",
+DlgFlashScaleNoBorder : "Không đường viền",
+DlgFlashScaleFit : "Vừa vặn",
+
+// Link Dialog
+DlgLnkWindowTitle : "Liên kết",
+DlgLnkInfoTab : "Thông tin Liên kết",
+DlgLnkTargetTab : "Đích",
+
+DlgLnkType : "Kiểu Liên kết",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "Neo trong trang này",
+DlgLnkTypeEMail : "Thư điện tử",
+DlgLnkProto : "Giao thức",
+DlgLnkProtoOther : "<khác>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "Chọn một Neo",
+DlgLnkAnchorByName : "Theo Tên Neo",
+DlgLnkAnchorById : "Theo Định danh Element",
+DlgLnkNoAnchors : "<Không có Neo nào trong tài liệu>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "Thư điện tử",
+DlgLnkEMailSubject : "Tiêu đề Thông điệp",
+DlgLnkEMailBody : "Nội dung Thông điệp",
+DlgLnkUpload : "Tải lên",
+DlgLnkBtnUpload : "Tải lên Máy chủ",
+
+DlgLnkTarget : "Đích",
+DlgLnkTargetFrame : "<khung>",
+DlgLnkTargetPopup : "<cửa sổ popup>",
+DlgLnkTargetBlank : "Cửa sổ mới (_blank)",
+DlgLnkTargetParent : "Cửa sổ cha (_parent)",
+DlgLnkTargetSelf : "Cùng cửa sổ (_self)",
+DlgLnkTargetTop : "Cửa sổ trên cùng(_top)",
+DlgLnkTargetFrameName : "Tên Khung đích",
+DlgLnkPopWinName : "Tên Cửa sổ Popup",
+DlgLnkPopWinFeat : "Đặc điểm của Cửa sổ Popup",
+DlgLnkPopResize : "Kích thước thay đổi",
+DlgLnkPopLocation : "Thanh vị trí",
+DlgLnkPopMenu : "Thanh Menu",
+DlgLnkPopScroll : "Thanh cuộn",
+DlgLnkPopStatus : "Thanh trạng thái",
+DlgLnkPopToolbar : "Thanh công cụ",
+DlgLnkPopFullScrn : "Toàn màn hình (IE)",
+DlgLnkPopDependent : "Phụ thuộc (Netscape)",
+DlgLnkPopWidth : "Rộng",
+DlgLnkPopHeight : "Cao",
+DlgLnkPopLeft : "Vị trí Trái",
+DlgLnkPopTop : "Vị trí Trên",
+
+DlnLnkMsgNoUrl : "Hãy đưa vào Liên kết URL",
+DlnLnkMsgNoEMail : "Hãy đưa vào địa chỉ thư điện tử",
+DlnLnkMsgNoAnchor : "Hãy chọn một Neo",
+DlnLnkMsgInvPopName : "Tên của cửa sổ Popup phải bắt đầu bằng một ký tự và không được chứa khoảng trắng",
+
+// Color Dialog
+DlgColorTitle : "Chọn màu",
+DlgColorBtnClear : "Xoá",
+DlgColorHighlight : "Tô sáng",
+DlgColorSelected : "Đã chọn",
+
+// Smiley Dialog
+DlgSmileyTitle : "Chèn Hình biểu lộ cảm xúc (mặt cười)",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "Hãy chọn Ký tự đặc biệt",
+
+// Table Dialog
+DlgTableTitle : "Thuộc tính bảng",
+DlgTableRows : "Hàng",
+DlgTableColumns : "Cột",
+DlgTableBorder : "Cỡ Đường viền",
+DlgTableAlign : "Canh lề",
+DlgTableAlignNotSet : "<Chưa thiết lập>",
+DlgTableAlignLeft : "Trái",
+DlgTableAlignCenter : "Giữa",
+DlgTableAlignRight : "Phải",
+DlgTableWidth : "Rộng",
+DlgTableWidthPx : "điểm (px)",
+DlgTableWidthPc : "%",
+DlgTableHeight : "Cao",
+DlgTableCellSpace : "Khoảng cách Ô",
+DlgTableCellPad : "Đệm Ô",
+DlgTableCaption : "Đầu đề",
+DlgTableSummary : "Tóm lược",
+
+// Table Cell Dialog
+DlgCellTitle : "Thuộc tính Ô",
+DlgCellWidth : "Rộng",
+DlgCellWidthPx : "điểm (px)",
+DlgCellWidthPc : "%",
+DlgCellHeight : "Cao",
+DlgCellWordWrap : "Bọc từ",
+DlgCellWordWrapNotSet : "<Chưa thiết lập>",
+DlgCellWordWrapYes : "Đồng ý",
+DlgCellWordWrapNo : "Không",
+DlgCellHorAlign : "Canh theo Chiều ngang",
+DlgCellHorAlignNotSet : "<Chưa thiết lập>",
+DlgCellHorAlignLeft : "Trái",
+DlgCellHorAlignCenter : "Giữa",
+DlgCellHorAlignRight: "Phải",
+DlgCellVerAlign : "Canh theo Chiều dọc",
+DlgCellVerAlignNotSet : "<Chưa thiết lập>",
+DlgCellVerAlignTop : "Trên",
+DlgCellVerAlignMiddle : "Giữa",
+DlgCellVerAlignBottom : "Dưới",
+DlgCellVerAlignBaseline : "Baseline",
+DlgCellRowSpan : "Nối Hàng",
+DlgCellCollSpan : "Nối Cột",
+DlgCellBackColor : "Màu nền",
+DlgCellBorderColor : "Màu viền",
+DlgCellBtnSelect : "Chọn...",
+
+// Find Dialog
+DlgFindTitle : "Tìm kiếm",
+DlgFindFindBtn : "Tìm kiếm",
+DlgFindNotFoundMsg : "Không tìm thấy chuỗi cần tìm.",
+
+// Replace Dialog
+DlgReplaceTitle : "Thay thế",
+DlgReplaceFindLbl : "Tìm chuỗi:",
+DlgReplaceReplaceLbl : "Thay bằng:",
+DlgReplaceCaseChk : "Phân biệt chữ hoa/thường",
+DlgReplaceReplaceBtn : "Thay thế",
+DlgReplaceReplAllBtn : "Thay thế Tất cả",
+DlgReplaceWordChk : "Đúng toàn bộ từ",
+
+// Paste Operations / Dialog
+PasteErrorCut : "Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh cắt. Hãy sử dụng bàn phím cho lệnh này (Ctrl+X).",
+PasteErrorCopy : "Các thiết lập bảo mật của trình duyệt không cho phép trình biên tập tự động thực thi lệnh sao chép. Hãy sử dụng bàn phím cho lệnh này (Ctrl+C).",
+
+PasteAsText : "Dán theo định dạng văn bản thuần",
+PasteFromWord : "Dán với định dạng Word",
+
+DlgPasteMsg2 : "Hãy dán nội dung vào trong khung bên dưới, sử dụng tổ hợp phím (<STRONG>Ctrl+V</STRONG>) và nhấn vào nút <STRONG>Đồng ý</STRONG>.",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "Chấp nhận các định dạng phông",
+DlgPasteRemoveStyles : "Gỡ bỏ các định dạng Styles",
+DlgPasteCleanBox : "Xóa nội dung",
+
+// Color Picker
+ColorAutomatic : "Tự động",
+ColorMoreColors : "Màu khác...",
+
+// Document Properties
+DocProps : "Thuộc tính Tài liệu",
+
+// Anchor Dialog
+DlgAnchorTitle : "Thuộc tính Neo",
+DlgAnchorName : "Tên của Neo",
+DlgAnchorErrorName : "Hãy đưa vào tên của Neo",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "Không có trong từ điển",
+DlgSpellChangeTo : "Chuyển thành",
+DlgSpellBtnIgnore : "Bỏ qua",
+DlgSpellBtnIgnoreAll : "Bỏ qua Tất cả",
+DlgSpellBtnReplace : "Thay thế",
+DlgSpellBtnReplaceAll : "Thay thế Tất cả",
+DlgSpellBtnUndo : "Phục hồi lại",
+DlgSpellNoSuggestions : "- Không đưa ra gợi ý về từ -",
+DlgSpellProgress : "Đang tiến hành kiểm tra chính tả...",
+DlgSpellNoMispell : "Hoàn tất kiểm tra chính tả: Không có lỗi chính tả",
+DlgSpellNoChanges : "Hoàn tất kiểm tra chính tả: Không có từ nào được thay đổi",
+DlgSpellOneChange : "Hoàn tất kiểm tra chính tả: Một từ đã được thay đổi",
+DlgSpellManyChanges : "Hoàn tất kiểm tra chính tả: %1 từ đã được thay đổi",
+
+IeSpellDownload : "Chức năng kiểm tra chính tả chưa được cài đặt. Bạn có muốn tải về ngay bây giờ?",
+
+// Button Dialog
+DlgButtonText : "Chuỗi hiển thị (Giá trị)",
+DlgButtonType : "Kiểu",
+DlgButtonTypeBtn : "Nút Bấm",
+DlgButtonTypeSbm : "Nút Gửi",
+DlgButtonTypeRst : "Nút Nhập lại",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "Tên",
+DlgCheckboxValue : "Giá trị",
+DlgCheckboxSelected : "Được chọn",
+
+// Form Dialog
+DlgFormName : "Tên",
+DlgFormAction : "Hành động",
+DlgFormMethod : "Phương thức",
+
+// Select Field Dialog
+DlgSelectName : "Tên",
+DlgSelectValue : "Giá trị",
+DlgSelectSize : "Kích cỡ",
+DlgSelectLines : "dòng",
+DlgSelectChkMulti : "Cho phép chọn nhiều",
+DlgSelectOpAvail : "Các tùy chọn có thể sử dụng",
+DlgSelectOpText : "Văn bản",
+DlgSelectOpValue : "Giá trị",
+DlgSelectBtnAdd : "Thêm",
+DlgSelectBtnModify : "Thay đổi",
+DlgSelectBtnUp : "Lên",
+DlgSelectBtnDown : "Xuống",
+DlgSelectBtnSetValue : "Giá trị được chọn",
+DlgSelectBtnDelete : "Xoá",
+
+// Textarea Dialog
+DlgTextareaName : "Tên",
+DlgTextareaCols : "Cột",
+DlgTextareaRows : "Hàng",
+
+// Text Field Dialog
+DlgTextName : "Tên",
+DlgTextValue : "Giá trị",
+DlgTextCharWidth : "Rộng",
+DlgTextMaxChars : "Số Ký tự tối đa",
+DlgTextType : "Kiểu",
+DlgTextTypeText : "Ký tự",
+DlgTextTypePass : "Mật khẩu",
+
+// Hidden Field Dialog
+DlgHiddenName : "Tên",
+DlgHiddenValue : "Giá trị",
+
+// Bulleted List Dialog
+BulletedListProp : "Thuộc tính Danh sách không thứ tự",
+NumberedListProp : "Thuộc tính Danh sách có thứ tự",
+DlgLstStart : "Bắt đầu",
+DlgLstType : "Kiểu",
+DlgLstTypeCircle : "Hình tròn",
+DlgLstTypeDisc : "Hình đĩa",
+DlgLstTypeSquare : "Hình vuông",
+DlgLstTypeNumbers : "Số thứ tự (1, 2, 3)",
+DlgLstTypeLCase : "Chữ cái thường (a, b, c)",
+DlgLstTypeUCase : "Chữ cái hoa (A, B, C)",
+DlgLstTypeSRoman : "Số La Mã thường (i, ii, iii)",
+DlgLstTypeLRoman : "Số La Mã hoa (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "Toàn thể",
+DlgDocBackTab : "Nền",
+DlgDocColorsTab : "Màu sắc và Đường biên",
+DlgDocMetaTab : "Siêu dữ liệu",
+
+DlgDocPageTitle : "Tiêu đề Trang",
+DlgDocLangDir : "Đường dẫn Ngôn ngữ",
+DlgDocLangDirLTR : "Trái sang Phải (LTR)",
+DlgDocLangDirRTL : "Phải sang Trái (RTL)",
+DlgDocLangCode : "Mã Ngôn ngữ",
+DlgDocCharSet : "Bảng mã ký tự",
+DlgDocCharSetCE : "Trung Âu",
+DlgDocCharSetCT : "Tiếng Trung Quốc (Big5)",
+DlgDocCharSetCR : "Tiếng Kirin",
+DlgDocCharSetGR : "Tiếng Hy Lạp",
+DlgDocCharSetJP : "Tiếng Nhật",
+DlgDocCharSetKR : "Tiếng Hàn",
+DlgDocCharSetTR : "Tiếng Thổ Nhĩ Kỳ",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "Tây Âu",
+DlgDocCharSetOther : "Bảng mã ký tự khác",
+
+DlgDocDocType : "Kiểu Đề mục Tài liệu",
+DlgDocDocTypeOther : "Kiểu Đề mục Tài liệu khác",
+DlgDocIncXHTML : "Bao gồm cả định nghĩa XHTML",
+DlgDocBgColor : "Màu nền",
+DlgDocBgImage : "URL của Hình ảnh nền",
+DlgDocBgNoScroll : "Không cuộn nền",
+DlgDocCText : "Văn bản",
+DlgDocCLink : "Liên kết",
+DlgDocCVisited : "Liên kết Đã ghé thăm",
+DlgDocCActive : "Liên kết Hiện hành",
+DlgDocMargins : "Đường biên của Trang",
+DlgDocMaTop : "Trên",
+DlgDocMaLeft : "Trái",
+DlgDocMaRight : "Phải",
+DlgDocMaBottom : "Dưới",
+DlgDocMeIndex : "Các từ khóa chỉ mục tài liệu (phân cách bởi dấu phẩy)",
+DlgDocMeDescr : "Mô tả tài liệu",
+DlgDocMeAuthor : "Tác giả",
+DlgDocMeCopy : "Bản quyền",
+DlgDocPreview : "Xem trước",
+
+// Templates Dialog
+Templates : "Mẫu dựng sẵn",
+DlgTemplatesTitle : "Nội dung Mẫu dựng sẵn",
+DlgTemplatesSelMsg : "Hãy chọn Mẫu dựng sẵn để mở trong trình biên tập<br>(nội dung hiện tại sẽ bị mất):",
+DlgTemplatesLoading : "Đang nạp Danh sách Mẫu dựng sẵn. Vui lòng đợi trong giây lát...",
+DlgTemplatesNoTpl : "(Không có Mẫu dựng sẵn nào được định nghĩa)",
+DlgTemplatesReplace : "Thay thế nội dung hiện tại",
+
+// About Dialog
+DlgAboutAboutTab : "Giới thiệu",
+DlgAboutBrowserInfoTab : "Thông tin trình duyệt",
+DlgAboutLicenseTab : "Giấy phép",
+DlgAboutVersion : "phiên bản",
+DlgAboutInfo : "Để biết thêm thông tin, hãy truy cập"
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/zh-cn.js b/httemplate/elements/fckeditor/editor/lang/zh-cn.js
new file mode 100644
index 000000000..6d6f4f411
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/zh-cn.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Chinese Simplified language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "折叠工具栏",
+ToolbarExpand : "展开工具栏",
+
+// Toolbar Items and Context Menu
+Save : "保存",
+NewPage : "新建",
+Preview : "预览",
+Cut : "剪切",
+Copy : "复制",
+Paste : "粘贴",
+PasteText : "粘贴为无格式文本",
+PasteWord : "从 MS Word 粘贴",
+Print : "打印",
+SelectAll : "全选",
+RemoveFormat : "清除格式",
+InsertLinkLbl : "超链接",
+InsertLink : "插入/编辑超链接",
+RemoveLink : "取消超链接",
+Anchor : "插入/编辑锚点链接",
+InsertImageLbl : "图象",
+InsertImage : "插入/编辑图象",
+InsertFlashLbl : "Flash",
+InsertFlash : "插入/编辑 Flash",
+InsertTableLbl : "表格",
+InsertTable : "插入/编辑表格",
+InsertLineLbl : "水平线",
+InsertLine : "插入水平线",
+InsertSpecialCharLbl: "特殊符号",
+InsertSpecialChar : "插入特殊符号",
+InsertSmileyLbl : "表情符",
+InsertSmiley : "插入表情图标",
+About : "关于 FCKeditor",
+Bold : "加粗",
+Italic : "倾斜",
+Underline : "下划线",
+StrikeThrough : "删除线",
+Subscript : "下标",
+Superscript : "上标",
+LeftJustify : "左对齐",
+CenterJustify : "居中对齐",
+RightJustify : "右对齐",
+BlockJustify : "两端对齐",
+DecreaseIndent : "减少缩进量",
+IncreaseIndent : "增加缩进量",
+Undo : "撤消",
+Redo : "重做",
+NumberedListLbl : "编号列表",
+NumberedList : "插入/删除编号列表",
+BulletedListLbl : "项目列表",
+BulletedList : "插入/删除项目列表",
+ShowTableBorders : "显示表格边框",
+ShowDetails : "显示详细资料",
+Style : "样式",
+FontFormat : "格式",
+Font : "字体",
+FontSize : "大小",
+TextColor : "文本颜色",
+BGColor : "背景颜色",
+Source : "源代码",
+Find : "查找",
+Replace : "替换",
+SpellCheck : "拼写检查",
+UniversalKeyboard : "软键盘",
+PageBreakLbl : "分页符",
+PageBreak : "插入分页符",
+
+Form : "表单",
+Checkbox : "复选框",
+RadioButton : "单选按钮",
+TextField : "单行文本",
+Textarea : "多行文本",
+HiddenField : "隐藏域",
+Button : "按钮",
+SelectionField : "列表/菜单",
+ImageButton : "图像域",
+
+FitWindow : "全屏编辑",
+
+// Context Menu
+EditLink : "编辑超链接",
+CellCM : "单元格",
+RowCM : "行",
+ColumnCM : "列",
+InsertRow : "插入行",
+DeleteRows : "删除行",
+InsertColumn : "插入列",
+DeleteColumns : "删除列",
+InsertCell : "插入单元格",
+DeleteCells : "删除单元格",
+MergeCells : "合并单元格",
+SplitCell : "拆分单元格",
+TableDelete : "删除表格",
+CellProperties : "单元格属性",
+TableProperties : "表格属性",
+ImageProperties : "图象属性",
+FlashProperties : "Flash 属性",
+
+AnchorProp : "锚点链接属性",
+ButtonProp : "按钮属性",
+CheckboxProp : "复选框属性",
+HiddenFieldProp : "隐藏域属性",
+RadioButtonProp : "单选按钮属性",
+ImageButtonProp : "图像域属性",
+TextFieldProp : "单行文本属性",
+SelectionFieldProp : "菜单/列表属性",
+TextareaProp : "多行文本属性",
+FormProp : "表单属性",
+
+FontFormats : "普通;已编排格式;地址;标题 1;标题 2;标题 3;标题 4;标题 5;标题 6;段落(DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "正在处理 XHTML,请稍等...",
+Done : "完成",
+PasteWordConfirm : "您要粘贴的内容好像是来自 MS Word,是否要清除 MS Word 格式后再粘贴?",
+NotCompatiblePaste : "该命令需要 Internet Explorer 5.5 或更高版本的支持,是否按常规粘贴进行?",
+UnknownToolbarItem : "未知工具栏项目 \"%1\"",
+UnknownCommand : "未知命令名称 \"%1\"",
+NotImplemented : "命令无法执行",
+UnknownToolbarSet : "工具栏设置 \"%1\" 不存在",
+NoActiveX : "浏览器安全设置限制了本编辑器的某些功能。您必须启用安全设置中的“运行 ActiveX 控件和插件”,否则将出现某些错误并缺少功能。",
+BrowseServerBlocked : "无法打开资源浏览器,请确认是否启用了禁止弹出窗口。",
+DialogBlocked : "无法打开对话框窗口,请确认是否启用了禁止弹出窗口或网页对话框(IE)。",
+
+// Dialogs
+DlgBtnOK : "确定",
+DlgBtnCancel : "取消",
+DlgBtnClose : "关闭",
+DlgBtnBrowseServer : "浏览服务器",
+DlgAdvancedTag : "高级",
+DlgOpOther : "<其它>",
+DlgInfoTab : "信息",
+DlgAlertUrl : "请插入 URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<没有设置>",
+DlgGenId : "ID",
+DlgGenLangDir : "语言方向",
+DlgGenLangDirLtr : "从左到右 (LTR)",
+DlgGenLangDirRtl : "从右到左 (RTL)",
+DlgGenLangCode : "语言代码",
+DlgGenAccessKey : "访问键",
+DlgGenName : "名称",
+DlgGenTabIndex : "Tab 键次序",
+DlgGenLongDescr : "详细说明地址",
+DlgGenClass : "样式类名称",
+DlgGenTitle : "标题",
+DlgGenContType : "内容类型",
+DlgGenLinkCharset : "字符编码",
+DlgGenStyle : "行内样式",
+
+// Image Dialog
+DlgImgTitle : "图象属性",
+DlgImgInfoTab : "图象",
+DlgImgBtnUpload : "发送到服务器上",
+DlgImgURL : "源文件",
+DlgImgUpload : "上传",
+DlgImgAlt : "替换文本",
+DlgImgWidth : "宽度",
+DlgImgHeight : "高度",
+DlgImgLockRatio : "锁定比例",
+DlgBtnResetSize : "恢复尺寸",
+DlgImgBorder : "边框大小",
+DlgImgHSpace : "水平间距",
+DlgImgVSpace : "垂直间距",
+DlgImgAlign : "对齐方式",
+DlgImgAlignLeft : "左对齐",
+DlgImgAlignAbsBottom: "绝对底边",
+DlgImgAlignAbsMiddle: "绝对居中",
+DlgImgAlignBaseline : "基线",
+DlgImgAlignBottom : "底边",
+DlgImgAlignMiddle : "居中",
+DlgImgAlignRight : "右对齐",
+DlgImgAlignTextTop : "文本上方",
+DlgImgAlignTop : "顶端",
+DlgImgPreview : "预览",
+DlgImgAlertUrl : "请输入图象地址",
+DlgImgLinkTab : "链接",
+
+// Flash Dialog
+DlgFlashTitle : "Flash 属性",
+DlgFlashChkPlay : "自动播放",
+DlgFlashChkLoop : "循环",
+DlgFlashChkMenu : "启用 Flash 菜单",
+DlgFlashScale : "缩放",
+DlgFlashScaleAll : "全部显示",
+DlgFlashScaleNoBorder : "无边框",
+DlgFlashScaleFit : "严格匹配",
+
+// Link Dialog
+DlgLnkWindowTitle : "超链接",
+DlgLnkInfoTab : "超链接信息",
+DlgLnkTargetTab : "目标",
+
+DlgLnkType : "超链接类型",
+DlgLnkTypeURL : "超链接",
+DlgLnkTypeAnchor : "页内锚点链接",
+DlgLnkTypeEMail : "电子邮件",
+DlgLnkProto : "协议",
+DlgLnkProtoOther : "<其它>",
+DlgLnkURL : "地址",
+DlgLnkAnchorSel : "选择一个锚点",
+DlgLnkAnchorByName : "按锚点名称",
+DlgLnkAnchorById : "按锚点 ID",
+DlgLnkNoAnchors : "<此文档没有可用的锚点>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "地址",
+DlgLnkEMailSubject : "主题",
+DlgLnkEMailBody : "内容",
+DlgLnkUpload : "上传",
+DlgLnkBtnUpload : "发送到服务器上",
+
+DlgLnkTarget : "目标",
+DlgLnkTargetFrame : "<框架>",
+DlgLnkTargetPopup : "<弹出窗口>",
+DlgLnkTargetBlank : "新窗口 (_blank)",
+DlgLnkTargetParent : "父窗口 (_parent)",
+DlgLnkTargetSelf : "本窗口 (_self)",
+DlgLnkTargetTop : "整页 (_top)",
+DlgLnkTargetFrameName : "目标框架名称",
+DlgLnkPopWinName : "弹出窗口名称",
+DlgLnkPopWinFeat : "弹出窗口属性",
+DlgLnkPopResize : "调整大小",
+DlgLnkPopLocation : "地址栏",
+DlgLnkPopMenu : "菜单栏",
+DlgLnkPopScroll : "滚动条",
+DlgLnkPopStatus : "状态栏",
+DlgLnkPopToolbar : "工具栏",
+DlgLnkPopFullScrn : "全屏 (IE)",
+DlgLnkPopDependent : "依附 (NS)",
+DlgLnkPopWidth : "宽",
+DlgLnkPopHeight : "高",
+DlgLnkPopLeft : "左",
+DlgLnkPopTop : "右",
+
+DlnLnkMsgNoUrl : "请输入超链接地址",
+DlnLnkMsgNoEMail : "请输入电子邮件地址",
+DlnLnkMsgNoAnchor : "请选择一个锚点",
+DlnLnkMsgInvPopName : "弹出窗口名称必须以字母开头,并且不能含有空格。",
+
+// Color Dialog
+DlgColorTitle : "选择颜色",
+DlgColorBtnClear : "清除",
+DlgColorHighlight : "预览",
+DlgColorSelected : "选择",
+
+// Smiley Dialog
+DlgSmileyTitle : "插入表情图标",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "选择特殊符号",
+
+// Table Dialog
+DlgTableTitle : "表格属性",
+DlgTableRows : "行数",
+DlgTableColumns : "列数",
+DlgTableBorder : "边框",
+DlgTableAlign : "对齐",
+DlgTableAlignNotSet : "<没有设置>",
+DlgTableAlignLeft : "左对齐",
+DlgTableAlignCenter : "居中",
+DlgTableAlignRight : "右对齐",
+DlgTableWidth : "宽度",
+DlgTableWidthPx : "像素",
+DlgTableWidthPc : "百分比",
+DlgTableHeight : "高度",
+DlgTableCellSpace : "间距",
+DlgTableCellPad : "边距",
+DlgTableCaption : "标题",
+DlgTableSummary : "摘要",
+
+// Table Cell Dialog
+DlgCellTitle : "单元格属性",
+DlgCellWidth : "宽度",
+DlgCellWidthPx : "像素",
+DlgCellWidthPc : "百分比",
+DlgCellHeight : "高度",
+DlgCellWordWrap : "自动换行",
+DlgCellWordWrapNotSet : "<没有设置>",
+DlgCellWordWrapYes : "是",
+DlgCellWordWrapNo : "否",
+DlgCellHorAlign : "水平对齐",
+DlgCellHorAlignNotSet : "<没有设置>",
+DlgCellHorAlignLeft : "左对齐",
+DlgCellHorAlignCenter : "居中",
+DlgCellHorAlignRight: "右对齐",
+DlgCellVerAlign : "垂直对齐",
+DlgCellVerAlignNotSet : "<没有设置>",
+DlgCellVerAlignTop : "顶端",
+DlgCellVerAlignMiddle : "居中",
+DlgCellVerAlignBottom : "底部",
+DlgCellVerAlignBaseline : "基线",
+DlgCellRowSpan : "纵跨行数",
+DlgCellCollSpan : "横跨列数",
+DlgCellBackColor : "背景颜色",
+DlgCellBorderColor : "边框颜色",
+DlgCellBtnSelect : "选择...",
+
+// Find Dialog
+DlgFindTitle : "查找",
+DlgFindFindBtn : "查找",
+DlgFindNotFoundMsg : "指定文本没有找到。",
+
+// Replace Dialog
+DlgReplaceTitle : "替换",
+DlgReplaceFindLbl : "查找:",
+DlgReplaceReplaceLbl : "替换:",
+DlgReplaceCaseChk : "区分大小写",
+DlgReplaceReplaceBtn : "替换",
+DlgReplaceReplAllBtn : "全部替换",
+DlgReplaceWordChk : "全字匹配",
+
+// Paste Operations / Dialog
+PasteErrorCut : "您的浏览器安全设置不允许编辑器自动执行剪切操作,请使用键盘快捷键(Ctrl+X)来完成。",
+PasteErrorCopy : "您的浏览器安全设置不允许编辑器自动执行复制操作,请使用键盘快捷键(Ctrl+C)来完成。",
+
+PasteAsText : "粘贴为无格式文本",
+PasteFromWord : "从 MS Word 粘贴",
+
+DlgPasteMsg2 : "请使用键盘快捷键(<STRONG>Ctrl+V</STRONG>)把内容粘贴到下面的方框里,再按 <STRONG>确定</STRONG>。",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "忽略 Font 标签",
+DlgPasteRemoveStyles : "清理 CSS 样式",
+DlgPasteCleanBox : "清空上面内容",
+
+// Color Picker
+ColorAutomatic : "自动",
+ColorMoreColors : "其它颜色...",
+
+// Document Properties
+DocProps : "页面属性",
+
+// Anchor Dialog
+DlgAnchorTitle : "命名锚点",
+DlgAnchorName : "锚点名称",
+DlgAnchorErrorName : "请输入锚点名称",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "没有在字典里",
+DlgSpellChangeTo : "更改为",
+DlgSpellBtnIgnore : "忽略",
+DlgSpellBtnIgnoreAll : "全部忽略",
+DlgSpellBtnReplace : "替换",
+DlgSpellBtnReplaceAll : "全部替换",
+DlgSpellBtnUndo : "撤消",
+DlgSpellNoSuggestions : "- 没有建议 -",
+DlgSpellProgress : "正在进行拼写检查...",
+DlgSpellNoMispell : "拼写检查完成:没有发现拼写错误",
+DlgSpellNoChanges : "拼写检查完成:没有更改任何单词",
+DlgSpellOneChange : "拼写检查完成:更改了一个单词",
+DlgSpellManyChanges : "拼写检查完成:更改了 %1 个单词",
+
+IeSpellDownload : "拼写检查插件还没安装,你是否想现在就下载?",
+
+// Button Dialog
+DlgButtonText : "标签(值)",
+DlgButtonType : "类型",
+DlgButtonTypeBtn : "按钮",
+DlgButtonTypeSbm : "提交",
+DlgButtonTypeRst : "重设",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "名称",
+DlgCheckboxValue : "选定值",
+DlgCheckboxSelected : "已勾选",
+
+// Form Dialog
+DlgFormName : "名称",
+DlgFormAction : "动作",
+DlgFormMethod : "方法",
+
+// Select Field Dialog
+DlgSelectName : "名称",
+DlgSelectValue : "选定",
+DlgSelectSize : "高度",
+DlgSelectLines : "行",
+DlgSelectChkMulti : "允许多选",
+DlgSelectOpAvail : "列表值",
+DlgSelectOpText : "标签",
+DlgSelectOpValue : "值",
+DlgSelectBtnAdd : "新增",
+DlgSelectBtnModify : "修改",
+DlgSelectBtnUp : "上移",
+DlgSelectBtnDown : "下移",
+DlgSelectBtnSetValue : "设为初始化时选定",
+DlgSelectBtnDelete : "删除",
+
+// Textarea Dialog
+DlgTextareaName : "名称",
+DlgTextareaCols : "字符宽度",
+DlgTextareaRows : "行数",
+
+// Text Field Dialog
+DlgTextName : "名称",
+DlgTextValue : "初始值",
+DlgTextCharWidth : "字符宽度",
+DlgTextMaxChars : "最多字符数",
+DlgTextType : "类型",
+DlgTextTypeText : "文本",
+DlgTextTypePass : "密码",
+
+// Hidden Field Dialog
+DlgHiddenName : "名称",
+DlgHiddenValue : "初始值",
+
+// Bulleted List Dialog
+BulletedListProp : "项目列表属性",
+NumberedListProp : "编号列表属性",
+DlgLstStart : "开始序号",
+DlgLstType : "列表类型",
+DlgLstTypeCircle : "圆圈",
+DlgLstTypeDisc : "圆点",
+DlgLstTypeSquare : "方块",
+DlgLstTypeNumbers : "数字 (1, 2, 3)",
+DlgLstTypeLCase : "小写字母 (a, b, c)",
+DlgLstTypeUCase : "大写字母 (A, B, C)",
+DlgLstTypeSRoman : "小写罗马数字 (i, ii, iii)",
+DlgLstTypeLRoman : "大写罗马数字 (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "常规",
+DlgDocBackTab : "背景",
+DlgDocColorsTab : "颜色和边距",
+DlgDocMetaTab : "Meta 数据",
+
+DlgDocPageTitle : "页面标题",
+DlgDocLangDir : "语言方向",
+DlgDocLangDirLTR : "从左到右 (LTR)",
+DlgDocLangDirRTL : "从右到左 (RTL)",
+DlgDocLangCode : "语言代码",
+DlgDocCharSet : "字符编码",
+DlgDocCharSetCE : "中欧",
+DlgDocCharSetCT : "繁体中文 (Big5)",
+DlgDocCharSetCR : "西里尔文",
+DlgDocCharSetGR : "希腊文",
+DlgDocCharSetJP : "日文",
+DlgDocCharSetKR : "韩文",
+DlgDocCharSetTR : "土耳其文",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "西欧",
+DlgDocCharSetOther : "其它字符编码",
+
+DlgDocDocType : "文档类型",
+DlgDocDocTypeOther : "其它文档类型",
+DlgDocIncXHTML : "包含 XHTML 声明",
+DlgDocBgColor : "背景颜色",
+DlgDocBgImage : "背景图像",
+DlgDocBgNoScroll : "不滚动背景图像",
+DlgDocCText : "文本",
+DlgDocCLink : "超链接",
+DlgDocCVisited : "已访问的超链接",
+DlgDocCActive : "活动超链接",
+DlgDocMargins : "页面边距",
+DlgDocMaTop : "上",
+DlgDocMaLeft : "左",
+DlgDocMaRight : "右",
+DlgDocMaBottom : "下",
+DlgDocMeIndex : "页面索引关键字 (用半角逗号[,]分隔)",
+DlgDocMeDescr : "页面说明",
+DlgDocMeAuthor : "作者",
+DlgDocMeCopy : "版权",
+DlgDocPreview : "预览",
+
+// Templates Dialog
+Templates : "模板",
+DlgTemplatesTitle : "内容模板",
+DlgTemplatesSelMsg : "请选择编辑器内容模板<br>(当前内容将会被清除替换):",
+DlgTemplatesLoading : "正在加载模板列表,请稍等...",
+DlgTemplatesNoTpl : "(没有模板)",
+DlgTemplatesReplace : "替换当前内容",
+
+// About Dialog
+DlgAboutAboutTab : "关于",
+DlgAboutBrowserInfoTab : "浏览器信息",
+DlgAboutLicenseTab : "许可证",
+DlgAboutVersion : "版本",
+DlgAboutInfo : "要获得更多信息请访问 "
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/lang/zh.js b/httemplate/elements/fckeditor/editor/lang/zh.js
new file mode 100644
index 000000000..b5cd2397e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/lang/zh.js
@@ -0,0 +1,504 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Chinese Traditional language file.
+ */
+
+var FCKLang =
+{
+// Language direction : "ltr" (left to right) or "rtl" (right to left).
+Dir : "ltr",
+
+ToolbarCollapse : "隱藏面板",
+ToolbarExpand : "顯示面板",
+
+// Toolbar Items and Context Menu
+Save : "儲存",
+NewPage : "開新檔案",
+Preview : "預覽",
+Cut : "剪下",
+Copy : "複製",
+Paste : "貼上",
+PasteText : "貼為純文字格式",
+PasteWord : "自 Word 貼上",
+Print : "列印",
+SelectAll : "全選",
+RemoveFormat : "清除格式",
+InsertLinkLbl : "超連結",
+InsertLink : "插入/編輯超連結",
+RemoveLink : "移除超連結",
+Anchor : "插入/編輯錨點",
+InsertImageLbl : "影像",
+InsertImage : "插入/編輯影像",
+InsertFlashLbl : "Flash",
+InsertFlash : "插入/編輯 Flash",
+InsertTableLbl : "表格",
+InsertTable : "插入/編輯表格",
+InsertLineLbl : "水平線",
+InsertLine : "插入水平線",
+InsertSpecialCharLbl: "特殊符號",
+InsertSpecialChar : "插入特殊符號",
+InsertSmileyLbl : "表情符號",
+InsertSmiley : "插入表情符號",
+About : "關於 FCKeditor",
+Bold : "粗體",
+Italic : "斜體",
+Underline : "底線",
+StrikeThrough : "刪除線",
+Subscript : "下標",
+Superscript : "上標",
+LeftJustify : "靠左對齊",
+CenterJustify : "置中",
+RightJustify : "靠右對齊",
+BlockJustify : "左右對齊",
+DecreaseIndent : "減少縮排",
+IncreaseIndent : "增加縮排",
+Undo : "復原",
+Redo : "重複",
+NumberedListLbl : "編號清單",
+NumberedList : "插入/移除編號清單",
+BulletedListLbl : "項目清單",
+BulletedList : "插入/移除項目清單",
+ShowTableBorders : "顯示表格邊框",
+ShowDetails : "顯示詳細資料",
+Style : "樣式",
+FontFormat : "格式",
+Font : "字體",
+FontSize : "大小",
+TextColor : "文字顏色",
+BGColor : "背景顏色",
+Source : "原始碼",
+Find : "尋找",
+Replace : "取代",
+SpellCheck : "拼字檢查",
+UniversalKeyboard : "萬國鍵盤",
+PageBreakLbl : "分頁符號",
+PageBreak : "插入分頁符號",
+
+Form : "表單",
+Checkbox : "核取方塊",
+RadioButton : "選項按鈕",
+TextField : "文字方塊",
+Textarea : "文字區域",
+HiddenField : "隱藏欄位",
+Button : "按鈕",
+SelectionField : "清單/選單",
+ImageButton : "影像按鈕",
+
+FitWindow : "編輯器最大化",
+
+// Context Menu
+EditLink : "編輯超連結",
+CellCM : "儲存格",
+RowCM : "列",
+ColumnCM : "欄",
+InsertRow : "插入列",
+DeleteRows : "刪除列",
+InsertColumn : "插入欄",
+DeleteColumns : "刪除欄",
+InsertCell : "插入儲存格",
+DeleteCells : "刪除儲存格",
+MergeCells : "合併儲存格",
+SplitCell : "分割儲存格",
+TableDelete : "刪除表格",
+CellProperties : "儲存格屬性",
+TableProperties : "表格屬性",
+ImageProperties : "影像屬性",
+FlashProperties : "Flash 屬性",
+
+AnchorProp : "錨點屬性",
+ButtonProp : "按鈕屬性",
+CheckboxProp : "核取方塊屬性",
+HiddenFieldProp : "隱藏欄位屬性",
+RadioButtonProp : "選項按鈕屬性",
+ImageButtonProp : "影像按鈕屬性",
+TextFieldProp : "文字方塊屬性",
+SelectionFieldProp : "清單/選單屬性",
+TextareaProp : "文字區域屬性",
+FormProp : "表單屬性",
+
+FontFormats : "本文;已格式化;位址;標題 1;標題 2;標題 3;標題 4;標題 5;標題 6;本文 (DIV)", //REVIEW : Check _getfontformat.html
+
+// Alerts and Messages
+ProcessingXHTML : "處理 XHTML 中,請稍候…",
+Done : "完成",
+PasteWordConfirm : "您想貼上的文字似乎是自 Word 複製而來,請問您是否要先清除 Word 的格式後再行貼上?",
+NotCompatiblePaste : "此指令僅在 Internet Explorer 5.5 或以上的版本有效。請問您是否同意不清除格式即貼上?",
+UnknownToolbarItem : "未知工具列項目 \"%1\"",
+UnknownCommand : "未知指令名稱 \"%1\"",
+NotImplemented : "尚未安裝此指令",
+UnknownToolbarSet : "工具列設定 \"%1\" 不存在",
+NoActiveX : "瀏覽器的安全性設定限制了本編輯器的某些功能。您必須啟用安全性設定中的「執行ActiveX控制項與外掛程式」項目,否則本編輯器將會出現錯誤並缺少某些功能",
+BrowseServerBlocked : "無法開啟資源瀏覽器,請確定所有快顯視窗封鎖程式是否關閉",
+DialogBlocked : "無法開啟對話視窗,請確定所有快顯視窗封鎖程式是否關閉",
+
+// Dialogs
+DlgBtnOK : "確定",
+DlgBtnCancel : "取消",
+DlgBtnClose : "關閉",
+DlgBtnBrowseServer : "瀏覽伺服器端",
+DlgAdvancedTag : "進階",
+DlgOpOther : "<其他>",
+DlgInfoTab : "資訊",
+DlgAlertUrl : "請插入 URL",
+
+// General Dialogs Labels
+DlgGenNotSet : "<尚未設定>",
+DlgGenId : "ID",
+DlgGenLangDir : "語言方向",
+DlgGenLangDirLtr : "由左而右 (LTR)",
+DlgGenLangDirRtl : "由右而左 (RTL)",
+DlgGenLangCode : "語言代碼",
+DlgGenAccessKey : "存取鍵",
+DlgGenName : "名稱",
+DlgGenTabIndex : "定位順序",
+DlgGenLongDescr : "詳細 URL",
+DlgGenClass : "樣式表類別",
+DlgGenTitle : "標題",
+DlgGenContType : "內容類型",
+DlgGenLinkCharset : "連結資源之編碼",
+DlgGenStyle : "樣式",
+
+// Image Dialog
+DlgImgTitle : "影像屬性",
+DlgImgInfoTab : "影像資訊",
+DlgImgBtnUpload : "上傳至伺服器",
+DlgImgURL : "URL",
+DlgImgUpload : "上傳",
+DlgImgAlt : "替代文字",
+DlgImgWidth : "寬度",
+DlgImgHeight : "高度",
+DlgImgLockRatio : "等比例",
+DlgBtnResetSize : "重設為原大小",
+DlgImgBorder : "邊框",
+DlgImgHSpace : "水平距離",
+DlgImgVSpace : "垂直距離",
+DlgImgAlign : "對齊",
+DlgImgAlignLeft : "靠左對齊",
+DlgImgAlignAbsBottom: "絕對下方",
+DlgImgAlignAbsMiddle: "絕對中間",
+DlgImgAlignBaseline : "基準線",
+DlgImgAlignBottom : "靠下對齊",
+DlgImgAlignMiddle : "置中對齊",
+DlgImgAlignRight : "靠右對齊",
+DlgImgAlignTextTop : "文字上方",
+DlgImgAlignTop : "靠上對齊",
+DlgImgPreview : "預覽",
+DlgImgAlertUrl : "請輸入影像 URL",
+DlgImgLinkTab : "超連結",
+
+// Flash Dialog
+DlgFlashTitle : "Flash 屬性",
+DlgFlashChkPlay : "自動播放",
+DlgFlashChkLoop : "重複",
+DlgFlashChkMenu : "開啟選單",
+DlgFlashScale : "縮放",
+DlgFlashScaleAll : "全部顯示",
+DlgFlashScaleNoBorder : "無邊框",
+DlgFlashScaleFit : "精確符合",
+
+// Link Dialog
+DlgLnkWindowTitle : "超連結",
+DlgLnkInfoTab : "超連結資訊",
+DlgLnkTargetTab : "目標",
+
+DlgLnkType : "超連接類型",
+DlgLnkTypeURL : "URL",
+DlgLnkTypeAnchor : "本頁錨點",
+DlgLnkTypeEMail : "電子郵件",
+DlgLnkProto : "通訊協定",
+DlgLnkProtoOther : "<其他>",
+DlgLnkURL : "URL",
+DlgLnkAnchorSel : "請選擇錨點",
+DlgLnkAnchorByName : "依錨點名稱",
+DlgLnkAnchorById : "依元件 ID",
+DlgLnkNoAnchors : "<本文件尚無可用之錨點>", //REVIEW : Change < and > with ( and )
+DlgLnkEMail : "電子郵件",
+DlgLnkEMailSubject : "郵件主旨",
+DlgLnkEMailBody : "郵件內容",
+DlgLnkUpload : "上傳",
+DlgLnkBtnUpload : "傳送至伺服器",
+
+DlgLnkTarget : "目標",
+DlgLnkTargetFrame : "<框架>",
+DlgLnkTargetPopup : "<快顯視窗>",
+DlgLnkTargetBlank : "新視窗 (_blank)",
+DlgLnkTargetParent : "父視窗 (_parent)",
+DlgLnkTargetSelf : "本視窗 (_self)",
+DlgLnkTargetTop : "最上層視窗 (_top)",
+DlgLnkTargetFrameName : "目標框架名稱",
+DlgLnkPopWinName : "快顯視窗名稱",
+DlgLnkPopWinFeat : "快顯視窗屬性",
+DlgLnkPopResize : "可調整大小",
+DlgLnkPopLocation : "網址列",
+DlgLnkPopMenu : "選單列",
+DlgLnkPopScroll : "捲軸",
+DlgLnkPopStatus : "狀態列",
+DlgLnkPopToolbar : "工具列",
+DlgLnkPopFullScrn : "全螢幕 (IE)",
+DlgLnkPopDependent : "從屬 (NS)",
+DlgLnkPopWidth : "寬",
+DlgLnkPopHeight : "高",
+DlgLnkPopLeft : "左",
+DlgLnkPopTop : "右",
+
+DlnLnkMsgNoUrl : "請輸入欲連結的 URL",
+DlnLnkMsgNoEMail : "請輸入電子郵件位址",
+DlnLnkMsgNoAnchor : "請選擇錨點",
+DlnLnkMsgInvPopName : "快顯名稱必須以「英文字母」為開頭,且不得含有空白",
+
+// Color Dialog
+DlgColorTitle : "請選擇顏色",
+DlgColorBtnClear : "清除",
+DlgColorHighlight : "預覽",
+DlgColorSelected : "選擇",
+
+// Smiley Dialog
+DlgSmileyTitle : "插入表情符號",
+
+// Special Character Dialog
+DlgSpecialCharTitle : "請選擇特殊符號",
+
+// Table Dialog
+DlgTableTitle : "表格屬性",
+DlgTableRows : "列數",
+DlgTableColumns : "欄數",
+DlgTableBorder : "邊框",
+DlgTableAlign : "對齊",
+DlgTableAlignNotSet : "<未設定>",
+DlgTableAlignLeft : "靠左對齊",
+DlgTableAlignCenter : "置中",
+DlgTableAlignRight : "靠右對齊",
+DlgTableWidth : "寬度",
+DlgTableWidthPx : "像素",
+DlgTableWidthPc : "百分比",
+DlgTableHeight : "高度",
+DlgTableCellSpace : "間距",
+DlgTableCellPad : "內距",
+DlgTableCaption : "標題",
+DlgTableSummary : "摘要",
+
+// Table Cell Dialog
+DlgCellTitle : "儲存格屬性",
+DlgCellWidth : "寬度",
+DlgCellWidthPx : "像素",
+DlgCellWidthPc : "百分比",
+DlgCellHeight : "高度",
+DlgCellWordWrap : "自動換行",
+DlgCellWordWrapNotSet : "<尚未設定>",
+DlgCellWordWrapYes : "是",
+DlgCellWordWrapNo : "否",
+DlgCellHorAlign : "水平對齊",
+DlgCellHorAlignNotSet : "<尚未設定>",
+DlgCellHorAlignLeft : "靠左對齊",
+DlgCellHorAlignCenter : "置中",
+DlgCellHorAlignRight: "靠右對齊",
+DlgCellVerAlign : "垂直對齊",
+DlgCellVerAlignNotSet : "<尚未設定>",
+DlgCellVerAlignTop : "靠上對齊",
+DlgCellVerAlignMiddle : "置中",
+DlgCellVerAlignBottom : "靠下對齊",
+DlgCellVerAlignBaseline : "基準線",
+DlgCellRowSpan : "合併列數",
+DlgCellCollSpan : "合併欄数",
+DlgCellBackColor : "背景顏色",
+DlgCellBorderColor : "邊框顏色",
+DlgCellBtnSelect : "請選擇…",
+
+// Find Dialog
+DlgFindTitle : "尋找",
+DlgFindFindBtn : "尋找",
+DlgFindNotFoundMsg : "未找到指定的文字。",
+
+// Replace Dialog
+DlgReplaceTitle : "取代",
+DlgReplaceFindLbl : "尋找:",
+DlgReplaceReplaceLbl : "取代:",
+DlgReplaceCaseChk : "大小寫須相符",
+DlgReplaceReplaceBtn : "取代",
+DlgReplaceReplAllBtn : "全部取代",
+DlgReplaceWordChk : "全字相符",
+
+// Paste Operations / Dialog
+PasteErrorCut : "瀏覽器的安全性設定不允許編輯器自動執行剪下動作。請使用快捷鍵 (Ctrl+X) 剪下。",
+PasteErrorCopy : "瀏覽器的安全性設定不允許編輯器自動執行複製動作。請使用快捷鍵 (Ctrl+C) 複製。",
+
+PasteAsText : "貼為純文字格式",
+PasteFromWord : "自 Word 貼上",
+
+DlgPasteMsg2 : "請使用快捷鍵 (<strong>Ctrl+V</strong>) 貼到下方區域中並按下 <strong>確定</strong>",
+DlgPasteSec : "Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.", //MISSING
+DlgPasteIgnoreFont : "移除字型設定",
+DlgPasteRemoveStyles : "移除樣式設定",
+DlgPasteCleanBox : "清除文字區域",
+
+// Color Picker
+ColorAutomatic : "自動",
+ColorMoreColors : "更多顏色…",
+
+// Document Properties
+DocProps : "文件屬性",
+
+// Anchor Dialog
+DlgAnchorTitle : "命名錨點",
+DlgAnchorName : "錨點名稱",
+DlgAnchorErrorName : "請輸入錨點名稱",
+
+// Speller Pages Dialog
+DlgSpellNotInDic : "不在字典中",
+DlgSpellChangeTo : "更改為",
+DlgSpellBtnIgnore : "忽略",
+DlgSpellBtnIgnoreAll : "全部忽略",
+DlgSpellBtnReplace : "取代",
+DlgSpellBtnReplaceAll : "全部取代",
+DlgSpellBtnUndo : "復原",
+DlgSpellNoSuggestions : "- 無建議值 -",
+DlgSpellProgress : "進行拼字檢查中…",
+DlgSpellNoMispell : "拼字檢查完成:未發現拼字錯誤",
+DlgSpellNoChanges : "拼字檢查完成:未更改任何單字",
+DlgSpellOneChange : "拼字檢查完成:更改了 1 個單字",
+DlgSpellManyChanges : "拼字檢查完成:更改了 %1 個單字",
+
+IeSpellDownload : "尚未安裝拼字檢查元件。您是否想要現在下載?",
+
+// Button Dialog
+DlgButtonText : "顯示文字 (值)",
+DlgButtonType : "類型",
+DlgButtonTypeBtn : "按鈕 (Button)",
+DlgButtonTypeSbm : "送出 (Submit)",
+DlgButtonTypeRst : "重設 (Reset)",
+
+// Checkbox and Radio Button Dialogs
+DlgCheckboxName : "名稱",
+DlgCheckboxValue : "選取值",
+DlgCheckboxSelected : "已選取",
+
+// Form Dialog
+DlgFormName : "名稱",
+DlgFormAction : "動作",
+DlgFormMethod : "方法",
+
+// Select Field Dialog
+DlgSelectName : "名稱",
+DlgSelectValue : "選取值",
+DlgSelectSize : "大小",
+DlgSelectLines : "行",
+DlgSelectChkMulti : "可多選",
+DlgSelectOpAvail : "可用選項",
+DlgSelectOpText : "顯示文字",
+DlgSelectOpValue : "值",
+DlgSelectBtnAdd : "新增",
+DlgSelectBtnModify : "修改",
+DlgSelectBtnUp : "上移",
+DlgSelectBtnDown : "下移",
+DlgSelectBtnSetValue : "設為預設值",
+DlgSelectBtnDelete : "刪除",
+
+// Textarea Dialog
+DlgTextareaName : "名稱",
+DlgTextareaCols : "字元寬度",
+DlgTextareaRows : "列數",
+
+// Text Field Dialog
+DlgTextName : "名稱",
+DlgTextValue : "值",
+DlgTextCharWidth : "字元寬度",
+DlgTextMaxChars : "最多字元數",
+DlgTextType : "類型",
+DlgTextTypeText : "文字",
+DlgTextTypePass : "密碼",
+
+// Hidden Field Dialog
+DlgHiddenName : "名稱",
+DlgHiddenValue : "值",
+
+// Bulleted List Dialog
+BulletedListProp : "項目清單屬性",
+NumberedListProp : "編號清單屬性",
+DlgLstStart : "起始編號",
+DlgLstType : "清單類型",
+DlgLstTypeCircle : "圓圈",
+DlgLstTypeDisc : "圓點",
+DlgLstTypeSquare : "方塊",
+DlgLstTypeNumbers : "數字 (1, 2, 3)",
+DlgLstTypeLCase : "小寫字母 (a, b, c)",
+DlgLstTypeUCase : "大寫字母 (A, B, C)",
+DlgLstTypeSRoman : "小寫羅馬數字 (i, ii, iii)",
+DlgLstTypeLRoman : "大寫羅馬數字 (I, II, III)",
+
+// Document Properties Dialog
+DlgDocGeneralTab : "一般",
+DlgDocBackTab : "背景",
+DlgDocColorsTab : "顯色與邊界",
+DlgDocMetaTab : "Meta 資料",
+
+DlgDocPageTitle : "頁面標題",
+DlgDocLangDir : "語言方向",
+DlgDocLangDirLTR : "由左而右 (LTR)",
+DlgDocLangDirRTL : "由右而左 (RTL)",
+DlgDocLangCode : "語言代碼",
+DlgDocCharSet : "字元編碼",
+DlgDocCharSetCE : "中歐語系",
+DlgDocCharSetCT : "正體中文 (Big5)",
+DlgDocCharSetCR : "斯拉夫文",
+DlgDocCharSetGR : "希臘文",
+DlgDocCharSetJP : "日文",
+DlgDocCharSetKR : "韓文",
+DlgDocCharSetTR : "土耳其文",
+DlgDocCharSetUN : "Unicode (UTF-8)",
+DlgDocCharSetWE : "西歐語系",
+DlgDocCharSetOther : "其他字元編碼",
+
+DlgDocDocType : "文件類型",
+DlgDocDocTypeOther : "其他文件類型",
+DlgDocIncXHTML : "包含 XHTML 定義",
+DlgDocBgColor : "背景顏色",
+DlgDocBgImage : "背景影像",
+DlgDocBgNoScroll : "浮水印",
+DlgDocCText : "文字",
+DlgDocCLink : "超連結",
+DlgDocCVisited : "已瀏覽過的超連結",
+DlgDocCActive : "作用中的超連結",
+DlgDocMargins : "頁面邊界",
+DlgDocMaTop : "上",
+DlgDocMaLeft : "左",
+DlgDocMaRight : "右",
+DlgDocMaBottom : "下",
+DlgDocMeIndex : "文件索引關鍵字 (用半形逗號[,]分隔)",
+DlgDocMeDescr : "文件說明",
+DlgDocMeAuthor : "作者",
+DlgDocMeCopy : "版權所有",
+DlgDocPreview : "預覽",
+
+// Templates Dialog
+Templates : "樣版",
+DlgTemplatesTitle : "內容樣版",
+DlgTemplatesSelMsg : "請選擇欲開啟的樣版<br> (原有的內容將會被清除):",
+DlgTemplatesLoading : "讀取樣版清單中,請稍候…",
+DlgTemplatesNoTpl : "(無樣版)",
+DlgTemplatesReplace : "取代原有內容",
+
+// About Dialog
+DlgAboutAboutTab : "關於",
+DlgAboutBrowserInfoTab : "瀏覽器資訊",
+DlgAboutLicenseTab : "許可證",
+DlgAboutVersion : "版本",
+DlgAboutInfo : "想獲得更多資訊請至 "
+}; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/autogrow/fckplugin.js b/httemplate/elements/fckeditor/editor/plugins/autogrow/fckplugin.js
new file mode 100644
index 000000000..7ce1c1cc2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/autogrow/fckplugin.js
@@ -0,0 +1,92 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Plugin: automatically resizes the editor until a configurable maximun
+ * height (FCKConfig.AutoGrowMax), based on its contents.
+ */
+
+var FCKAutoGrow_Min = window.frameElement.offsetHeight ;
+
+function FCKAutoGrow_Check()
+{
+ var oInnerDoc = FCK.EditorDocument ;
+
+ var iFrameHeight, iInnerHeight ;
+
+ if ( FCKBrowserInfo.IsIE )
+ {
+ iFrameHeight = FCK.EditorWindow.frameElement.offsetHeight ;
+ iInnerHeight = oInnerDoc.body.scrollHeight ;
+ }
+ else
+ {
+ iFrameHeight = FCK.EditorWindow.innerHeight ;
+ iInnerHeight = oInnerDoc.body.offsetHeight ;
+ }
+
+ var iDiff = iInnerHeight - iFrameHeight ;
+
+ if ( iDiff != 0 )
+ {
+ var iMainFrameSize = window.frameElement.offsetHeight ;
+
+ if ( iDiff > 0 && iMainFrameSize < FCKConfig.AutoGrowMax )
+ {
+ iMainFrameSize += iDiff ;
+ if ( iMainFrameSize > FCKConfig.AutoGrowMax )
+ iMainFrameSize = FCKConfig.AutoGrowMax ;
+ }
+ else if ( iDiff < 0 && iMainFrameSize > FCKAutoGrow_Min )
+ {
+ iMainFrameSize += iDiff ;
+ if ( iMainFrameSize < FCKAutoGrow_Min )
+ iMainFrameSize = FCKAutoGrow_Min ;
+ }
+ else
+ return ;
+
+ window.frameElement.height = iMainFrameSize ;
+ }
+}
+
+FCK.AttachToOnSelectionChange( FCKAutoGrow_Check ) ;
+
+function FCKAutoGrow_SetListeners()
+{
+ if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
+ return ;
+
+ FCK.EditorWindow.attachEvent( 'onscroll', FCKAutoGrow_Check ) ;
+ FCK.EditorDocument.attachEvent( 'onkeyup', FCKAutoGrow_Check ) ;
+}
+
+if ( FCKBrowserInfo.IsIE )
+{
+// FCKAutoGrow_SetListeners() ;
+ FCK.Events.AttachEvent( 'OnAfterSetHTML', FCKAutoGrow_SetListeners ) ;
+}
+
+function FCKAutoGrow_CheckEditorStatus( sender, status )
+{
+ if ( status == FCK_STATUS_COMPLETE )
+ FCKAutoGrow_Check() ;
+}
+
+FCK.Events.AttachEvent( 'OnStatusChange', FCKAutoGrow_CheckEditorStatus ) ; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/fck_placeholder.html b/httemplate/elements/fckeditor/editor/plugins/placeholder/fck_placeholder.html
new file mode 100644
index 000000000..a334206a5
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/fck_placeholder.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placeholder Plugin.
+-->
+<html>
+ <head>
+ <title>Placeholder Properties</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta content="noindex, nofollow" name="robots">
+ <script language="javascript">
+
+var oEditor = window.parent.InnerDialogLoaded() ;
+var FCKLang = oEditor.FCKLang ;
+var FCKPlaceholders = oEditor.FCKPlaceholders ;
+
+window.onload = function ()
+{
+ // First of all, translate the dialog box texts
+ oEditor.FCKLanguageManager.TranslatePage( document ) ;
+
+ LoadSelected() ;
+
+ // Show the "Ok" button.
+ window.parent.SetOkButton( true ) ;
+}
+
+var eSelected = oEditor.FCKSelection.GetSelectedElement() ;
+
+function LoadSelected()
+{
+ if ( !eSelected )
+ return ;
+
+ if ( eSelected.tagName == 'SPAN' && eSelected._fckplaceholder )
+ document.getElementById('txtName').value = eSelected._fckplaceholder ;
+ else
+ eSelected == null ;
+}
+
+function Ok()
+{
+ var sValue = document.getElementById('txtName').value ;
+
+ if ( eSelected && eSelected._fckplaceholder == sValue )
+ return true ;
+
+ if ( sValue.length == 0 )
+ {
+ alert( FCKLang.PlaceholderErrNoName ) ;
+ return false ;
+ }
+
+ if ( FCKPlaceholders.Exist( sValue ) )
+ {
+ alert( FCKLang.PlaceholderErrNameInUse ) ;
+ return false ;
+ }
+
+ FCKPlaceholders.Add( sValue ) ;
+ return true ;
+}
+
+ </script>
+ </head>
+ <body scroll="no" style="OVERFLOW: hidden">
+ <table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td>
+ <table cellSpacing="0" cellPadding="0" align="center" border="0">
+ <tr>
+ <td>
+ <span fckLang="PlaceholderDlgName">Placeholder Name</span><br>
+ <input id="txtName" type="text">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/fckplugin.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/fckplugin.js
new file mode 100644
index 000000000..26489b872
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/fckplugin.js
@@ -0,0 +1,187 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Plugin to insert "Placeholders" in the editor.
+ */
+
+// Register the related command.
+FCKCommands.RegisterCommand( 'Placeholder', new FCKDialogCommand( 'Placeholder', FCKLang.PlaceholderDlgTitle, FCKPlugins.Items['placeholder'].Path + 'fck_placeholder.html', 340, 170 ) ) ;
+
+// Create the "Plaholder" toolbar button.
+var oPlaceholderItem = new FCKToolbarButton( 'Placeholder', FCKLang.PlaceholderBtn ) ;
+oPlaceholderItem.IconPath = FCKPlugins.Items['placeholder'].Path + 'placeholder.gif' ;
+
+FCKToolbarItems.RegisterItem( 'Placeholder', oPlaceholderItem ) ;
+
+
+// The object used for all Placeholder operations.
+var FCKPlaceholders = new Object() ;
+
+// Add a new placeholder at the actual selection.
+FCKPlaceholders.Add = function( name )
+{
+ var oSpan = FCK.CreateElement( 'SPAN' ) ;
+ this.SetupSpan( oSpan, name ) ;
+}
+
+FCKPlaceholders.SetupSpan = function( span, name )
+{
+ span.innerHTML = '[[ ' + name + ' ]]' ;
+
+ span.style.backgroundColor = '#ffff00' ;
+ span.style.color = '#000000' ;
+
+ if ( FCKBrowserInfo.IsGecko )
+ span.style.cursor = 'default' ;
+
+ span._fckplaceholder = name ;
+ span.contentEditable = false ;
+
+ // To avoid it to be resized.
+ span.onresizestart = function()
+ {
+ FCK.EditorWindow.event.returnValue = false ;
+ return false ;
+ }
+}
+
+// On Gecko we must do this trick so the user select all the SPAN when clicking on it.
+FCKPlaceholders._SetupClickListener = function()
+{
+ FCKPlaceholders._ClickListener = function( e )
+ {
+ if ( e.target.tagName == 'SPAN' && e.target._fckplaceholder )
+ FCKSelection.SelectNode( e.target ) ;
+ }
+
+ FCK.EditorDocument.addEventListener( 'click', FCKPlaceholders._ClickListener, true ) ;
+}
+
+// Open the Placeholder dialog on double click.
+FCKPlaceholders.OnDoubleClick = function( span )
+{
+ if ( span.tagName == 'SPAN' && span._fckplaceholder )
+ FCKCommands.GetCommand( 'Placeholder' ).Execute() ;
+}
+
+FCK.RegisterDoubleClickHandler( FCKPlaceholders.OnDoubleClick, 'SPAN' ) ;
+
+// Check if a Placholder name is already in use.
+FCKPlaceholders.Exist = function( name )
+{
+ var aSpans = FCK.EditorDocument.getElementsByTagName( 'SPAN' ) ;
+
+ for ( var i = 0 ; i < aSpans.length ; i++ )
+ {
+ if ( aSpans[i]._fckplaceholder == name )
+ return true ;
+ }
+
+ return false ;
+}
+
+if ( FCKBrowserInfo.IsIE )
+{
+ FCKPlaceholders.Redraw = function()
+ {
+ if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
+ return ;
+
+ var aPlaholders = FCK.EditorDocument.body.innerText.match( /\[\[[^\[\]]+\]\]/g ) ;
+ if ( !aPlaholders )
+ return ;
+
+ var oRange = FCK.EditorDocument.body.createTextRange() ;
+
+ for ( var i = 0 ; i < aPlaholders.length ; i++ )
+ {
+ if ( oRange.findText( aPlaholders[i] ) )
+ {
+ var sName = aPlaholders[i].match( /\[\[\s*([^\]]*?)\s*\]\]/ )[1] ;
+ oRange.pasteHTML( '<span style="color: #000000; background-color: #ffff00" contenteditable="false" _fckplaceholder="' + sName + '">' + aPlaholders[i] + '</span>' ) ;
+ }
+ }
+ }
+}
+else
+{
+ FCKPlaceholders.Redraw = function()
+ {
+ if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG )
+ return ;
+
+ var oInteractor = FCK.EditorDocument.createTreeWalker( FCK.EditorDocument.body, NodeFilter.SHOW_TEXT, FCKPlaceholders._AcceptNode, true ) ;
+
+ var aNodes = new Array() ;
+
+ while ( ( oNode = oInteractor.nextNode() ) )
+ {
+ aNodes[ aNodes.length ] = oNode ;
+ }
+
+ for ( var n = 0 ; n < aNodes.length ; n++ )
+ {
+ var aPieces = aNodes[n].nodeValue.split( /(\[\[[^\[\]]+\]\])/g ) ;
+
+ for ( var i = 0 ; i < aPieces.length ; i++ )
+ {
+ if ( aPieces[i].length > 0 )
+ {
+ if ( aPieces[i].indexOf( '[[' ) == 0 )
+ {
+ var sName = aPieces[i].match( /\[\[\s*([^\]]*?)\s*\]\]/ )[1] ;
+
+ var oSpan = FCK.EditorDocument.createElement( 'span' ) ;
+ FCKPlaceholders.SetupSpan( oSpan, sName ) ;
+
+ aNodes[n].parentNode.insertBefore( oSpan, aNodes[n] ) ;
+ }
+ else
+ aNodes[n].parentNode.insertBefore( FCK.EditorDocument.createTextNode( aPieces[i] ) , aNodes[n] ) ;
+ }
+ }
+
+ aNodes[n].parentNode.removeChild( aNodes[n] ) ;
+ }
+
+ FCKPlaceholders._SetupClickListener() ;
+ }
+
+ FCKPlaceholders._AcceptNode = function( node )
+ {
+ if ( /\[\[[^\[\]]+\]\]/.test( node.nodeValue ) )
+ return NodeFilter.FILTER_ACCEPT ;
+ else
+ return NodeFilter.FILTER_SKIP ;
+ }
+}
+
+FCK.Events.AttachEvent( 'OnAfterSetHTML', FCKPlaceholders.Redraw ) ;
+
+// We must process the SPAN tags to replace then with the real resulting value of the placeholder.
+FCKXHtml.TagProcessors['span'] = function( node, htmlNode )
+{
+ if ( htmlNode._fckplaceholder )
+ node = FCKXHtml.XML.createTextNode( '[[' + htmlNode._fckplaceholder + ']]' ) ;
+ else
+ FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
+
+ return node ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/de.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/de.js
new file mode 100644
index 000000000..a666f8b6a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/de.js
@@ -0,0 +1,27 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placholder German language file.
+ */
+FCKLang.PlaceholderBtn = 'Einfügen/editieren Platzhalter' ;
+FCKLang.PlaceholderDlgTitle = 'Platzhalter Eigenschaften' ;
+FCKLang.PlaceholderDlgName = 'Platzhalter Name' ;
+FCKLang.PlaceholderErrNoName = 'Bitte den Namen des Platzhalters schreiben' ;
+FCKLang.PlaceholderErrNameInUse = 'Der angegebene Namen ist schon in Gebrauch' ; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/en.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/en.js
new file mode 100644
index 000000000..290a3fb3c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/en.js
@@ -0,0 +1,27 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placholder English language file.
+ */
+FCKLang.PlaceholderBtn = 'Insert/Edit Placeholder' ;
+FCKLang.PlaceholderDlgTitle = 'Placeholder Properties' ;
+FCKLang.PlaceholderDlgName = 'Placeholder Name' ;
+FCKLang.PlaceholderErrNoName = 'Please type the placeholder name' ;
+FCKLang.PlaceholderErrNameInUse = 'The specified name is already in use' ; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/fr.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/fr.js
new file mode 100644
index 000000000..f5ac26eb2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/fr.js
@@ -0,0 +1,27 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placeholder French language file.
+ */
+FCKLang.PlaceholderBtn = "Insérer/Modifier l'Espace réservé" ;
+FCKLang.PlaceholderDlgTitle = "Propriétés de l'Espace réservé" ;
+FCKLang.PlaceholderDlgName = "Nom de l'Espace réservé" ;
+FCKLang.PlaceholderErrNoName = "Veuillez saisir le nom de l'Espace réservé" ;
+FCKLang.PlaceholderErrNameInUse = "Ce nom est déjà utilisé" ;
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/it.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/it.js
new file mode 100644
index 000000000..51d75c034
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/it.js
@@ -0,0 +1,27 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placholder Italian language file.
+ */
+FCKLang.PlaceholderBtn = 'Aggiungi/Modifica Placeholder' ;
+FCKLang.PlaceholderDlgTitle = 'Proprietà del Placeholder' ;
+FCKLang.PlaceholderDlgName = 'Nome del Placeholder' ;
+FCKLang.PlaceholderErrNoName = 'Digitare il nome del placeholder' ;
+FCKLang.PlaceholderErrNameInUse = 'Il nome inserito è già in uso' ;
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/pl.js b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/pl.js
new file mode 100644
index 000000000..bc55b3801
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/lang/pl.js
@@ -0,0 +1,27 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Placholder Polish language file.
+ */
+FCKLang.PlaceholderBtn = 'Wstaw/Edytuj nagłówek' ;
+FCKLang.PlaceholderDlgTitle = 'Właśności nagłówka' ;
+FCKLang.PlaceholderDlgName = 'Nazwa nagłówka' ;
+FCKLang.PlaceholderErrNoName = 'Proszę wprowadzić nazwę nagłówka' ;
+FCKLang.PlaceholderErrNameInUse = 'Podana nazwa jest już w użyciu' ; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/plugins/placeholder/placeholder.gif b/httemplate/elements/fckeditor/editor/plugins/placeholder/placeholder.gif
new file mode 100644
index 000000000..c07078c17
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/placeholder/placeholder.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/plugins/simplecommands/fckplugin.js b/httemplate/elements/fckeditor/editor/plugins/simplecommands/fckplugin.js
new file mode 100644
index 000000000..cd25b6a26
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/simplecommands/fckplugin.js
@@ -0,0 +1,29 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This plugin register Toolbar items for the combos modifying the style to
+ * not show the box.
+ */
+
+FCKToolbarItems.RegisterItem( 'SourceSimple' , new FCKToolbarButton( 'Source', FCKLang.Source, null, FCK_TOOLBARITEM_ONLYICON, true, true, 1 ) ) ;
+FCKToolbarItems.RegisterItem( 'StyleSimple' , new FCKToolbarStyleCombo( null, FCK_TOOLBARITEM_ONLYTEXT ) ) ;
+FCKToolbarItems.RegisterItem( 'FontNameSimple' , new FCKToolbarFontsCombo( null, FCK_TOOLBARITEM_ONLYTEXT ) ) ;
+FCKToolbarItems.RegisterItem( 'FontSizeSimple' , new FCKToolbarFontSizeCombo( null, FCK_TOOLBARITEM_ONLYTEXT ) ) ;
+FCKToolbarItems.RegisterItem( 'FontFormatSimple', new FCKToolbarFontFormatCombo( null, FCK_TOOLBARITEM_ONLYTEXT ) ) ;
diff --git a/httemplate/elements/fckeditor/editor/plugins/tablecommands/fckplugin.js b/httemplate/elements/fckeditor/editor/plugins/tablecommands/fckplugin.js
new file mode 100644
index 000000000..88dac9cdd
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/plugins/tablecommands/fckplugin.js
@@ -0,0 +1,32 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This plugin register the required Toolbar items to be able to insert the
+ * toolbar commands in the toolbar.
+ */
+
+FCKToolbarItems.RegisterItem( 'TableInsertRow' , new FCKToolbarButton( 'TableInsertRow' , FCKLang.InsertRow, null, null, null, null, 62 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableDeleteRows' , new FCKToolbarButton( 'TableDeleteRows' , FCKLang.DeleteRows, null, null, null, null, 63 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableInsertColumn' , new FCKToolbarButton( 'TableInsertColumn' , FCKLang.InsertColumn, null, null, null, null, 64 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableDeleteColumns' , new FCKToolbarButton( 'TableDeleteColumns', FCKLang.DeleteColumns, null, null, null, null, 65 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableInsertCell' , new FCKToolbarButton( 'TableInsertCell' , FCKLang.InsertCell, null, null, null, null, 58 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableDeleteCells' , new FCKToolbarButton( 'TableDeleteCells' , FCKLang.DeleteCells, null, null, null, null, 59 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableMergeCells' , new FCKToolbarButton( 'TableMergeCells' , FCKLang.MergeCells, null, null, null, null, 60 ) ) ;
+FCKToolbarItems.RegisterItem( 'TableSplitCell' , new FCKToolbarButton( 'TableSplitCell' , FCKLang.SplitCell, null, null, null, null, 61 ) ) ; \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/skins/_fckviewstrips.html b/httemplate/elements/fckeditor/editor/skins/_fckviewstrips.html
new file mode 100644
index 000000000..b28b941a7
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/_fckviewstrips.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Useful page that enumerates all icons in the skins strips.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>FCKeditor - View Icons Strips</title>
+ <style type="text/css">
+ .TB_Button_Image
+ {
+ overflow: hidden;
+ width: 16px;
+ height: 16px;
+ margin: 3px;
+ background-repeat: no-repeat;
+ }
+
+ .TB_Button_Image img
+ {
+ position: relative;
+ }
+ </style>
+ <script type="text/javascript">
+
+window.onload = function()
+{
+ var eImg1 = document.createElement( 'img' ) ;
+ eImg1.onload = Img_OnLoad ;
+ eImg1.src = 'default/fck_strip.gif' ;
+
+ var eImg2 = document.createElement( 'img' ) ;
+ eImg2.onload = Img_OnLoad ;
+ eImg2.src = 'office2003/fck_strip.gif' ;
+
+ var eImg3 = document.createElement( 'img' ) ;
+ eImg3.onload = Img_OnLoad ;
+ eImg3.src = 'silver/fck_strip.gif' ;
+}
+
+var iTotalStrips = 3 ;
+var iMaxHeight = 0 ;
+
+function Img_OnLoad()
+{
+ if ( iMaxHeight < this.height )
+ iMaxHeight = this.height ;
+
+ iTotalStrips-- ;
+
+ if ( iTotalStrips == 0 )
+ LoadIcons( iMaxHeight / 16 ) ;
+}
+
+function LoadIcons( total )
+{
+ var xIconsTable = document.getElementById( 'xIconsTable' ) ;
+
+ for ( var i = 0 ; i < total ; i++ )
+ {
+ var eRow = xIconsTable.insertRow(-1) ;
+
+ var eCell = eRow.insertCell(-1) ;
+ eCell.innerHTML = i + 1 ;
+
+ eCell = eRow.insertCell(-1) ;
+ eCell.align = 'center' ;
+ eCell.style.border = '#dcdcdc 1px solid' ;
+ eCell.innerHTML = '<div class="TB_Button_Image"><img src="default/fck_strip.gif" style="top:-' + ( i * 16 ) + 'px;"><\/div>' ;
+
+ eCell = eRow.insertCell(-1) ;
+ eCell.align = 'center' ;
+ eCell.style.border = '#dcdcdc 1px solid' ;
+ eCell.innerHTML = '<div class="TB_Button_Image"><img src="office2003/fck_strip.gif" style="top:-' + ( i * 16 ) + 'px;"><\/div>' ;
+
+ eCell = eRow.insertCell(-1) ;
+ eCell.align = 'center' ;
+ eCell.style.border = '#dcdcdc 1px solid' ;
+ eCell.innerHTML = '<div class="TB_Button_Image"><img src="silver/fck_strip.gif" style="top:-' + ( i * 16 ) + 'px;"><\/div>' ;
+ }
+}
+
+ </script>
+</head>
+<body>
+ <table id="xIconsTable">
+ <tr>
+ <td rowspan="2">
+ Index</td>
+ <td align="center" colspan="3">
+ Skins</td>
+ </tr>
+ <tr>
+ <td width="80" align="center">
+ default</td>
+ <td width="80" align="center">
+ office2003</td>
+ <td width="80" align="center">
+ silver</td>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/httemplate/elements/fckeditor/editor/skins/default/fck_dialog.css b/httemplate/elements/fckeditor/editor/skins/default/fck_dialog.css
new file mode 100644
index 000000000..9725f6ca3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/fck_dialog.css
@@ -0,0 +1,137 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the dialog boxes.
+ */
+
+body
+{
+ margin: 0px;
+ padding: 10px;
+}
+
+body, td, input, select, textarea
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana;
+}
+
+body, .BackColor
+{
+ background-color: #f1f1e3;
+}
+
+.PopupBody
+{
+ margin: 0px;
+ padding: 0px;
+}
+
+.PopupTitle
+{
+ font-weight: bold;
+ font-size: 14pt;
+ color: #737357;
+ background-color: #e3e3c7;
+ padding: 3px 10px 3px 10px;
+}
+
+.PopupButtons
+{
+ border-top: #d5d59d 1px solid;
+ background-color: #e3e3c7;
+ padding: 7px 10px 7px 10px;
+}
+
+.Button
+{
+ border: #737357 1px solid;
+ color: #3b3b1f;
+ background-color: #c7c78f;
+}
+
+#btnOk
+{
+ width: 100px;
+}
+
+.DarkBackground
+{
+ background-color: #d7d79f;
+}
+
+.LightBackground
+{
+ background-color: #ffffbe;
+}
+
+.PopupTitleBorder
+{
+ border-bottom: #d5d59d 1px solid;
+}
+
+.PopupTabArea
+{
+ color: #737357;
+ background-color: #e3e3c7;
+}
+
+.PopupTabEmptyArea
+{
+ padding-left: 10px ;
+ border-bottom: #d5d59d 1px solid;
+}
+
+.PopupTab, .PopupTabSelected
+{
+ border-right: #d5d59d 1px solid;
+ border-top: #d5d59d 1px solid;
+ border-left: #d5d59d 1px solid;
+ padding-right: 5px;
+ padding-left: 5px;
+ padding-bottom: 3px;
+ padding-top: 3px;
+ color: #737357;
+}
+
+.PopupTab
+{
+ margin-top: 1px;
+ border-bottom: #d5d59d 1px solid;
+ cursor: pointer;
+ cursor: hand;
+}
+
+.PopupTabSelected
+{
+ font-weight:bold;
+ cursor: default;
+ padding-top: 4px;
+ border-bottom: #f1f1e3 1px solid;
+ background-color: #f1f1e3;
+}
+
+.PopupSelectionBox
+{
+ border: #ff9933 1px solid !important;
+ background-color: #fffacd !important;
+ cursor: pointer;
+ cursor: hand;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/skins/default/fck_editor.css b/httemplate/elements/fckeditor/editor/skins/default/fck_editor.css
new file mode 100644
index 000000000..b849cca41
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/fck_editor.css
@@ -0,0 +1,464 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the editor IFRAME and Toolbar.
+ */
+
+/*
+ ### Basic Editor IFRAME Styles.
+*/
+
+body
+{
+ padding: 1px 1px 1px 1px;
+ margin: 0px 0px 0px 0px;
+}
+
+#xEditingArea
+{
+ border: #696969 1px solid;
+}
+
+.SourceField
+{
+ padding: 5px;
+ margin: 0px;
+ font-family: Monospace;
+}
+
+/*
+ Toolbar
+*/
+
+.TB_ToolbarSet, .TB_Expand, .TB_Collapse
+{
+ cursor: default;
+ background-color: #efefde;
+}
+
+.TB_ToolbarSet
+{
+ border-top: #efefde 1px outset;
+ border-bottom: #efefde 1px outset;
+}
+
+.TB_ToolbarSet TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.TB_Toolbar
+{
+ height: 24px;
+ display: inline-table; /* inline = Opera jumping buttons bug */
+}
+
+.TB_Separator
+{
+ width: 1px;
+ height: 16px;
+ margin: 2px;
+ background-color: #999966;
+}
+
+.TB_Start
+{
+ background-image: url(images/toolbar.start.gif);
+ margin: 2px;
+ width: 3px;
+ background-repeat: no-repeat;
+ height: 16px;
+}
+
+.TB_End
+{
+ display: none;
+}
+
+.TB_ExpandImg
+{
+ background-image: url(images/toolbar.expand.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_CollapseImg
+{
+ background-image: url(images/toolbar.collapse.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_SideBorder
+{
+ background-color: #696969;
+}
+
+.TB_Expand, .TB_Collapse
+{
+ padding: 2px 2px 2px 2px;
+ border: #efefde 1px outset;
+}
+
+.TB_Collapse
+{
+ width: 5px;
+}
+
+.TB_Break
+{
+ height: 24px; /* IE needs the height to be set, otherwise no break */
+}
+
+/*
+ Toolbar Button
+*/
+
+.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled
+{
+ border: #efefde 1px solid; /* This is the default border */
+ height: 22px; /* The height is necessary, otherwise IE will not apply the alpha */
+}
+
+.TB_Button_On
+{
+ border: #316ac5 1px solid;
+ background-color: #c1d2ee;
+}
+
+.TB_Button_On_Over, .TB_Button_Off_Over
+{
+ border: #316ac5 1px solid;
+ background-color: #dff1ff;
+}
+
+.TB_Button_Off
+{
+ filter: alpha(opacity=70); /* IE */
+ opacity: 0.70; /* Safari, Opera and Mozilla */
+}
+
+.TB_Button_Disabled
+{
+ filter: gray() alpha(opacity=30); /* IE */
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+}
+
+.TB_Button_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 22px;
+}
+
+.TB_Button_Image
+{
+ overflow: hidden;
+ width: 16px;
+ height: 16px;
+ margin: 3px;
+ background-repeat: no-repeat;
+}
+
+.TB_Button_Image img
+{
+ position: relative;
+}
+
+.TB_Button_Off .TB_Button_Text
+{
+ background-color: #efefde; /* Needed because of a bug on Clear Type */
+}
+
+.TB_ConnectionLine
+{
+ background-color: #ffffff;
+ height: 1px;
+ margin-left: 1px; /* ltr */
+ margin-right: 1px; /* rtl */
+}
+
+.TB_Text
+{
+ height: 22px;
+}
+
+.TB_Button_Off .TB_Text
+{
+ background-color: #efefde ; /* Needed because of a bug on ClearType */
+}
+
+.TB_Button_On_Over .TB_Text
+{
+ background-color: #dff1ff ; /* Needed because of a bug on ClearType */
+}
+
+/*
+ Menu
+*/
+
+.MN_Menu
+{
+ border: 1px solid #8f8f73;
+ padding: 2px;
+ background-color: #ffffff;
+ cursor: default;
+}
+
+.MN_Menu, .MN_Menu .MN_Label
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.MN_Item_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 20px;
+}
+
+.MN_Icon
+{
+ background-color: #e3e3c7;
+ text-align: center;
+ height: 20px;
+}
+
+.MN_Label
+{
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+.MN_Separator
+{
+ height: 3px;
+}
+
+.MN_Separator_Line
+{
+ border-top: #b9b99d 1px solid;
+}
+
+.MN_Item .MN_Icon IMG
+{
+ filter: alpha(opacity=70);
+ opacity: 0.70;
+}
+
+.MN_Item_Over
+{
+ color: #ffffff;
+ background-color: #8f8f73;
+}
+
+.MN_Item_Over .MN_Icon
+{
+ background-color: #737357;
+}
+
+.MN_Item_Disabled IMG
+{
+ filter: gray() alpha(opacity=30); /* IE */
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+}
+
+.MN_Item_Disabled .MN_Label
+{
+ color: #b7b7b7;
+}
+
+.MN_Arrow
+{
+ padding-right: 3px;
+ padding-left: 3px;
+}
+
+.MN_ConnectionLine
+{
+ background-color: #ffffff;
+}
+
+.Menu .TB_Button_On, .Menu .TB_Button_On_Over
+{
+ border: #8f8f73 1px solid;
+ background-color: #ffffff;
+}
+
+/*
+ ### Panel Styles
+*/
+
+.FCK_Panel
+{
+ border: #8f8f73 1px solid;
+ padding: 2px;
+ background-color: #ffffff;
+}
+
+.FCK_Panel, .FCK_Panel TD
+{
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+ font-size: 11px;
+}
+
+/*
+ ### Special Combos
+*/
+
+.SC_Panel
+{
+ overflow: auto;
+ white-space: nowrap;
+ cursor: default;
+ border: 1px solid #8f8f73;
+ padding-left: 2px;
+ padding-right: 2px;
+ background-color: #ffffff;
+}
+
+.SC_Panel, .SC_Panel TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.SC_Item, .SC_ItemSelected
+{
+ margin-top: 2px;
+ margin-bottom: 2px;
+ background-position: left center;
+ padding-left: 11px;
+ padding-right: 3px;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ background-repeat: no-repeat;
+ border: #dddddd 1px solid;
+}
+
+.SC_Item *, .SC_ItemSelected *
+{
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.SC_ItemSelected
+{
+ border: #9a9afb 1px solid;
+ background-image: url(images/toolbar.arrowright.gif);
+}
+
+.SC_ItemOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_Field
+{
+ border: #b7b7a6 1px solid;
+ cursor: default;
+}
+
+.SC_FieldCaption
+{
+ overflow: visible;
+ padding-right: 5px;
+ padding-left: 5px;
+ opacity: 0.75; /* Safari, Opera and Mozilla */
+ filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */
+ height: 23px;
+ background-color: #efefde;
+}
+
+.SC_FieldLabel
+{
+ white-space: nowrap;
+ padding: 2px;
+ width: 100%;
+ cursor: default;
+ background-color: #ffffff;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.SC_FieldButton
+{
+ background-position: center center;
+ background-image: url(images/toolbar.buttonarrow.gif);
+ border-left: #b7b7a6 1px solid;
+ width: 14px;
+ background-repeat: no-repeat;
+}
+
+.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption
+{
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+ filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */
+}
+
+.SC_FieldOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_FieldOver .SC_FieldButton
+{
+ border-left: #316ac5 1px solid;
+}
+
+/*
+ ### Color Selector Panel
+*/
+
+.ColorBoxBorder
+{
+ border: #808080 1px solid;
+ position: static;
+}
+
+.ColorBox
+{
+ font-size: 1px;
+ width: 10px;
+ position: static;
+ height: 10px;
+}
+
+.ColorDeselected, .ColorSelected
+{
+ cursor: default;
+}
+
+.ColorDeselected
+{
+ border: #ffffff 1px solid;
+ padding: 2px;
+ float: left;
+}
+
+.ColorSelected
+{
+ border: #330066 1px solid;
+ padding: 2px;
+ float: left;
+ background-color: #c4cdd6;
+}
diff --git a/httemplate/elements/fckeditor/editor/skins/default/fck_strip.gif b/httemplate/elements/fckeditor/editor/skins/default/fck_strip.gif
new file mode 100644
index 000000000..d5ba74e8d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/fck_strip.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.arrowright.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.arrowright.gif
new file mode 100644
index 000000000..6843c8d41
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.arrowright.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif
new file mode 100644
index 000000000..ea60995e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.collapse.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.collapse.gif
new file mode 100644
index 000000000..87aa56d3b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.collapse.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.end.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.end.gif
new file mode 100644
index 000000000..5bfd67a2d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.end.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.expand.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.expand.gif
new file mode 100644
index 000000000..79075e7c3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.expand.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.separator.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.separator.gif
new file mode 100644
index 000000000..eaed04a7a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.separator.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.start.gif b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.start.gif
new file mode 100644
index 000000000..1774246c2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/default/images/toolbar.start.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/fck_dialog.css b/httemplate/elements/fckeditor/editor/skins/office2003/fck_dialog.css
new file mode 100644
index 000000000..54a958b1c
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/fck_dialog.css
@@ -0,0 +1,138 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the dialog boxes.
+ */
+
+body
+{
+ margin: 0px;
+ padding: 10px;
+ background-color: #f7f8fd;
+}
+
+body, td, input, select, textarea
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana;
+}
+
+body, .BackColor
+{
+ background-color: #f7f8fd;
+}
+
+.PopupBody
+{
+ margin: 0px;
+ padding: 0px;
+}
+
+.PopupTitle
+{
+ font-weight: bold;
+ font-size: 14pt;
+ color: #0e3460;
+ background-color: #8cb2fd;
+ padding: 3px 10px 3px 10px;
+}
+
+.PopupButtons
+{
+ border-top: #466ca6 1px solid;
+ background-color: #8cb2fd;
+ padding: 7px 10px 7px 10px;
+}
+
+.Button
+{
+ border: #1c3460 1px solid;
+ color: #000a28;
+ background-color: #7096d3;
+}
+
+#btnOk
+{
+ width: 100px;
+}
+
+.DarkBackground
+{
+ background-color: #d7d79f;
+}
+
+.LightBackground
+{
+ background-color: #ffffbe;
+}
+
+.PopupTitleBorder
+{
+ border-bottom: #d5d59d 1px solid;
+}
+
+.PopupTabArea
+{
+ color: #0e3460;
+ background-color: #8cb2fd;
+}
+
+.PopupTabEmptyArea
+{
+ padding-left: 10px ;
+ border-bottom: #466ca6 1px solid;
+}
+
+.PopupTab, .PopupTabSelected
+{
+ border-right: #466ca6 1px solid;
+ border-top: #466ca6 1px solid;
+ border-left: #466ca6 1px solid;
+ padding-right: 5px;
+ padding-left: 5px;
+ padding-bottom: 3px;
+ padding-top: 3px;
+ color: #0e3460;
+}
+
+.PopupTab
+{
+ margin-top: 1px;
+ border-bottom: #466ca6 1px solid;
+ cursor: pointer;
+ cursor: hand;
+}
+
+.PopupTabSelected
+{
+ font-weight:bold;
+ cursor: default;
+ padding-top: 4px;
+ border-bottom: #f7f8fd 1px solid;
+ background-color: #f7f8fd;
+}
+
+.PopupSelectionBox
+{
+ border: #1e90ff 1px solid !important;
+ background-color: #add8e6 !important;
+ cursor: pointer;
+ cursor: hand;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/fck_editor.css b/httemplate/elements/fckeditor/editor/skins/office2003/fck_editor.css
new file mode 100644
index 000000000..f68c06f59
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/fck_editor.css
@@ -0,0 +1,476 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the editor IFRAME and Toolbar.
+ */
+
+/*
+ ### Basic Editor IFRAME Styles.
+*/
+
+body
+{
+ padding: 1px 1px 1px 1px;
+ margin: 0px 0px 0px 0px;
+}
+
+#xEditingArea
+{
+ border: #696969 1px solid;
+}
+
+.SourceField
+{
+ padding: 5px;
+ margin: 0px;
+ font-family: Monospace;
+}
+
+/*
+ Toolbar
+*/
+
+.TB_ToolbarSet, .TB_Expand, .TB_Collapse
+{
+ cursor: default;
+ background-color: #f7f8fd;
+}
+
+.TB_ToolbarSet
+{
+ border-top: #f7f8fd 1px outset;
+ border-bottom: #f7f8fd 1px outset;
+}
+
+.TB_ToolbarSet TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.TB_Toolbar
+{
+ background-color: #d6dff7;
+ background-image: url(images/toolbar.bg.gif);
+ background-repeat: repeat-x;
+ display: inline-table;
+}
+
+.TB_Separator
+{
+ width: 1px;
+ height: 16px;
+ margin: 2px;
+ background-color: #B2CBFF;
+}
+
+.TB_Start
+{
+ background-image: url(images/toolbar.start.gif);
+ background-repeat: no-repeat;
+ background-position: center center;
+ margin: 0px;
+ width: 7px;
+ height: 24px;
+}
+
+.TB_End
+{
+ background-image: url(images/toolbar.end.gif);
+ background-repeat: no-repeat;
+ background-position: center left;
+ height: 24px;
+ width: 4px;
+}
+
+.TB_ExpandImg
+{
+ background-image: url(images/toolbar.expand.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_CollapseImg
+{
+ background-image: url(images/toolbar.collapse.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_SideBorder
+{
+ background-color: #696969;
+}
+
+.TB_Expand, .TB_Collapse
+{
+ padding: 2px 2px 2px 2px;
+ border: #f7f8fd 1px outset;
+}
+
+.TB_Collapse
+{
+ width: 5px;
+}
+
+.TB_Break
+{
+ height: 24px; /* IE needs the height to be set, otherwise no break */
+}
+
+/*
+ Toolbar Button
+*/
+
+.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled
+{
+ margin: 1px;
+ height: 22px; /* The height is necessary, otherwise IE will not apply the alpha */
+}
+
+.TB_Button_On
+{
+ margin: 0px;
+ border: #316ac5 1px solid;
+ background-color: #c1d2ee;
+}
+
+.TB_Button_On_Over, .TB_Button_Off_Over
+{
+ margin: 0px ;
+ border: #316ac5 1px solid;
+ background-color: #dff1ff;
+}
+
+.TB_Button_Off
+{
+ filter: alpha(opacity=70); /* IE */
+ opacity: 0.70; /* Safari, Opera and Mozilla */
+}
+
+.TB_Button_Disabled
+{
+ filter: gray() alpha(opacity=30); /* IE */
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+}
+
+.TB_Button_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 22px;
+}
+
+.TB_Button_Image
+{
+ overflow: hidden;
+ width: 16px;
+ height: 16px;
+ margin: 3px;
+ background-repeat: no-repeat;
+}
+
+.TB_Button_Image img
+{
+ position: relative;
+}
+
+.TB_Button_Off .TB_Button_Text
+{
+ background-color: #d6dff7; /* Needed because of a bug on ClearType */
+ background-image: url(images/toolbar.bg.gif);
+ background-repeat: repeat-x;
+}
+
+.TB_ConnectionLine
+{
+ background-color: #f7f8fd;
+ height: 1px;
+ margin-left: 1px; /* ltr */
+ margin-right: 1px; /* rtl */
+}
+
+.TB_Button_Off .TB_Text
+{
+ background-color: #d6dff7; /* Needed because of a bug on ClearType */
+ background-image: url(images/toolbar.bg.gif);
+ background-repeat: repeat-x;
+}
+
+.TB_Button_On_Over .TB_Text
+{
+ background-color: #dff1ff ; /* Needed because of a bug on ClearType */
+}
+
+/*
+ Menu
+*/
+
+.MN_Menu
+{
+ border: 1px solid #8f8f73;
+ padding: 2px;
+ background-color: #f7f8fd;
+ cursor: default;
+}
+
+.MN_Menu, .MN_Menu .MN_Label
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.MN_Item_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 20px;
+}
+
+.MN_Icon
+{
+ background-color: #d6dff7;
+ text-align: center;
+ height: 20px;
+}
+
+.MN_Label
+{
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+.MN_Separator
+{
+ height: 3px;
+}
+
+.MN_Separator_Line
+{
+ border-top: #b9b99d 1px solid;
+}
+
+.MN_Item .MN_Icon IMG
+{
+ filter: alpha(opacity=70);
+ opacity: 0.70;
+}
+
+.MN_Item_Over
+{
+ color: #ffffff;
+ background-color: #7096FA;
+}
+
+.MN_Item_Over .MN_Icon
+{
+ background-color: #466ca6;
+}
+
+.MN_Item_Disabled IMG
+{
+ filter: gray() alpha(opacity=30); /* IE */
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+}
+
+.MN_Item_Disabled .MN_Label
+{
+ color: #b7b7b7;
+}
+
+.MN_Arrow
+{
+ padding-right: 3px;
+ padding-left: 3px;
+}
+
+.MN_ConnectionLine
+{
+ background-color: #f7f8fd;
+}
+
+.Menu .TB_Button_On, .Menu .TB_Button_On_Over
+{
+ border: #8f8f73 1px solid;
+ background-color: #f7f8fd;
+}
+
+/*
+ ### Panel Styles
+*/
+
+.FCK_Panel
+{
+ border: #8f8f73 1px solid;
+ padding: 2px;
+ background-color: #f7f8fd;
+}
+
+.FCK_Panel, .FCK_Panel TD
+{
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+ font-size: 11px;
+}
+
+/*
+ ### Special Combos
+*/
+
+.SC_Panel
+{
+ overflow: auto;
+ white-space: nowrap;
+ cursor: default;
+ border: 1px solid #8f8f73;
+ padding-left: 2px;
+ padding-right: 2px;
+ background-color: #ffffff;
+}
+
+.SC_Panel, .SC_Panel TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.SC_Item, .SC_ItemSelected
+{
+ margin-top: 2px;
+ margin-bottom: 2px;
+ background-position: left center;
+ padding-left: 11px;
+ padding-right: 3px;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ background-repeat: no-repeat;
+ border: #dddddd 1px solid;
+}
+
+.SC_Item *, .SC_ItemSelected *
+{
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.SC_ItemSelected
+{
+ border: #9a9afb 1px solid;
+ background-image: url(images/toolbar.arrowright.gif);
+}
+
+.SC_ItemOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_Field
+{
+ margin-top: 2px ;
+ border: #b7b7a6 1px solid;
+ cursor: default;
+}
+
+.SC_FieldCaption
+{
+ overflow: visible;
+ padding-right: 5px;
+ padding-left: 5px;
+ opacity: 0.75; /* Safari, Opera and Mozilla */
+ filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */
+ height: 23px;
+ background-color: #d6dff7; /* Needed because of a bug on ClearType */
+ background-image: url(images/toolbar.bg.gif);
+ background-repeat: repeat-x;
+/* background-color: inherit; Maybe this is needed wait to check */
+}
+
+.SC_FieldLabel
+{
+ white-space: nowrap;
+ padding: 2px;
+ width: 100%;
+ cursor: default;
+ background-color: #ffffff;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.SC_FieldButton
+{
+ background-position: center center;
+ background-image: url(images/toolbar.buttonarrow.gif);
+ border-left: #b7b7a6 1px solid;
+ width: 14px;
+ background-repeat: no-repeat;
+}
+
+.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption
+{
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+ filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */
+}
+
+.SC_FieldOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_FieldOver .SC_FieldButton
+{
+ border-left: #316ac5 1px solid;
+}
+
+/*
+ ### Color Selector Panel
+*/
+
+.ColorBoxBorder
+{
+ border: #808080 1px solid;
+ position: static;
+}
+
+.ColorBox
+{
+ font-size: 1px;
+ width: 10px;
+ position: static;
+ height: 10px;
+}
+
+.ColorDeselected, .ColorSelected
+{
+ cursor: default;
+}
+
+.ColorDeselected
+{
+ border: #ffffff 1px solid;
+ padding: 2px;
+ float: left;
+}
+
+.ColorSelected
+{
+ border: #330066 1px solid;
+ padding: 2px;
+ float: left;
+ background-color: #c4cdd6;
+}
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/fck_strip.gif b/httemplate/elements/fckeditor/editor/skins/office2003/fck_strip.gif
new file mode 100644
index 000000000..a7282f202
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/fck_strip.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif
new file mode 100644
index 000000000..6843c8d41
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.bg.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.bg.gif
new file mode 100644
index 000000000..b03960b1b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.bg.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif
new file mode 100644
index 000000000..ea60995e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif
new file mode 100644
index 000000000..d549166d1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.end.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.end.gif
new file mode 100644
index 000000000..7ff599dee
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.end.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.expand.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.expand.gif
new file mode 100644
index 000000000..c4a7326e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.expand.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.separator.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.separator.gif
new file mode 100644
index 000000000..27db9c38d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.separator.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.start.gif b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.start.gif
new file mode 100644
index 000000000..41f1241b9
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/office2003/images/toolbar.start.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/fck_dialog.css b/httemplate/elements/fckeditor/editor/skins/silver/fck_dialog.css
new file mode 100644
index 000000000..e05c1735e
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/fck_dialog.css
@@ -0,0 +1,141 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the dialog boxes.
+ */
+
+body
+{
+ margin: 0px;
+ padding: 10px;
+ background-color: #f7f7f7;
+}
+
+body, td, input, select, textarea
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Arial, Helvetica, Verdana;
+}
+
+body, .BackColor
+{
+ background-color: #f7f7f7;
+}
+
+.PopupBody
+{
+ margin: 0px;
+ padding: 0px;
+}
+
+.PopupTitle
+{
+ padding-right: 10px;
+ padding-left: 10px;
+ font-weight: bold;
+ font-size: 14pt;
+ padding-bottom: 3px;
+ color: #504845;
+ padding-top: 3px;
+ background-color: #dedede;
+}
+
+.PopupButtons
+{
+ border-top: #cec6b5 1px solid;
+ background-color: #DEDEDE;
+ padding: 7px 10px 7px 10px;
+}
+
+.Button
+{
+ border: #7a7261 1px solid;
+ color: #504845;
+ background-color: #cec6b5;
+}
+
+#btnOk
+{
+ width: 100px;
+}
+
+.DarkBackground
+{
+ background-color: #d7d79f;
+}
+
+.LightBackground
+{
+ background-color: #ffffbe;
+}
+
+.PopupTitleBorder
+{
+ border-bottom: #cec6b5 1px solid;
+}
+
+.PopupTabArea
+{
+ color: #504845;
+ background-color: #DEDEDE;
+}
+
+.PopupTabEmptyArea
+{
+ padding-left: 10px ;
+ border-bottom: #cec6b5 1px solid;
+}
+
+.PopupTab, .PopupTabSelected
+{
+ border-right: #cec6b5 1px solid;
+ border-top: #cec6b5 1px solid;
+ border-left: #cec6b5 1px solid;
+ padding-right: 5px;
+ padding-left: 5px;
+ padding-bottom: 3px;
+ padding-top: 3px;
+ color: #504845;
+}
+
+.PopupTab
+{
+ margin-top: 1px;
+ border-bottom: #cec6b5 1px solid;
+ cursor: pointer;
+ cursor: hand;
+}
+
+.PopupTabSelected
+{
+ font-weight:bold;
+ cursor: default;
+ padding-top: 4px;
+ border-bottom: #f1f1e3 1px solid;
+ background-color: #f7f7f7;
+}
+
+.PopupSelectionBox
+{
+ border: #a9a9a9 1px solid !important;
+ background-color: #dcdcdc !important;
+ cursor: pointer;
+ cursor: hand;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/fck_editor.css b/httemplate/elements/fckeditor/editor/skins/silver/fck_editor.css
new file mode 100644
index 000000000..656dcdb90
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/fck_editor.css
@@ -0,0 +1,473 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Styles used by the editor IFRAME and Toolbar.
+ */
+
+/*
+ ### Basic Editor IFRAME Styles.
+*/
+
+body
+{
+ padding: 1px 1px 1px 1px;
+ margin: 0px 0px 0px 0px;
+}
+
+#xEditingArea
+{
+ border: #696969 1px solid;
+}
+
+.SourceField
+{
+ padding: 5px;
+ margin: 0px;
+ font-family: Monospace;
+}
+
+/*
+ Toolbar
+*/
+
+.TB_ToolbarSet, .TB_Expand, .TB_Collapse
+{
+ cursor: default;
+ background-color: #f7f7f7;
+}
+
+.TB_ToolbarSet
+{
+ padding: 1px;
+ border-top: #efefde 1px outset;
+ border-bottom: #efefde 1px outset;
+}
+
+.TB_ToolbarSet TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.TB_Toolbar
+{
+ display: inline-table;
+}
+
+.TB_Separator
+{
+ width: 1px;
+ height: 21px;
+ margin: 2px;
+ background-color: #C6C3BD;
+}
+
+.TB_Start
+{
+ background-image: url(images/toolbar.start.gif);
+ margin-left: 2px;
+ margin-right: 2px;
+ width: 3px;
+ background-repeat: no-repeat;
+ height: 27px;
+ background-position: center center;
+}
+
+.TB_End
+{
+ display: none;
+}
+
+.TB_ExpandImg
+{
+ background-image: url(images/toolbar.expand.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_CollapseImg
+{
+ background-image: url(images/toolbar.collapse.gif);
+ background-repeat: no-repeat;
+}
+
+.TB_SideBorder
+{
+ background-color: #696969;
+}
+
+.TB_Expand, .TB_Collapse
+{
+ padding: 2px 2px 2px 2px;
+ border: #efefde 1px outset;
+}
+
+.TB_Collapse
+{
+ border: #efefde 1px outset;
+ width: 5px;
+}
+
+.TB_Break
+{
+ height: 27px;
+}
+
+/*
+ Toolbar Button
+*/
+
+.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled
+{
+ padding: 1px ;
+ margin:1px;
+ height: 21px;
+}
+
+.TB_Button_On, .TB_Button_Off, .TB_Button_On_Over, .TB_Button_Off_Over, .TB_Button_Disabled
+{
+ border: #cec6b5 1px solid;
+}
+
+.TB_Button_On
+{
+ border-color: #316ac5;
+ background-color: #c1d2ee;
+}
+
+.TB_Button_On_Over, .TB_Button_Off_Over
+{
+ border: #316ac5 1px solid;
+ background-color: #dff1ff;
+}
+
+.TB_Button_Off
+{
+ background: #efefef url(images/toolbar.buttonbg.gif) repeat-x;
+}
+
+.TB_Button_Off, .TB_Combo_Off
+{
+ opacity: 0.70; /* Safari, Opera and Mozilla */
+ filter: alpha(opacity=70); /* IE */
+ /* -moz-opacity: 0.70; Mozilla (Old) */
+}
+
+.TB_Button_Disabled
+{
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+ filter: gray() alpha(opacity=30); /* IE */
+}
+
+.TB_Button_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 21px;
+}
+
+.TB_Button_Image
+{
+ overflow: hidden;
+ width: 16px;
+ height: 16px;
+ margin: 3px;
+ margin-top: 4px;
+ margin-bottom: 2px;
+ background-repeat: no-repeat;
+}
+
+/* For composed button ( icon + text, icon + arrow ), we must compensate the table */
+.TB_Button_On TABLE .TB_Button_Image,
+.TB_Button_Off TABLE .TB_Button_Image,
+.TB_Button_On_Over TABLE .TB_Button_Image,
+.TB_Button_Off_Over TABLE .TB_Button_Image,
+.TB_Button_Disabled TABLE .TB_Button_Image
+{
+ margin-top: 3px;
+}
+
+.TB_Button_Image img
+{
+ position: relative;
+}
+
+.TB_ConnectionLine
+{
+ background-color: #ffffff;
+ height: 1px;
+ margin-left: 1px; /* ltr */
+ margin-right: 1px; /* rtl */
+}
+
+/*
+ Menu
+*/
+
+.MN_Menu
+{
+ border: 1px solid #8f8f73;
+ padding: 2px;
+ background-color: #f7f7f7;
+ cursor: default;
+}
+
+.MN_Menu, .MN_Menu .MN_Label
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.MN_Item_Padding
+{
+ visibility: hidden;
+ width: 3px;
+ height: 20px;
+}
+
+.MN_Icon
+{
+ background-color: #dedede;
+ text-align: center;
+ height: 20px;
+}
+
+.MN_Label
+{
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+.MN_Separator
+{
+ height: 3px;
+}
+
+.MN_Separator_Line
+{
+ border-top: #b9b99d 1px solid;
+}
+
+.MN_Item .MN_Icon IMG
+{
+ filter: alpha(opacity=70);
+ opacity: 0.70;
+}
+
+.MN_Item_Over
+{
+ color: #ffffff;
+ background-color: #8a857d;
+}
+
+.MN_Item_Over .MN_Icon
+{
+ background-color: #6c6761;
+}
+
+.MN_Item_Disabled IMG
+{
+ filter: gray() alpha(opacity=30); /* IE */
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+}
+
+.MN_Item_Disabled .MN_Label
+{
+ color: #b7b7b7;
+}
+
+.MN_Arrow
+{
+ padding-right: 3px;
+ padding-left: 3px;
+}
+
+.MN_ConnectionLine
+{
+ background-color: #ffffff;
+}
+
+.Menu .TB_Button_On, .Menu .TB_Button_On_Over
+{
+ border: #8f8f73 1px solid;
+ background-color: #ffffff;
+}
+
+/*
+ ### Panel Styles
+*/
+
+.FCK_Panel
+{
+ border: #8f8f73 1px solid;
+ padding: 2px;
+ background-color: #ffffff;
+}
+
+.FCK_Panel, .FCK_Panel TD
+{
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+ font-size: 11px;
+}
+
+/*
+ ### Special Combos
+*/
+
+.SC_Panel
+{
+ overflow: auto;
+ white-space: nowrap;
+ cursor: default;
+ border: 1px solid #8f8f73;
+ padding-left: 2px;
+ padding-right: 2px;
+ background-color: #ffffff;
+}
+
+.SC_Panel, .SC_Panel TD
+{
+ font-size: 11px;
+ font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif;
+}
+
+.SC_Item, .SC_ItemSelected
+{
+ margin-top: 2px;
+ margin-bottom: 2px;
+ background-position: left center;
+ padding-left: 11px;
+ padding-right: 3px;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ background-repeat: no-repeat;
+ border: #dddddd 1px solid;
+}
+
+.SC_Item *, .SC_ItemSelected *
+{
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.SC_ItemSelected
+{
+ border: #9a9afb 1px solid;
+ background-image: url(images/toolbar.arrowright.gif);
+}
+
+.SC_ItemOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_Field
+{
+ margin-top:1px ;
+ border: #b7b7a6 1px solid;
+ cursor: default;
+}
+
+.SC_FieldCaption
+{
+ padding-top: 1px ;
+ overflow: visible;
+ padding-right: 5px;
+ padding-left: 5px;
+ opacity: 0.75; /* Safari, Opera and Mozilla */
+ filter: alpha(opacity=70); /* IE */ /* -moz-opacity: 0.75; Mozilla (Old) */
+ height: 23px;
+ background-color: #f7f7f7;
+}
+
+.SC_FieldLabel
+{
+ white-space: nowrap;
+ padding: 2px;
+ width: 100%;
+ cursor: default;
+ background-color: #ffffff;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.SC_FieldButton
+{
+ background-position: center center;
+ background-image: url(images/toolbar.buttonarrow.gif);
+ border-left: #b7b7a6 1px solid;
+ width: 14px;
+ background-repeat: no-repeat;
+}
+
+.SC_FieldDisabled .SC_FieldButton, .SC_FieldDisabled .SC_FieldCaption
+{
+ opacity: 0.30; /* Safari, Opera and Mozilla */
+ filter: gray() alpha(opacity=30); /* IE */ /* -moz-opacity: 0.30; Mozilla (Old) */
+}
+
+.SC_FieldOver
+{
+ border: #316ac5 1px solid;
+}
+
+.SC_FieldOver .SC_FieldButton
+{
+ border-left: #316ac5 1px solid;
+}
+
+/*
+ ### Color Selector Panel
+*/
+
+.ColorBoxBorder
+{
+ border: #808080 1px solid;
+ position: static;
+}
+
+.ColorBox
+{
+ font-size: 1px;
+ width: 10px;
+ position: static;
+ height: 10px;
+}
+
+.ColorDeselected, .ColorSelected
+{
+ cursor: default;
+}
+
+.ColorDeselected
+{
+ border: #ffffff 1px solid;
+ padding: 2px;
+ float: left;
+}
+
+.ColorSelected
+{
+ border: #316ac5 1px solid;
+ padding: 2px;
+ float: left;
+ background-color: #c1d2ee;
+}
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/fck_strip.gif b/httemplate/elements/fckeditor/editor/skins/silver/fck_strip.gif
new file mode 100644
index 000000000..d5ba74e8d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/fck_strip.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif
new file mode 100644
index 000000000..6843c8d41
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif
new file mode 100644
index 000000000..ea60995e1
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif
new file mode 100644
index 000000000..a93ffcaa3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.collapse.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.collapse.gif
new file mode 100644
index 000000000..87aa56d3b
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.collapse.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.end.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.end.gif
new file mode 100644
index 000000000..5bfd67a2d
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.end.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.expand.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.expand.gif
new file mode 100644
index 000000000..79075e7c3
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.expand.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.separator.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.separator.gif
new file mode 100644
index 000000000..eaed04a7a
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.separator.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.start.gif b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.start.gif
new file mode 100644
index 000000000..1774246c2
--- /dev/null
+++ b/httemplate/elements/fckeditor/editor/skins/silver/images/toolbar.start.gif
Binary files differ
diff --git a/httemplate/elements/fckeditor/fckconfig.js b/httemplate/elements/fckeditor/fckconfig.js
new file mode 100644
index 000000000..215bc0a74
--- /dev/null
+++ b/httemplate/elements/fckeditor/fckconfig.js
@@ -0,0 +1,245 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Editor configuration settings.
+ *
+ * Follow this link for more information:
+ * http://wiki.fckeditor.net/Developer%27s_Guide/Configuration/Configurations_Settings
+ */
+
+// Disable the custom Enter Key Handler. This option will be removed in version 2.5.
+FCKConfig.DisableEnterKeyHandler = false ;
+
+FCKConfig.CustomConfigurationsPath = '' ;
+
+FCKConfig.EditorAreaCSS = FCKConfig.BasePath + 'css/fck_editorarea.css' ;
+FCKConfig.ToolbarComboPreviewCSS = '' ;
+
+FCKConfig.DocType = '' ;
+
+FCKConfig.BaseHref = '' ;
+
+FCKConfig.FullPage = false ;
+
+FCKConfig.Debug = false ;
+FCKConfig.AllowQueryStringDebug = true ;
+
+FCKConfig.SkinPath = FCKConfig.BasePath + 'skins/default/' ;
+//FCKConfig.SkinPath = FCKConfig.BasePath + 'editor/skins/silver/' ;
+FCKConfig.PreloadImages = [ FCKConfig.SkinPath + 'images/toolbar.start.gif', FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif' ] ;
+
+FCKConfig.PluginsPath = FCKConfig.BasePath + 'plugins/' ;
+
+// FCKConfig.Plugins.Add( 'autogrow' ) ;
+FCKConfig.AutoGrowMax = 400 ;
+
+// FCKConfig.ProtectedSource.Add( /<%[\s\S]*?%>/g ) ; // ASP style server side code <%...%>
+// FCKConfig.ProtectedSource.Add( /<\?[\s\S]*?\?>/g ) ; // PHP style server side code
+// FCKConfig.ProtectedSource.Add( /(<asp:[^\>]+>[\s|\S]*?<\/asp:[^\>]+>)|(<asp:[^\>]+\/>)/gi ) ; // ASP.Net style tags <asp:control>
+
+FCKConfig.AutoDetectLanguage = true ;
+FCKConfig.DefaultLanguage = 'en' ;
+FCKConfig.ContentLangDirection = 'ltr' ;
+
+FCKConfig.ProcessHTMLEntities = true ;
+FCKConfig.IncludeLatinEntities = true ;
+FCKConfig.IncludeGreekEntities = true ;
+
+FCKConfig.ProcessNumericEntities = false ;
+
+FCKConfig.AdditionalNumericEntities = '' ; // Single Quote: "'"
+
+FCKConfig.FillEmptyBlocks = true ;
+
+FCKConfig.FormatSource = true ;
+FCKConfig.FormatOutput = true ;
+FCKConfig.FormatIndentator = ' ' ;
+
+FCKConfig.ForceStrongEm = true ;
+FCKConfig.GeckoUseSPAN = false ;
+FCKConfig.StartupFocus = false ;
+FCKConfig.ForcePasteAsPlainText = false ;
+FCKConfig.AutoDetectPasteFromWord = true ; // IE only.
+FCKConfig.ForceSimpleAmpersand = false ;
+FCKConfig.TabSpaces = 0 ;
+FCKConfig.ShowBorders = true ;
+FCKConfig.SourcePopup = false ;
+FCKConfig.ToolbarStartExpanded = true ;
+FCKConfig.ToolbarCanCollapse = true ;
+FCKConfig.IgnoreEmptyParagraphValue = true ;
+FCKConfig.PreserveSessionOnFileBrowser = false ;
+FCKConfig.FloatingPanelsZIndex = 10000 ;
+
+FCKConfig.TemplateReplaceAll = true ;
+FCKConfig.TemplateReplaceCheckbox = true ;
+
+FCKConfig.ToolbarLocation = 'In' ;
+
+//FCKConfig.ToolbarSets["Default"] = [
+// ['Source','DocProps','-','Save','NewPage','Preview','-','Templates'],
+// ['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'],
+// ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
+// ['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'],
+// '/',
+// ['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
+// ['OrderedList','UnorderedList','-','Outdent','Indent'],
+// ['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
+// ['Link','Unlink','Anchor'],
+// ['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak'],
+// '/',
+// ['Style','FontFormat','FontName','FontSize'],
+// ['TextColor','BGColor'],
+// ['FitWindow','-','About']
+//] ;
+FCKConfig.ToolbarSets["Default"] = [
+ ['Source','DocProps','-','Save','Preview','-'],
+ ['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'],
+ ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
+ //['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'],
+ '/',
+ ['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
+ ['OrderedList','UnorderedList','-','Outdent','Indent'],
+ ['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
+ ['Link','Unlink','Anchor'],
+ ['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak'],
+ '/',
+ ['Style','FontFormat','FontName','FontSize'],
+ ['TextColor','BGColor'],
+ ['FitWindow','-','About']
+] ;
+
+FCKConfig.ToolbarSets["Basic"] = [
+ ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About']
+] ;
+
+FCKConfig.EnterMode = 'p' ; // p | div | br
+FCKConfig.ShiftEnterMode = 'br' ; // p | div | br
+
+FCKConfig.Keystrokes = [
+ [ CTRL + 65 /*A*/, true ],
+ [ CTRL + 67 /*C*/, true ],
+ [ CTRL + 70 /*F*/, true ],
+ [ CTRL + 83 /*S*/, true ],
+ [ CTRL + 88 /*X*/, true ],
+ [ CTRL + 86 /*V*/, 'Paste' ],
+ [ SHIFT + 45 /*INS*/, 'Paste' ],
+ [ CTRL + 90 /*Z*/, 'Undo' ],
+ [ CTRL + 89 /*Y*/, 'Redo' ],
+ [ CTRL + SHIFT + 90 /*Z*/, 'Redo' ],
+ [ CTRL + 76 /*L*/, 'Link' ],
+ [ CTRL + 66 /*B*/, 'Bold' ],
+ [ CTRL + 73 /*I*/, 'Italic' ],
+ [ CTRL + 85 /*U*/, 'Underline' ],
+ [ CTRL + SHIFT + 83 /*S*/, 'Save' ],
+ [ CTRL + ALT + 13 /*ENTER*/, 'FitWindow' ],
+ [ CTRL + 9 /*TAB*/, 'Source' ]
+] ;
+
+FCKConfig.ContextMenu = ['Generic','Link','Anchor','Image','Flash','Select','Textarea','Checkbox','Radio','TextField','HiddenField','ImageButton','Button','BulletedList','NumberedList','Table','Form'] ;
+FCKConfig.BrowserContextMenuOnCtrl = false ;
+
+FCKConfig.FontColors = '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,808080,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF' ;
+
+FCKConfig.FontNames = 'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
+FCKConfig.FontSizes = '1/xx-small;2/x-small;3/small;4/medium;5/large;6/x-large;7/xx-large' ;
+FCKConfig.FontFormats = 'p;div;pre;address;h1;h2;h3;h4;h5;h6' ;
+
+FCKConfig.StylesXmlPath = FCKConfig.EditorPath + 'fckstyles.xml' ;
+FCKConfig.TemplatesXmlPath = FCKConfig.EditorPath + 'fcktemplates.xml' ;
+
+FCKConfig.SpellChecker = 'ieSpell' ; // 'ieSpell' | 'SpellerPages'
+FCKConfig.IeSpellDownloadUrl = 'http://www.iespell.com/download.php' ;
+FCKConfig.SpellerPagesServerScript = 'server-scripts/spellchecker.php' ; // Available extension: .php .cfm .pl
+FCKConfig.FirefoxSpellChecker = false ;
+
+FCKConfig.MaxUndoLevels = 15 ;
+
+FCKConfig.DisableObjectResizing = false ;
+FCKConfig.DisableFFTableHandles = true ;
+
+FCKConfig.LinkDlgHideTarget = false ;
+FCKConfig.LinkDlgHideAdvanced = false ;
+
+FCKConfig.ImageDlgHideLink = false ;
+FCKConfig.ImageDlgHideAdvanced = false ;
+
+FCKConfig.FlashDlgHideAdvanced = false ;
+
+FCKConfig.ProtectedTags = '' ;
+
+// This will be applied to the body element of the editor
+FCKConfig.BodyId = '' ;
+FCKConfig.BodyClass = '' ;
+
+FCKConfig.DefaultLinkTarget = '' ;
+
+// The option switches between trying to keep the html structure or do the changes so the content looks like it was in Word
+FCKConfig.CleanWordKeepsStructure = false ;
+
+// The following value defines which File Browser connector and Quick Upload
+// "uploader" to use. It is valid for the default implementaion and it is here
+// just to make this configuration file cleaner.
+// It is not possible to change this value using an external file or even
+// inline when creating the editor instance. In that cases you must set the
+// values of LinkBrowserURL, ImageBrowserURL and so on.
+// Custom implementations should just ignore it.
+var _FileBrowserLanguage = 'asp' ; // asp | aspx | cfm | lasso | perl | php | py
+var _QuickUploadLanguage = 'asp' ; // asp | aspx | cfm | lasso | php
+
+
+// Don't care about the following line. It just calculates the correct connector
+// extension to use for the default File Browser (Perl uses "cgi").
+var _FileBrowserExtension = _FileBrowserLanguage == 'perl' ? 'cgi' : _FileBrowserLanguage ;
+
+FCKConfig.LinkBrowser = true ;
+FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
+FCKConfig.LinkBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70%
+FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70%
+
+FCKConfig.ImageBrowser = true ;
+FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
+FCKConfig.ImageBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70% ;
+FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ;
+
+FCKConfig.FlashBrowser = true ;
+FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
+FCKConfig.FlashBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; //70% ;
+FCKConfig.FlashBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; //70% ;
+
+FCKConfig.LinkUpload = true ;
+FCKConfig.LinkUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage ;
+FCKConfig.LinkUploadAllowedExtensions = "" ; // empty for all
+FCKConfig.LinkUploadDeniedExtensions = ".(html|htm|php|php2|php3|php4|php5|phtml|pwml|inc|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|com|dll|vbs|js|reg|cgi|htaccess|asis|sh|shtml|shtm|phtm)$" ; // empty for no one
+
+FCKConfig.ImageUpload = true ;
+FCKConfig.ImageUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Image' ;
+FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png|bmp)$" ; // empty for all
+FCKConfig.ImageUploadDeniedExtensions = "" ; // empty for no one
+
+FCKConfig.FlashUpload = true ;
+FCKConfig.FlashUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Flash' ;
+FCKConfig.FlashUploadAllowedExtensions = ".(swf|fla)$" ; // empty for all
+FCKConfig.FlashUploadDeniedExtensions = "" ; // empty for no one
+
+FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ;
+FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif','teeth_smile.gif','confused_smile.gif','tounge_smile.gif','embaressed_smile.gif','omg_smile.gif','whatchutalkingabout_smile.gif','angry_smile.gif','angel_smile.gif','shades_smile.gif','devil_smile.gif','cry_smile.gif','lightbulb.gif','thumbs_down.gif','thumbs_up.gif','heart.gif','broken_heart.gif','kiss.gif','envelope.gif'] ;
+FCKConfig.SmileyColumns = 8 ;
+FCKConfig.SmileyWindowWidth = 320 ;
+FCKConfig.SmileyWindowHeight = 240 ;
diff --git a/httemplate/elements/fckeditor/fckeditor.js b/httemplate/elements/fckeditor/fckeditor.js
new file mode 100644
index 000000000..63ec41f80
--- /dev/null
+++ b/httemplate/elements/fckeditor/fckeditor.js
@@ -0,0 +1,214 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the integration file for JavaScript.
+ *
+ * It defines the FCKeditor class that can be used to create editor
+ * instances in a HTML page in the client side. For server side
+ * operations, use the specific integration system.
+ */
+
+// FCKeditor Class
+var FCKeditor = function( instanceName, width, height, toolbarSet, value )
+{
+ // Properties
+ this.InstanceName = instanceName ;
+ this.Width = width || '100%' ;
+ this.Height = height || '200' ;
+ this.ToolbarSet = toolbarSet || 'Default' ;
+ this.Value = value || '' ;
+ this.BasePath = '/fckeditor/' ;
+ this.CheckBrowser = true ;
+ this.DisplayErrors = true ;
+ this.EnableSafari = false ; // This is a temporary property, while Safari support is under development.
+ this.EnableOpera = false ; // This is a temporary property, while Opera support is under development.
+
+ this.Config = new Object() ;
+
+ // Events
+ this.OnError = null ; // function( source, errorNumber, errorDescription )
+}
+
+FCKeditor.prototype.Version = '2.4.3' ;
+FCKeditor.prototype.VersionBuild = '15657' ;
+
+FCKeditor.prototype.Create = function()
+{
+ document.write( this.CreateHtml() ) ;
+}
+
+FCKeditor.prototype.CreateHtml = function()
+{
+ // Check for errors
+ if ( !this.InstanceName || this.InstanceName.length == 0 )
+ {
+ this._ThrowError( 701, 'You must specify an instance name.' ) ;
+ return '' ;
+ }
+
+ var sHtml = '<div>' ;
+
+ if ( !this.CheckBrowser || this._IsCompatibleBrowser() )
+ {
+ sHtml += '<input type="hidden" id="' + this.InstanceName + '" name="' + this.InstanceName + '" value="' + this._HTMLEncode( this.Value ) + '" style="display:none" />' ;
+ sHtml += this._GetConfigHtml() ;
+ sHtml += this._GetIFrameHtml() ;
+ }
+ else
+ {
+ var sWidth = this.Width.toString().indexOf('%') > 0 ? this.Width : this.Width + 'px' ;
+ var sHeight = this.Height.toString().indexOf('%') > 0 ? this.Height : this.Height + 'px' ;
+ sHtml += '<textarea name="' + this.InstanceName + '" rows="4" cols="40" style="width:' + sWidth + ';height:' + sHeight + '">' + this._HTMLEncode( this.Value ) + '<\/textarea>' ;
+ }
+
+ sHtml += '</div>' ;
+
+ return sHtml ;
+}
+
+FCKeditor.prototype.ReplaceTextarea = function()
+{
+ if ( !this.CheckBrowser || this._IsCompatibleBrowser() )
+ {
+ // We must check the elements firstly using the Id and then the name.
+ var oTextarea = document.getElementById( this.InstanceName ) ;
+ var colElementsByName = document.getElementsByName( this.InstanceName ) ;
+ var i = 0;
+ while ( oTextarea || i == 0 )
+ {
+ if ( oTextarea && oTextarea.tagName.toLowerCase() == 'textarea' )
+ break ;
+ oTextarea = colElementsByName[i++] ;
+ }
+
+ if ( !oTextarea )
+ {
+ alert( 'Error: The TEXTAREA with id or name set to "' + this.InstanceName + '" was not found' ) ;
+ return ;
+ }
+
+ oTextarea.style.display = 'none' ;
+ this._InsertHtmlBefore( this._GetConfigHtml(), oTextarea ) ;
+ this._InsertHtmlBefore( this._GetIFrameHtml(), oTextarea ) ;
+ }
+}
+
+FCKeditor.prototype._InsertHtmlBefore = function( html, element )
+{
+ if ( element.insertAdjacentHTML ) // IE
+ element.insertAdjacentHTML( 'beforeBegin', html ) ;
+ else // Gecko
+ {
+ var oRange = document.createRange() ;
+ oRange.setStartBefore( element ) ;
+ var oFragment = oRange.createContextualFragment( html );
+ element.parentNode.insertBefore( oFragment, element ) ;
+ }
+}
+
+FCKeditor.prototype._GetConfigHtml = function()
+{
+ var sConfig = '' ;
+ for ( var o in this.Config )
+ {
+ if ( sConfig.length > 0 ) sConfig += '&amp;' ;
+ sConfig += encodeURIComponent( o ) + '=' + encodeURIComponent( this.Config[o] ) ;
+ }
+
+ return '<input type="hidden" id="' + this.InstanceName + '___Config" value="' + sConfig + '" style="display:none" />' ;
+}
+
+FCKeditor.prototype._GetIFrameHtml = function()
+{
+ var sFile = 'fckeditor.html' ;
+
+ try
+ {
+ if ( (/fcksource=true/i).test( window.top.location.search ) )
+ sFile = 'fckeditor.original.html' ;
+ }
+ catch (e) { /* Ignore it. Much probably we are inside a FRAME where the "top" is in another domain (security error). */ }
+
+ var sLink = this.BasePath + 'editor/' + sFile + '?InstanceName=' + encodeURIComponent( this.InstanceName ) ;
+ if (this.ToolbarSet) sLink += '&amp;Toolbar=' + this.ToolbarSet ;
+
+ return '<iframe id="' + this.InstanceName + '___Frame" src="' + sLink + '" width="' + this.Width + '" height="' + this.Height + '" frameborder="0" scrolling="no"></iframe>' ;
+}
+
+FCKeditor.prototype._IsCompatibleBrowser = function()
+{
+ return FCKeditor_IsCompatibleBrowser( this.EnableSafari, this.EnableOpera ) ;
+}
+
+FCKeditor.prototype._ThrowError = function( errorNumber, errorDescription )
+{
+ this.ErrorNumber = errorNumber ;
+ this.ErrorDescription = errorDescription ;
+
+ if ( this.DisplayErrors )
+ {
+ document.write( '<div style="COLOR: #ff0000">' ) ;
+ document.write( '[ FCKeditor Error ' + this.ErrorNumber + ': ' + this.ErrorDescription + ' ]' ) ;
+ document.write( '</div>' ) ;
+ }
+
+ if ( typeof( this.OnError ) == 'function' )
+ this.OnError( this, errorNumber, errorDescription ) ;
+}
+
+FCKeditor.prototype._HTMLEncode = function( text )
+{
+ if ( typeof( text ) != "string" )
+ text = text.toString() ;
+
+ text = text.replace(
+ /&/g, "&amp;").replace(
+ /"/g, "&quot;").replace(
+ /</g, "&lt;").replace(
+ />/g, "&gt;") ;
+
+ return text ;
+}
+
+function FCKeditor_IsCompatibleBrowser( enableSafari, enableOpera )
+{
+ var sAgent = navigator.userAgent.toLowerCase() ;
+
+ // Internet Explorer
+ if ( sAgent.indexOf("msie") != -1 && sAgent.indexOf("mac") == -1 && sAgent.indexOf("opera") == -1 )
+ {
+ var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
+ return ( sBrowserVersion >= 5.5 ) ;
+ }
+
+ // Gecko (Opera 9 tries to behave like Gecko at this point).
+ if ( navigator.product == "Gecko" && navigator.productSub >= 20030210 && !( typeof(opera) == 'object' && opera.postError ) )
+ return true ;
+
+ // Opera
+ if ( enableOpera && sAgent.indexOf( 'opera' ) == 0 && parseInt( navigator.appVersion, 10 ) >= 9 )
+ return true ;
+
+ // Safari
+ if ( enableSafari && sAgent.indexOf( 'safari' ) != -1 )
+ return ( sAgent.match( /safari\/(\d+)/ )[1] >= 312 ) ; // Build must be at least 312 (1.3)
+
+ return false ;
+} \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/fckpackager.xml b/httemplate/elements/fckeditor/fckpackager.xml
new file mode 100644
index 000000000..3cae595a6
--- /dev/null
+++ b/httemplate/elements/fckeditor/fckpackager.xml
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the configuration file to be used with FCKpackager to generate the
+ * compressed code files in the "js" folder.
+ *
+ * Please check http://www.fckeditor.net for more info.
+-->
+<Package>
+ <Header><![CDATA[/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This file has been compressed for better performance. The original source
+ * can be found at "editor/_source".
+ */
+]]></Header>
+ <Constants removeDeclaration="false">
+ <Constant name="FCK_STATUS_NOTLOADED" value="0" />
+ <Constant name="FCK_STATUS_ACTIVE" value="1" />
+ <Constant name="FCK_STATUS_COMPLETE" value="2" />
+ <Constant name="FCK_TRISTATE_OFF" value="0" />
+ <Constant name="FCK_TRISTATE_ON" value="1" />
+ <Constant name="FCK_TRISTATE_DISABLED" value="-1" />
+ <Constant name="FCK_UNKNOWN" value="-9" />
+ <Constant name="FCK_TOOLBARITEM_ONLYICON" value="0" />
+ <Constant name="FCK_TOOLBARITEM_ONLYTEXT" value="1" />
+ <Constant name="FCK_TOOLBARITEM_ICONTEXT" value="2" />
+ <Constant name="FCK_EDITMODE_WYSIWYG" value="0" />
+ <Constant name="FCK_EDITMODE_SOURCE" value="1" />
+ </Constants>
+ <PackageFile path="editor/js/fckeditorcode_ie.js">
+ <File path="editor/_source/fckconstants.js" />
+ <File path="editor/_source/fckjscoreextensions.js" />
+ <File path="editor/_source/classes/fckiecleanup.js" />
+ <File path="editor/_source/internals/fckbrowserinfo.js" />
+ <File path="editor/_source/internals/fckurlparams.js" />
+ <File path="editor/_source/classes/fckevents.js" />
+ <File path="editor/_source/internals/fck.js" />
+ <File path="editor/_source/internals/fck_ie.js" />
+ <File path="editor/_source/internals/fckconfig.js" />
+ <File path="editor/_source/internals/fckdebug.js" />
+ <File path="editor/_source/internals/fckdomtools.js" />
+ <File path="editor/_source/internals/fcktools.js" />
+ <File path="editor/_source/internals/fcktools_ie.js" />
+ <File path="editor/_source/fckeditorapi.js" />
+ <File path="editor/_source/classes/fckimagepreloader.js" />
+
+ <File path="editor/_source/internals/fckregexlib.js" />
+ <File path="editor/_source/internals/fcklistslib.js" />
+ <File path="editor/_source/internals/fcklanguagemanager.js" />
+ <File path="editor/_source/internals/fckxhtmlentities.js" />
+ <File path="editor/_source/internals/fckxhtml.js" />
+ <File path="editor/_source/internals/fckxhtml_ie.js" />
+ <File path="editor/_source/internals/fckcodeformatter.js" />
+ <File path="editor/_source/internals/fckundo_ie.js" />
+ <File path="editor/_source/classes/fckeditingarea.js" />
+ <File path="editor/_source/classes/fckkeystrokehandler.js" />
+
+ <File path="editor/_source/internals/fcklisthandler.js" />
+ <File path="editor/_source/classes/fckelementpath.js" />
+ <File path="editor/_source/classes/fckdomrange.js" />
+ <File path="editor/_source/classes/fckdomrange_ie.js" />
+ <File path="editor/_source/classes/fckdocumentfragment_ie.js" />
+ <File path="editor/_source/classes/fckw3crange.js" />
+ <File path="editor/_source/classes/fckenterkey.js" />
+
+ <File path="editor/_source/internals/fckdocumentprocessor.js" />
+ <File path="editor/_source/internals/fckselection.js" />
+ <File path="editor/_source/internals/fckselection_ie.js" />
+
+ <File path="editor/_source/internals/fcktablehandler.js" />
+ <File path="editor/_source/internals/fcktablehandler_ie.js" />
+ <File path="editor/_source/classes/fckxml_ie.js" />
+ <File path="editor/_source/classes/fckstyledef.js" />
+ <File path="editor/_source/classes/fckstyledef_ie.js" />
+ <File path="editor/_source/classes/fckstylesloader.js" />
+
+ <File path="editor/_source/commandclasses/fcknamedcommand.js" />
+ <File path="editor/_source/commandclasses/fck_othercommands.js" />
+ <File path="editor/_source/commandclasses/fckspellcheckcommand_ie.js" />
+ <File path="editor/_source/commandclasses/fcktextcolorcommand.js" />
+ <File path="editor/_source/commandclasses/fckpasteplaintextcommand.js" />
+ <File path="editor/_source/commandclasses/fckpastewordcommand.js" />
+ <File path="editor/_source/commandclasses/fcktablecommand.js" />
+ <File path="editor/_source/commandclasses/fckstylecommand.js" />
+ <File path="editor/_source/commandclasses/fckfitwindow.js" />
+ <File path="editor/_source/internals/fckcommands.js" />
+
+ <File path="editor/_source/classes/fckpanel.js" />
+ <File path="editor/_source/classes/fckicon.js" />
+ <File path="editor/_source/classes/fcktoolbarbuttonui.js" />
+ <File path="editor/_source/classes/fcktoolbarbutton.js" />
+ <File path="editor/_source/classes/fckspecialcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarspecialcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontscombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontsizecombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontformatcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarstylecombo.js" />
+ <File path="editor/_source/classes/fcktoolbarpanelbutton.js" />
+ <File path="editor/_source/internals/fcktoolbaritems.js" />
+ <File path="editor/_source/classes/fcktoolbar.js" />
+ <File path="editor/_source/classes/fcktoolbarbreak_ie.js" />
+ <File path="editor/_source/internals/fcktoolbarset.js" />
+ <File path="editor/_source/internals/fckdialog.js" />
+ <File path="editor/_source/internals/fckdialog_ie.js" />
+
+ <File path="editor/_source/classes/fckmenuitem.js" />
+ <File path="editor/_source/classes/fckmenublock.js" />
+ <File path="editor/_source/classes/fckmenublockpanel.js" />
+ <File path="editor/_source/classes/fckcontextmenu.js" />
+ <File path="editor/_source/internals/fck_contextmenu.js" />
+
+ <File path="editor/_source/classes/fckplugin.js" />
+ <File path="editor/_source/internals/fckplugins.js" />
+ </PackageFile>
+
+ <PackageFile path="editor/js/fckeditorcode_gecko.js">
+ <File path="editor/_source/fckconstants.js" />
+ <File path="editor/_source/fckjscoreextensions.js" />
+ <File path="editor/_source/internals/fckbrowserinfo.js" />
+ <File path="editor/_source/internals/fckurlparams.js" />
+ <File path="editor/_source/classes/fckevents.js" />
+ <File path="editor/_source/internals/fck.js" />
+ <File path="editor/_source/internals/fck_gecko.js" />
+ <File path="editor/_source/internals/fckconfig.js" />
+ <File path="editor/_source/internals/fckdebug.js" />
+ <File path="editor/_source/internals/fckdomtools.js" />
+ <File path="editor/_source/internals/fcktools.js" />
+ <File path="editor/_source/internals/fcktools_gecko.js" />
+ <File path="editor/_source/fckeditorapi.js" />
+ <File path="editor/_source/classes/fckimagepreloader.js" />
+
+ <File path="editor/_source/internals/fckregexlib.js" />
+ <File path="editor/_source/internals/fcklistslib.js" />
+ <File path="editor/_source/internals/fcklanguagemanager.js" />
+ <File path="editor/_source/internals/fckxhtmlentities.js" />
+ <File path="editor/_source/internals/fckxhtml.js" />
+ <File path="editor/_source/internals/fckxhtml_gecko.js" />
+ <File path="editor/_source/internals/fckcodeformatter.js" />
+ <File path="editor/_source/internals/fckundo_gecko.js" />
+ <File path="editor/_source/classes/fckeditingarea.js" />
+ <File path="editor/_source/classes/fckkeystrokehandler.js" />
+
+ <File path="editor/_source/internals/fcklisthandler.js" />
+ <File path="editor/_source/classes/fckelementpath.js" />
+ <File path="editor/_source/classes/fckdomrange.js" />
+ <File path="editor/_source/classes/fckdomrange_gecko.js" />
+ <File path="editor/_source/classes/fckdocumentfragment_gecko.js" />
+ <File path="editor/_source/classes/fckw3crange.js" />
+ <File path="editor/_source/classes/fckenterkey.js" />
+
+ <File path="editor/_source/internals/fckdocumentprocessor.js" />
+ <File path="editor/_source/internals/fckselection.js" />
+ <File path="editor/_source/internals/fckselection_gecko.js" />
+
+ <File path="editor/_source/internals/fcktablehandler.js" />
+ <File path="editor/_source/internals/fcktablehandler_gecko.js" />
+ <File path="editor/_source/classes/fckxml_gecko.js" />
+ <File path="editor/_source/classes/fckstyledef.js" />
+ <File path="editor/_source/classes/fckstyledef_gecko.js" />
+ <File path="editor/_source/classes/fckstylesloader.js" />
+
+ <File path="editor/_source/commandclasses/fcknamedcommand.js" />
+ <File path="editor/_source/commandclasses/fck_othercommands.js" />
+ <File path="editor/_source/commandclasses/fckspellcheckcommand_gecko.js" />
+ <File path="editor/_source/commandclasses/fcktextcolorcommand.js" />
+ <File path="editor/_source/commandclasses/fckpasteplaintextcommand.js" />
+ <File path="editor/_source/commandclasses/fckpastewordcommand.js" />
+ <File path="editor/_source/commandclasses/fcktablecommand.js" />
+ <File path="editor/_source/commandclasses/fckstylecommand.js" />
+ <File path="editor/_source/commandclasses/fckfitwindow.js" />
+ <File path="editor/_source/internals/fckcommands.js" />
+
+ <File path="editor/_source/classes/fckpanel.js" />
+ <File path="editor/_source/classes/fckicon.js" />
+ <File path="editor/_source/classes/fcktoolbarbuttonui.js" />
+ <File path="editor/_source/classes/fcktoolbarbutton.js" />
+ <File path="editor/_source/classes/fckspecialcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarspecialcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontscombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontsizecombo.js" />
+ <File path="editor/_source/classes/fcktoolbarfontformatcombo.js" />
+ <File path="editor/_source/classes/fcktoolbarstylecombo.js" />
+ <File path="editor/_source/classes/fcktoolbarpanelbutton.js" />
+ <File path="editor/_source/internals/fcktoolbaritems.js" />
+ <File path="editor/_source/classes/fcktoolbar.js" />
+ <File path="editor/_source/classes/fcktoolbarbreak_gecko.js" />
+ <File path="editor/_source/internals/fcktoolbarset.js" />
+ <File path="editor/_source/internals/fckdialog.js" />
+ <File path="editor/_source/internals/fckdialog_gecko.js" />
+
+ <File path="editor/_source/classes/fckmenuitem.js" />
+ <File path="editor/_source/classes/fckmenublock.js" />
+ <File path="editor/_source/classes/fckmenublockpanel.js" />
+ <File path="editor/_source/classes/fckcontextmenu.js" />
+ <File path="editor/_source/internals/fck_contextmenu.js" />
+
+ <File path="editor/_source/classes/fckplugin.js" />
+ <File path="editor/_source/internals/fckplugins.js" />
+ </PackageFile>
+
+</Package> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/fckstyles.xml b/httemplate/elements/fckeditor/fckstyles.xml
new file mode 100644
index 000000000..bfd80e717
--- /dev/null
+++ b/httemplate/elements/fckeditor/fckstyles.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the sample style definitions file. It makes the styles combo
+ * completely customizable.
+ *
+ * See FCKConfig.StylesXmlPath in the configuration file.
+-->
+<Styles>
+ <Style name="Image on Left" element="img">
+ <Attribute name="style" value="padding: 5px; margin-right: 5px" />
+ <Attribute name="border" value="2" />
+ <Attribute name="align" value="left" />
+ </Style>
+ <Style name="Image on Right" element="img">
+ <Attribute name="style" value="padding: 5px; margin-left: 5px" />
+ <Attribute name="border" value="2" />
+ <Attribute name="align" value="right" />
+ </Style>
+ <Style name="Custom Bold" element="span">
+ <Attribute name="style" value="font-weight: bold;" />
+ </Style>
+ <Style name="Custom Italic" element="em" />
+ <Style name="Title" element="span">
+ <Attribute name="class" value="Title" />
+ </Style>
+ <Style name="Code" element="span">
+ <Attribute name="class" value="Code" />
+ </Style>
+ <Style name="Title H3" element="h3" />
+ <Style name="Custom Ruler" element="hr">
+ <Attribute name="size" value="1" />
+ <Attribute name="color" value="#ff0000" />
+ </Style>
+</Styles> \ No newline at end of file
diff --git a/httemplate/elements/fckeditor/fcktemplates.xml b/httemplate/elements/fckeditor/fcktemplates.xml
new file mode 100644
index 000000000..87610628a
--- /dev/null
+++ b/httemplate/elements/fckeditor/fcktemplates.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is the sample templates definitions file. It makes the "templates"
+ * command completely customizable.
+ *
+ * See FCKConfig.TemplatesXmlPath in the configuration file.
+-->
+<Templates imagesBasePath="fck_template/images/">
+ <Template title="Image and Title" image="template1.gif">
+ <Description>One main image with a title and text that surround the image.</Description>
+ <Html>
+ <![CDATA[
+ <img style="MARGIN-RIGHT: 10px" height="100" alt="" width="100" align="left"/>
+ <h3>Type the title here</h3>
+ Type the text here
+ ]]>
+ </Html>
+ </Template>
+ <Template title="Strange Template" image="template2.gif">
+ <Description>A template that defines two colums, each one with a title, and some text.</Description>
+ <Html>
+ <![CDATA[
+ <table cellspacing="0" cellpadding="0" width="100%" border="0">
+ <tbody>
+ <tr>
+ <td width="50%">
+ <h3>Title 1</h3>
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </td>
+ <td width="50%">
+ <h3>Title 2</h3>
+ </td>
+ </tr>
+ <tr>
+ <td>Text 1</td>
+ <td>&nbsp;</td>
+ <td>Text 2</td>
+ </tr>
+ </tbody>
+ </table>
+ More text goes here.
+ ]]>
+ </Html>
+ </Template>
+ <Template title="Text and Table" image="template3.gif">
+ <Description>A title with some text and a table.</Description>
+ <Html>
+ <![CDATA[
+ <table align="left" width="80%" border="0" cellspacing="0" cellpadding="0"><tr><td>
+ <h3>Title goes here</h3>
+ <p>
+ <table style="FLOAT: right" cellspacing="0" cellpadding="0" width="150" border="1">
+ <tbody>
+ <tr>
+ <td align="center" colspan="3"><strong>Table title</strong></td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ </tr>
+ </tbody>
+ </table>
+ Type the text here</p>
+ </td></tr></table>
+ ]]>
+ </Html>
+ </Template>
+</Templates>
diff --git a/httemplate/elements/file-upload.html b/httemplate/elements/file-upload.html
new file mode 100644
index 000000000..c8b026d04
--- /dev/null
+++ b/httemplate/elements/file-upload.html
@@ -0,0 +1,74 @@
+<SCRIPT TYPE="text/javascript">
+
+ function doUpload(form, callback) {
+ var name = 'form' + Math.floor(Math.random() * 99999); // perlize?
+ var d = document.createElement('DIV');
+ d.innerHTML = '<iframe style="display:none" src="about:blank" ' +
+ 'id="' + name + '" ' +
+ 'name="' + name + '" ' +
+ 'onload="uploadComplete(\'' + name + '\')">' +
+ '</iframe>';
+ document.body.appendChild(d);
+
+ var i = document.getElementById(name);
+ if (callback && typeof(callback) == 'function') {
+ i.onComplete = callback;
+ }
+
+ form.setAttribute('target', name);
+ return true;
+ }
+
+ function uploadComplete(id) {
+ var i = document.getElementById(id);
+ if (i.contentDocument) {
+ var d = i.contentDocument;
+ } else if (i.contentWindow) {
+ var d = i.contentWindow.document;
+ } else {
+ var d = window.frames[id].document;
+ }
+ if (d.location.href == "about:blank") {
+ return;
+ }
+
+ document.getElementById('r').innerHTML = d.body.innerHTML;
+ if (typeof(i.onComplete) == 'function') {
+ var p;
+ if (p = d.body.innerHTML.indexOf("File Upload Successful ") >= 0) {
+ var v = d.body.innerHTML.substr(p+24);
+ var u = document.getElementById('uploaded_files');
+ v = v.substr(0, v.indexOf(';'));
+ u.value = v;
+ i.onComplete(true, '');
+ }else{
+ i.onComplete(false, d.body.innerHTML);
+ }
+ }
+ }
+
+</SCRIPT>
+
+<INPUT TYPE="hidden" NAME="uploaded_files" ID="uploaded_files" VALUE="" />
+
+<INPUT TYPE="hidden" NAME="upload_fields" VALUE="<% join(',', @field) %>" />
+
+% foreach (@field) {
+ <TR>
+ <TH ALIGN="right"><% shift @label %></TH>
+ <TD><INPUT TYPE="file" NAME="<% $_ %>" /></TD>
+ </TR>
+% }
+
+<DIV STYLE="display:<% $param{debug} ? 'visible' : 'none' %>">
+ Debugging: <PRE ID="r"></PRE>
+</DIV>
+
+<%init>
+
+my %param = @_;
+
+my @label = ref($param{'label'}) ? @{$param{'label'}} : ($param{'label'});
+my @field = ref($param{'field'}) ? @{$param{'field'}} : ($param{'field'});
+
+</%init>
diff --git a/httemplate/elements/footer.html b/httemplate/elements/footer.html
new file mode 100644
index 000000000..32d121996
--- /dev/null
+++ b/httemplate/elements/footer.html
@@ -0,0 +1,5 @@
+ </TD>
+ </TR>
+ </TABLE>
+ </BODY>
+</HTML>
diff --git a/httemplate/elements/form-file_upload.html b/httemplate/elements/form-file_upload.html
new file mode 100644
index 000000000..4ab70ad9c
--- /dev/null
+++ b/httemplate/elements/form-file_upload.html
@@ -0,0 +1,93 @@
+<%doc>
+
+Example:
+
+ <% include( '/elements/form-file_upload.html',
+
+ 'name' => 'form_name',
+ 'action' => 'process/target.cgi', #progress-init target
+ 'fields' => [ 'other', 'form', 'fields' ],
+ 'num_files' => 1, #or more
+
+ 'url' => $url
+ #AND/OR
+ 'message' => 'Message',
+
+ #optional
+ 'key' => 'unique_key', #for using more than once on a page
+ )
+
+% #...
+
+% # num_files=>1
+ include( '/elements/file-upload.html',
+ 'field' => 'element',
+ 'label' => 'Label',
+ )
+
+% # OR
+
+% # num_files=>2 # or more
+ include( '/elements/file-upload.html',
+ 'field' => [ 'element', 'element2', ], #etc.
+ 'label' => [ 'Label', 'Label2', ], #etc.
+ )
+
+
+%>
+
+</%doc>
+
+<% include( '/elements/progress-init.html',
+ $opt{name},
+ $opt{fields},
+ $opt{action},
+ $msg_or_url,
+ $opt{key},
+ )
+%>
+
+<SCRIPT>
+
+ function <% $opt{key} %>gotUploaded(success, message) {
+
+ var uploaded = document.getElementById('uploaded_files');
+ var a = uploaded.value.split(',');
+ if (success && uploaded.value.split(',').length == <% $opt{num_files} %>){
+ process();
+ }else{
+ var p = document.getElementById('uploadError');
+ p.innerHTML='<FONT SIZE="+1" COLOR="#ff0000">Error: '+message+'</FONT><BR><BR>';
+ p.style='display:visible';
+ return false;
+ }
+
+ }
+
+</SCRIPT>
+
+<div style="display:none:" id="uploadError"></div>
+
+<FORM NAME = "<% $opt{name} %>"
+ ACTION = "<% $fsurl %>misc/file-upload.html"
+ METHOD = "POST"
+ ENCTYPE = "multipart/form-data"
+ onSubmit = "return doUpload(this, <% $opt{key} %>gotUploaded)"
+>
+
+<%init>
+
+#my( $formname, $fields, $action, $url_or_message, $key ) = @_;
+my %opt = ref($_[0]) ? %{ $_[0] } : @_;
+
+my $key = exists $opt{key} ? $opt{key} : '';
+
+push @{ $opt{fields} }, 'uploaded_files';
+
+my $msg_or_url = $opt{message}
+ ? { 'message' => $opt{message},
+ 'url' => $opt{url},
+ }
+ : $opt{url};
+
+</%init>
diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css
new file mode 100644
index 000000000..c310e2fa0
--- /dev/null
+++ b/httemplate/elements/freeside.css
@@ -0,0 +1,16 @@
+* {
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ /* font-family: Verdana, Arial, Helvetica, sans-serif; */
+}
+
+A:link IMG, A:visited { border-style: none }
+/* A:focus {text-decoration: underline } */
+
+a:link, a:visited {
+ /* text-decoration: none; */
+ color: #000000;
+}
+/* a:hover { text-decoration: underline } */
+
+/* a:focus { background-color: #ccccee } */
+
diff --git a/httemplate/elements/header-minimal.html b/httemplate/elements/header-minimal.html
new file mode 100644
index 000000000..f74a9cc62
--- /dev/null
+++ b/httemplate/elements/header-minimal.html
@@ -0,0 +1,19 @@
+%
+% my($title, $menubar) = ( shift, shift ); #$menubar is unused here though
+% my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
+% my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section
+% my $conf = new FS::Conf;
+%
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+ <HEAD>
+ <TITLE>
+ <% $title %>
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+ <% $head %>
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8" <% $etc %>>
diff --git a/httemplate/elements/header-popup.html b/httemplate/elements/header-popup.html
new file mode 100644
index 000000000..68be108d2
--- /dev/null
+++ b/httemplate/elements/header-popup.html
@@ -0,0 +1,24 @@
+%
+% my($title, $menubar) = ( shift, shift ); #$menubar is unused here though
+% my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
+% my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section
+% my $conf = new FS::Conf;
+%
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+ <HEAD>
+ <TITLE>
+ <% $title %>
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+ <% $head %>
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8" <% $etc %>>
+ <link href="<%$fsurl%>elements/freeside.css" type="text/css" rel="stylesheet">
+ <FONT SIZE=6>
+ <CENTER><% $title %></CENTER>
+ </FONT>
+ <BR><!--<BR>-->
diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html
new file mode 100644
index 000000000..8e902f038
--- /dev/null
+++ b/httemplate/elements/header.html
@@ -0,0 +1,299 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+ <HEAD>
+ <TITLE>
+ <% $title %>
+ </TITLE>
+ <META HTTP-Equiv="Cache-Control" Content="no-cache">
+ <META HTTP-Equiv="Pragma" Content="no-cache">
+ <META HTTP-Equiv="Expires" Content="0">
+
+ <% include('menu.html', 'freeside_baseurl' => $fsurl,
+ 'position' => $menu_position,
+ ) |n
+ %>
+
+ <% include('init_overlib.html') |n %>
+
+ <SCRIPT TYPE="text/javascript">
+ function clearhint_search_cust (what) {
+ if ( what.value == '(cust #, name, company or phone)' )
+ what.value = '';
+ }
+
+ function clearhint_search_address2 (what) {
+ if ( what.value == '(Unit #)' )
+ what.value = '';
+ }
+
+ function clearhint_search_invoice (what) {
+ if ( what.value == '(inv #)' )
+ what.value = '';
+ }
+
+ function clearhint_search_svc (what) {
+ if ( what.value == '(user, email, ip, mac, or domain)' )
+ what.value = '';
+ }
+
+ function clearhint_search_ticket (what) {
+ if ( what.value == '(ticket #, subject, email or fulltext:text)' )
+ what.value = '';
+ }
+ </SCRIPT>
+
+ <% $head |n %>
+
+ </HEAD>
+ <BODY <% $menu_position eq 'left' ? qq( BACKGROUND="${fsurl}images/background-cheat.png" ) : ' BGCOLOR="#e8e8e8" ' %> <% $etc |n %> STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0">
+ <table width="100%" CELLPADDING=0 CELLSPACING=0 STYLE="padding-left:0; padding-right:4">
+ <tr>
+ <td rowspan=2 BGCOLOR="#ffffff"><IMG BORDER=0 ALT="freeside" SRC="<%$fsurl%>view/REAL_logo.cgi"></td>
+ <td align=left rowspan=2 BGCOLOR="#ffffff"> <!-- valign="top" -->
+ <font size=6><% $company_name || 'ExampleCo' %></font>
+ </td>
+ <td align=right valign=top BGCOLOR="#ffffff"><FONT SIZE="-1">Logged in as <b><% getotaker %>&nbsp;</b><br></FONT><FONT SIZE="-2"><a href="<%$fsurl%>pref/pref.html">Preferences</a>&nbsp;<BR></FONT>
+ </td>
+ </tr>
+ <tr>
+ <td align=right valign=bottom BGCOLOR="#ffffff">
+
+ <table>
+ <tr>
+ <td align=right BGCOLOR="#ffffff">
+ <FONT SIZE="-2">
+ <% include('/elements/popup_link.html',
+ 'action' => $fsurl.'docs/about.html',
+ 'label' => 'Freeside',
+ 'actionlabel' => 'About',
+ 'width' => 300,
+ 'height' => 360,
+ 'color' => '#7e0079',
+ 'scrolling' => 'no',
+ ) |n
+ %>&nbsp;v<% $FS::VERSION %><BR>
+ <A HREF="<% $conf->config('support-key') ? "http://www.freeside.biz/mediawiki/index.php/Supported:Documentation" : "http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation" %>" TARGET="_blank">Documentation</A><BR>
+ </FONT>
+ </td>
+% if ( $conf->config('ticket_system') eq 'RT_Internal' ) {
+% eval "use RT;";
+
+ <td bgcolor=#000000></td>
+ <td align=left>
+ <FONT SIZE="-2">
+ <A HREF="http://www.bestpractical.com/rt" TARGET="_blank">RT<A>&nbsp;v<% $RT::VERSION %><BR>
+ <A HREF="http://wiki.bestpractical.com/" TARGET="_blank">Documentation</A><BR>
+ </FONT>
+ </td>
+% }
+
+
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+ </table>
+
+<style type="text/css">
+input.fsblackbutton {
+ background-color:#333333;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ font-weight:bold;
+ padding-left:12px;
+ padding-right:12px;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666')
+}
+
+input.fsblackbuttonselected {
+ background-color:#7e0079;
+ color: #ffffff;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+ font-weight:bold;
+ padding-left:12px;
+ padding-right:12px;
+ overflow:visible;
+ filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079')
+}
+</style>
+
+ <TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD COLSPAN=6 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD>
+ </TR>
+
+% if ( $menu_position eq 'top' ) {
+
+ <TR>
+
+ <TD COLSPAN="6" WIDTH="100%" STYLE="padding:0">
+ <SCRIPT TYPE="text/javascript">
+ document.write(myBar);
+ </SCRIPT>
+ </TD>
+
+ </TR>
+
+ <TR>
+ <TD COLSPAN="6" WIDTH="100%" HEIGHT="2px" STYLE="padding:0" BGCOLOR="#000000">
+ </TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN="6" WIDTH="100%" HEIGHT="4px" STYLE="padding:0" BGCOLOR="#000000">
+ </TD>
+ </TR>
+
+% }
+
+ <TR>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
+ <FORM ACTION="<%$fsurl%>edit/cust_main.cgi" METHOD="GET" STYLE="margin:0">
+ <INPUT TYPE="submit" VALUE="New customer" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="vertical-align:bottom; font-size:100%">
+ </FORM>
+ </TD>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
+% if ( $curuser->access_right('List customers') ) {
+ <FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0">
+ <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name, company or phone)" SIZE="28" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
+ <A HREF="<%$fsurl%>search/report_cust_main.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search customers" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ </FORM>
+% }
+ </TD>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="center">
+% if ( $conf->exists('address2-search') ) {
+ <FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0;display:inline">
+ <INPUT TYPE="hidden" NAME="address2_on" VALUE="1">
+ <INPUT NAME="address2_text" TYPE="text" VALUE="(Unit #)" SIZE="4" onFocus="clearhint_search_address2(this);" onClick="clearhint_search_address2(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
+ <BR>
+ <INPUT TYPE="submit" VALUE="Search units" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
+ </FORM>
+% }
+ </TD>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
+% if ( $curuser->access_right('View invoices') ) {
+
+ <FORM ACTION="<%$fsurl%>search/cust_bill.html" METHOD="GET" STYLE="margin:0;display:inline">
+ <INPUT NAME="invnum" TYPE="text" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
+% if ( $curuser->access_right('List invoices') ) {
+
+ <A HREF="<%$fsurl%>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
+% }
+
+ <BR>
+ <INPUT TYPE="submit" VALUE="Search invoices" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ </FORM>
+% }
+ </TD>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
+ <FORM ACTION="<%$fsurl%>search/cust_svc.html" METHOD="GET" STYLE="margin:0">
+ <INPUT NAME="search_svc" TYPE="text" VALUE="(user, email, ip, mac, or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
+ <A NOTYET="<%$fsurl%>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search services" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
+ </FORM>
+ </TD>
+
+ <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right" STYLE="padding-right:4px">
+% if ( $conf->config("ticket_system") ) {
+ <FORM ACTION="<% FS::TicketSystem->baseurl %>index.html" METHOD="GET" STYLE="margin:0">
+ <INPUT NAME="q" TYPE="text" VALUE="(ticket #, subject, email or fulltext:text)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="vertical-align:bottom;text-align:right"><BR>
+ <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
+ <INPUT TYPE="submit" VALUE="Search tickets" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
+ </FORM>
+% }
+ </TD>
+
+ </TR>
+ </TABLE>
+
+ <TABLE WIDTH="100%" HEIGHT="100%" CELLSPACING=0 CELLPADDING=4>
+
+ <TR>
+
+% if ( $menu_position eq 'left' ) {
+
+ <TD BGCOLOR="#000000" STYLE="padding:0" WIDTH="154"></TD>
+ <TD STYLE="padding:0" WIDTH="13"><IMG BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gray-corner.png"></TD>
+
+% }
+
+ <TD STYLE="padding:0" WIDTH="100%"><IMG BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gray-top.png" HEIGHT="13" WIDTH="100%"></TD>
+
+ </TR>
+
+ <TR HEIGHT="100%">
+
+% if ( $menu_position eq 'left' ) {
+
+ <TD BGCOLOR="#000000" ALIGN="left" HEIGHT="100%" WIDTH="154" VALIGN="top" ALIGN="right">
+ <SCRIPT TYPE="text/javascript">
+ document.write(myBar);
+ </SCRIPT>
+ <BR>
+ <IMG SRC="<%$fsurl%>images/32clear.gif" HEIGHT="1" WIDTH="154">
+
+ </TD>
+ <TD STYLE="padding:0" HEIGHT="100%" WIDTH=13 VALIGN="top"><IMG WIDTH="13" HEIGHT="100%" BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gray-side.png"></TD>
+
+% }
+
+ <TD BGCOLOR="#e8e8e8" HEIGHT="100%" VALIGN="top"> <!-- WIDTH="100%"> -->
+
+ <FONT SIZE=6>
+ <% $title %>
+ </FONT>
+
+% unless ( $nobr ) {
+ <BR><BR>
+% }
+
+ <% $menubar !~ /^\s*$/ ? "$menubar<BR><BR>" : '' %>
+<%init>
+
+my( $title, $menubar, $etc, $head ) = ( '', '', '', '' );
+my( $nobr ) = ( 0 );
+if ( ref($_[0]) ) {
+ my $opt = shift;
+ $title = $opt->{title};
+ $menubar = $opt->{menubar};
+ $etc = $opt->{etc};
+ $head = $opt->{head};
+ $nobr = $opt->{nobr};
+} else {
+ ($title, $menubar) = ( shift, shift );
+ $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc.
+ $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section
+}
+
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $menu_position = $curuser->option('menu_position')
+ || 'top'; #new default for 1.9
+
+my $company_name;
+my @agentnums = $curuser->agentnums;
+if ( scalar(@agentnums) == 1 ) {
+ $company_name = $conf->config('company_name', $agentnums[0] );
+} else {
+ $company_name = $conf->config('company_name');
+}
+
+</%init>
diff --git a/httemplate/elements/hidden.html b/httemplate/elements/hidden.html
new file mode 100644
index 000000000..831108121
--- /dev/null
+++ b/httemplate/elements/hidden.html
@@ -0,0 +1,11 @@
+<INPUT TYPE = "hidden"
+ NAME = "<% $opt{field} %>"
+ ID = "<% $opt{field} %>"
+ VALUE = "<% $opt{curr_value} || $opt{value} |h %>"
+>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/htmlarea.html b/httemplate/elements/htmlarea.html
new file mode 100644
index 000000000..f27c4b5e6
--- /dev/null
+++ b/httemplate/elements/htmlarea.html
@@ -0,0 +1,36 @@
+<%doc>
+
+Example:
+
+ include('/elements/htmlarea.html',
+ 'field' => 'fieldname',
+ 'curr_value' => $curr_value,
+ 'height' => 800,
+ );
+
+</%doc>
+
+% #init
+<SCRIPT TYPE="text/javascript" src="<% $p %>elements/fckeditor/fckeditor.js">
+</SCRIPT>
+
+% #editor
+<SCRIPT TYPE="text/javascript">
+
+ var oFCKeditor = new FCKeditor('<% $opt{'field'} %>');
+ oFCKeditor.Value = <% $opt{'curr_value'} |js_string %>;
+
+ oFCKeditor.BasePath = '<% $p %>elements/fckeditor/';
+ oFCKeditor.Config['SkinPath'] = '<% $p %>elements/fckeditor/editor/skins/silver/';
+ oFCKeditor.Height = '<% $opt{'height'} || 420 %>';
+ oFCKeditor.Config['StartupFocus'] = true;
+
+ oFCKeditor.Create();
+
+</SCRIPT>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/iframecontentmws.js b/httemplate/elements/iframecontentmws.js
new file mode 100644
index 000000000..f2a91d21b
--- /dev/null
+++ b/httemplate/elements/iframecontentmws.js
@@ -0,0 +1,59 @@
+/*
+ iframecontentmws.js - Foteos Macrides (author and copyright holder)
+ Initial: October 10, 2004 - Last Revised: January 26, 2008
+ Scripts for using HTML documents as iframe content in overlibmws popups.
+
+ See http://www.macridesweb.com/oltest/IFRAME.html
+ and http://www.macridesweb.com/oltest/AJAX.html#ajaxex3
+ for more information.
+*/
+
+/*
+ Use as lead argument in overlib or overlb2 calls. Include WRAP and
+ TEXTPADDING,0 in the call to ensure that the width arg is respected (unless
+ the CAPTION plus CLOSETEXT widths add up to more than the width arg, in which
+ case you should increase the width arg). The name arg should be a unique
+ string for each popup with iframe content in the document. The frameborder
+ arg should be 1 (browser default if omitted) or 0. The scrolling arg should
+ be 'auto' (default if omitted), 'yes' or 'no'.
+*/
+function OLiframeContent(src, width, height, name, frameborder, scrolling) {
+
+ /* stupid safari iframe location caching... */
+ var d = new Date();
+ var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
+ name = name + '' + unique;
+
+ return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"'
+ +(name!=null?' name="'+name+'" id="'+name+'"':'')
+ +(frameborder!=null?' frameborder="'+frameborder+'"':'')
+ +' scrolling="'+(scrolling!=null?scrolling:'auto')
+ +'"><div>[iframe not supported]</div></iframe>');
+}
+
+/*
+ Swap the src if we are iframe content. The name arg should be the same
+ string as in the OLiframeContent function for the popup. The src arg is
+ a partial, relative, or complete URL for the document to be swapped in.
+*/
+function OLswapIframeSrc(name, src){
+ if(parent==self){
+ alert(src+'\n\n is only for iframe content');
+ return;
+ }
+ var o=parent.OLgetRef(name);
+ if(o)o.src=src;
+ else alert(src+'\n\n is not available');
+}
+
+/*
+ Emulate the Back button if we are iframe content. Use only in documents
+ which are swapped in by using the OLswapIframeSrc function.
+*/
+function OLiframeBack(){
+ if(parent==self){
+ alert('This feature is only for iframe content');
+ return;
+ }
+ history.back();
+}
diff --git a/httemplate/elements/init_calendar.html b/httemplate/elements/init_calendar.html
new file mode 100644
index 000000000..04b013596
--- /dev/null
+++ b/httemplate/elements/init_calendar.html
@@ -0,0 +1,5 @@
+<LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
+
+% foreach (qw( _stripped -en -setup )) {
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar<%$_%>.js"></SCRIPT>
+% }
diff --git a/httemplate/elements/init_overlib.html b/httemplate/elements/init_overlib.html
new file mode 100644
index 000000000..d27ca3bda
--- /dev/null
+++ b/httemplate/elements/init_overlib.html
@@ -0,0 +1,9 @@
+% for my $file (@files) {
+ <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/<%$file%>.js"></SCRIPT>
+% }
+<%init>
+
+my @files = map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) );
+push @files, map { "${_}contentmws" } qw( iframe ajax );
+
+</%init>
diff --git a/httemplate/elements/input-text.html b/httemplate/elements/input-text.html
new file mode 100644
index 000000000..9db064348
--- /dev/null
+++ b/httemplate/elements/input-text.html
@@ -0,0 +1,44 @@
+<% $opt{'prefix'} %><INPUT TYPE = "<% $opt{type} || 'text' %>"
+ NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id} %>"
+ VALUE = "<% $value |h %>"
+ <% $size %>
+ <% $maxlength %>
+ <% $style %>
+ <% $opt{disabled} %>
+ <% $onchange %>
+ ><% $opt{'postfix'} %>
+<%init>
+
+my %opt = @_;
+
+my $value = length($opt{curr_value}) ? $opt{curr_value} : $opt{value};
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $size = $opt{'size'}
+ ? 'SIZE="'. $opt{'size'}. '"'
+ : '';
+
+my $maxlength = $opt{'maxlength'}
+ ? 'MAXLENGTH="'. $opt{'maxlength'}. '"'
+ : '';
+
+$opt{'disabled'} = &{ $opt{'disabled'} }( \%opt )
+ if ref($opt{'disabled'}) eq 'CODE';
+$opt{'disabled'} = 'DISABLED'
+ if $opt{'disabled'} && $opt{'disabled'} !~ /disabled/i; # uuh... yeah?
+
+my @style = ();
+
+push @style, 'text-align: '. $opt{'text-align'}
+ if $opt{'text-align'};
+
+push @style, 'background-color: #dddddd'
+ if $opt{'disabled'};
+
+my $style = scalar(@style) ? 'STYLE="'. join(';', @style). '"' : '';
+
+</%init>
diff --git a/httemplate/elements/jsrsClient.js b/httemplate/elements/jsrsClient.js
new file mode 100644
index 000000000..3a2572ccb
--- /dev/null
+++ b/httemplate/elements/jsrsClient.js
@@ -0,0 +1,356 @@
+//
+// jsrsClient.js - javascript remote scripting client include
+//
+// Author: Brent Ashley [jsrs@megahuge.com]
+//
+// make asynchronous remote calls to server without client page refresh
+//
+// see license.txt for copyright and license information
+
+/*
+see history.txt for full history
+2.0 26 Jul 2001 - added POST capability for IE/MOZ
+2.2 10 Aug 2003 - added Opera support
+2.3(beta) 10 Oct 2003 - added Konqueror support - **needs more testing**
+*/
+
+// callback pool needs global scope
+var jsrsContextPoolSize = 0;
+var jsrsContextMaxPool = 10;
+var jsrsContextPool = new Array();
+var jsrsBrowser = jsrsBrowserSniff();
+var jsrsPOST = true;
+var containerName;
+
+// constructor for context object
+function jsrsContextObj( contextID ){
+
+ // properties
+ this.id = contextID;
+ this.busy = true;
+ this.callback = null;
+ this.container = contextCreateContainer( contextID );
+
+ // methods
+ this.GET = contextGET;
+ this.POST = contextPOST;
+ this.getPayload = contextGetPayload;
+ this.setVisibility = contextSetVisibility;
+}
+
+// method functions are not privately scoped
+// because Netscape's debugger chokes on private functions
+function contextCreateContainer( containerName ){
+ // creates hidden container to receive server data
+ var container;
+ switch( jsrsBrowser ) {
+ case 'NS':
+ container = new Layer(100);
+ container.name = containerName;
+ container.visibility = 'hidden';
+ container.clip.width = 100;
+ container.clip.height = 100;
+ break;
+
+ case 'IE':
+ document.body.insertAdjacentHTML( "afterBegin", '<span id="SPAN' + containerName + '"></span>' );
+ var span = document.all( "SPAN" + containerName );
+ var html = '<iframe name="' + containerName + '" src=""></iframe>';
+ span.innerHTML = html;
+ span.style.display = 'none';
+ container = window.frames[ containerName ];
+ break;
+
+ case 'MOZ':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+ break;
+
+ case 'OPR':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+ break;
+
+ case 'KONQ':
+ var span = document.createElement('SPAN');
+ span.id = "SPAN" + containerName;
+ document.body.appendChild( span );
+ var iframe = document.createElement('IFRAME');
+ iframe.name = containerName;
+ iframe.id = containerName;
+ span.appendChild( iframe );
+ container = iframe;
+
+ // Needs to be hidden for Konqueror, otherwise it'll appear on the page
+ span.style.display = none;
+ iframe.style.display = none;
+ iframe.style.visibility = hidden;
+ iframe.height = 0;
+ iframe.width = 0;
+
+ break;
+ }
+ return container;
+}
+
+function contextPOST( rsPage, func, parms ){
+
+ var d = new Date();
+ var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
+ var doc = (jsrsBrowser == "IE" ) ? this.container.document : this.container.contentDocument;
+ doc.open();
+ doc.write('<html><body>');
+ doc.write('<form name="jsrsForm" method="post" target="" ');
+ doc.write(' action="' + rsPage + '?U=' + unique + '">');
+ doc.write('<input type="hidden" name="C" value="' + this.id + '">');
+
+ // func and parms are optional
+ if (func != null){
+ doc.write('<input type="hidden" name="F" value="' + func + '">');
+
+ if (parms != null){
+ if (typeof(parms) == "string"){
+ // single parameter
+ doc.write( '<input type="hidden" name="P0" '
+ + 'value="[' + jsrsEscapeQQ(parms) + ']">');
+ } else {
+ // assume parms is array of strings
+ for( var i=0; i < parms.length; i++ ){
+ doc.write( '<input type="hidden" name="P' + i + '" '
+ + 'value="[' + jsrsEscapeQQ(parms[i]) + ']">');
+ }
+ } // parm type
+ } // parms
+ } // func
+
+ doc.write('</form></body></html>');
+ doc.close();
+ doc.forms['jsrsForm'].submit();
+}
+
+function contextGET( rsPage, func, parms ){
+
+ // build URL to call
+ var URL = rsPage;
+
+ // always send context
+ URL += "?C=" + this.id;
+
+ // func and parms are optional
+ if (func != null){
+ URL += "&F=" + escape(func);
+
+ if (parms != null){
+ if (typeof(parms) == "string"){
+ // single parameter
+ URL += "&P0=[" + escape(parms+'') + "]";
+ } else {
+ // assume parms is array of strings
+ for( var i=0; i < parms.length; i++ ){
+ URL += "&P" + i + "=[" + escape(parms[i]+'') + "]";
+ }
+ } // parm type
+ } // parms
+ } // func
+
+ // unique string to defeat cache
+ var d = new Date();
+ URL += "&U=" + d.getTime();
+
+ // make the call
+ switch( jsrsBrowser ) {
+ case 'NS':
+ this.container.src = URL;
+ break;
+ case 'IE':
+ this.container.document.location.replace(URL);
+ break;
+ case 'MOZ':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ case 'OPR':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ case 'KONQ':
+ this.container.src = '';
+ this.container.src = URL;
+ break;
+ }
+}
+
+function contextGetPayload(){
+ switch( jsrsBrowser ) {
+ case 'NS':
+ return this.container.document.forms['jsrs_Form'].elements['jsrs_Payload'].value;
+ case 'IE':
+ return this.container.document.forms['jsrs_Form']['jsrs_Payload'].value;
+ case 'MOZ':
+ return window.frames[this.container.name].document.forms['jsrs_Form']['jsrs_Payload'].value;
+ case 'OPR':
+ var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
+ case 'KONQ':
+ var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
+ return textElement.value;
+ }
+}
+
+function contextSetVisibility( vis ){
+ switch( jsrsBrowser ) {
+ case 'NS':
+ this.container.visibility = (vis)? 'show' : 'hidden';
+ break;
+ case 'IE':
+ document.all("SPAN" + this.id ).style.display = (vis)? '' : 'none';
+ break;
+ case 'MOZ':
+ document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
+ case 'OPR':
+ document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
+ this.container.width = (vis)? 250 : 0;
+ this.container.height = (vis)? 100 : 0;
+ break;
+ }
+}
+
+// end of context constructor
+
+function jsrsGetContextID(){
+ var contextObj;
+ for (var i = 1; i <= jsrsContextPoolSize; i++){
+ contextObj = jsrsContextPool[ 'jsrs' + i ];
+ if ( !contextObj.busy ){
+ contextObj.busy = true;
+ return contextObj.id;
+ }
+ }
+ // if we got here, there are no existing free contexts
+ if ( jsrsContextPoolSize <= jsrsContextMaxPool ){
+ // create new context
+ var contextID = "jsrs" + (jsrsContextPoolSize + 1);
+ jsrsContextPool[ contextID ] = new jsrsContextObj( contextID );
+ jsrsContextPoolSize++;
+ return contextID;
+ } else {
+ alert( "jsrs Error: context pool full" );
+ return null;
+ }
+}
+
+function jsrsExecute( rspage, callback, func, parms, visibility ){
+ // call a server routine from client code
+ //
+ // rspage - href to asp file
+ // callback - function to call on return
+ // or null if no return needed
+ // (passes returned string to callback)
+ // func - sub or function name to call
+ // parm - string parameter to function
+ // or array of string parameters if more than one
+ // visibility - optional boolean to make container visible for debugging
+
+ // get context
+ var contextObj = jsrsContextPool[ jsrsGetContextID() ];
+ contextObj.callback = callback;
+
+ var vis = (visibility == null)? false : visibility;
+ contextObj.setVisibility( vis );
+
+ if ( jsrsPOST && ((jsrsBrowser == 'IE') || (jsrsBrowser == 'MOZ'))){
+ contextObj.POST( rspage, func, parms );
+ } else {
+ contextObj.GET( rspage, func, parms );
+ }
+
+ return contextObj.id;
+}
+
+function jsrsLoaded( contextID ){
+ // get context object and invoke callback
+ var contextObj = jsrsContextPool[ contextID ];
+ if( contextObj.callback != null){
+ contextObj.callback( jsrsUnescape( contextObj.getPayload() ), contextID );
+ }
+ // clean up and return context to pool
+ contextObj.callback = null;
+ contextObj.busy = false;
+}
+
+function jsrsError( contextID, str ){
+ alert( unescape(str) );
+ jsrsContextPool[ contextID ].busy = false
+}
+
+function jsrsEscapeQQ( thing ){
+ return thing.replace(/'"'/g, '\\"');
+}
+
+function jsrsUnescape( str ){
+ // payload has slashes escaped with whacks
+ return str.replace( /\\\//g, "/" );
+}
+
+function jsrsBrowserSniff(){
+ if (document.layers) return "NS";
+ if (document.all) {
+ // But is it really IE?
+ // convert all characters to lowercase to simplify testing
+ var agt=navigator.userAgent.toLowerCase();
+ var is_opera = (agt.indexOf("opera") != -1);
+ var is_konq = (agt.indexOf("konqueror") != -1);
+ if(is_opera) {
+ return "OPR";
+ } else {
+ if(is_konq) {
+ return "KONQ";
+ } else {
+ // Really is IE
+ return "IE";
+ }
+ }
+ }
+ if (document.getElementById) return "MOZ";
+ return "OTHER";
+}
+
+/////////////////////////////////////////////////
+//
+// user functions
+
+function jsrsArrayFromString( s, delim ){
+ // rebuild an array returned from server as string
+ // optional delimiter defaults to ~
+ var d = (delim == null)? '~' : delim;
+ return s.split(d);
+}
+
+function jsrsDebugInfo(){
+ // use for debugging by attaching to f1 (works with IE)
+ // with onHelp = "return jsrsDebugInfo();" in the body tag
+ var doc = window.open().document;
+ doc.open;
+ doc.write( 'Pool Size: ' + jsrsContextPoolSize + '<br><font face="arial" size="2"><b>' );
+ for( var i in jsrsContextPool ){
+ var contextObj = jsrsContextPool[i];
+ doc.write( '<hr>' + contextObj.id + ' : ' + (contextObj.busy ? 'busy' : 'available') + '<br>');
+ doc.write( contextObj.container.document.location.pathname + '<br>');
+ doc.write( contextObj.container.document.location.search + '<br>');
+ doc.write( '<table border="1"><tr><td>' + contextObj.container.document.body.innerHTML + '</td></tr></table>' );
+ }
+ doc.write('</table>');
+ doc.close();
+ return false;
+}
diff --git a/httemplate/elements/jsrsServer.html b/httemplate/elements/jsrsServer.html
new file mode 100644
index 000000000..f37b0aaee
--- /dev/null
+++ b/httemplate/elements/jsrsServer.html
@@ -0,0 +1,4 @@
+%
+% my $server = new FS::UI::Web::JSRPC '', $cgi;
+%
+<% $server->process %>
diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html
new file mode 100644
index 000000000..d7b73a220
--- /dev/null
+++ b/httemplate/elements/location.html
@@ -0,0 +1,154 @@
+<%doc>
+
+Example:
+
+ include( '/elements/location.html',
+ 'object' => $cust_main, # or $cust_location
+ 'prefix' => $pre, #only for cust_main objects
+ 'onchange' => $javascript,
+ 'disabled' => $disabled,
+ 'same_checked' => $same_checked,
+ 'geocode' => $geocode, #passed through
+ 'no_asterisks' => 0, #set true to disable the red asterisks next
+ #to required fields
+ )
+
+</%doc>
+
+<TR>
+ <TH ALIGN="right"><%$r%>Address</TH>
+ <TD COLSPAN=7>
+ <INPUT TYPE = "text"
+ NAME = "<%$pre%>address1"
+ ID = "<%$pre%>address1"
+ VALUE = "<% $object->get($pre.'address1') |h %>"
+ SIZE = 58
+ onChange = "<% $onchange %>"
+ <% $disabled %>
+ <% $style %>
+ >
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right"><FONT ID="<% $pre %>address2_required" color="#ff0000" <% $address2_label_style %>>*</FONT>&nbsp;<FONT ID="<% $pre %>address2_label" <% $address2_label_style %>><B>Unit&nbsp;#</B></FONT></TD>
+ <TD COLSPAN=7>
+ <INPUT TYPE = "text"
+ NAME = "<%$pre%>address2"
+ ID = "<%$pre%>address2"
+ VALUE = "<% $object->get($pre.'address2') |h %>"
+ SIZE = 58
+ onChange = "<% $onchange %>"
+ <% $disabled %>
+ <% $style %>
+ >
+ </TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right"><%$r%>City</TH>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "<%$pre%>city"
+ ID = "<%$pre%>city"
+ VALUE = "<% $object->get($pre.'city') |h %>"
+ onChange = "<% $onchange %>"
+ <% $disabled %>
+ <% $style %>
+ >
+ </TD>
+ <TH ALIGN="right" ID="<%$pre%>countylabel" <%$county_style%>><%$r%>County</TH>
+ <TD>
+ <% include('/elements/select-county.html', %select_hash ) %>
+ </TD>
+ <TH ALIGN="right"><%$r%>State</TH>
+ <TD>
+ <% include('/elements/select-state.html', %select_hash ) %>
+ </TD>
+ <TH><%$r%>Zip</TH>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "<%$pre%>zip"
+ ID = "<%$pre%>zip"
+ VALUE = "<% $object->get($pre.'zip') |h %>"
+ SIZE = 10
+ onChange = "<% $onchange %>"
+ <% $disabled %>
+ <% $style %>
+ >
+ </TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right"><%$r%>Country</TH>
+ <TD COLSPAN=5><% include('/elements/select-country.html', %select_hash ) %></TD>
+</TR>
+
+% if ( !$pre ) {
+ <INPUT TYPE="hidden" NAME="geocode" VALUE="<% $opt{geocode} %>">
+% }
+
+<%init>
+
+my %opt = @_;
+
+my $pre = $opt{'prefix'};
+my $object = $opt{'object'};
+my $onchange = $opt{'onchange'};
+my $disabled = $opt{'disabled'};
+
+my $conf = new FS::Conf;
+
+my $r = $opt{'no_asterisks'} ? '' : qq!<font color="#ff0000">*</font>&nbsp;!;
+
+#false laziness with ship state
+my $countrydefault = $conf->config('countrydefault') || 'US';
+$object->set($pre.'country', $countrydefault )
+ unless $object->get($pre.'country');
+
+my $statedefault = $conf->config('statedefault')
+ || ($countrydefault eq 'US' ? 'CA' : '');
+$object->set($pre.'state', $statedefault )
+ unless $object->get($pre.'state')
+ || $object->get($pre.'country') ne $countrydefault;
+
+my @style = ();
+push @style, 'background-color: #dddddd"' if $disabled;
+
+my @address2_label_style = ();
+push @address2_label_style, 'visibility:hidden'
+ if $disabled
+ || ! $conf->exists('cust_main-require_address2')
+ || ( !$pre && !$opt{'same_checked'} );
+
+my @counties = counties( $object->get($pre.'state'),
+ $object->get($pre.'country'),
+ );
+my @county_style = ();
+push @county_style, 'visibility:hidden'
+ unless scalar(@counties) > 1;
+
+my $style =
+ scalar(@style)
+ ? 'STYLE="'. join(';', @style). '"'
+ : '';
+my $address2_label_style =
+ scalar(@address2_label_style)
+ ? 'STYLE="'. join(';', @address2_label_style). '"'
+ : '';
+my $county_style =
+ scalar(@county_style)
+ ? 'STYLE="'. join(';', @county_style). '"'
+ : '';
+
+my %select_hash = (
+ 'county' => $object->get($pre.'county'),
+ 'state' => $object->get($pre.'state'),
+ 'country' => $object->get($pre.'country'),
+ 'prefix' => $pre,
+ 'onchange' => $onchange,
+ 'disabled' => $disabled,
+ 'style' => \@style,
+);
+
+</%init>
diff --git a/httemplate/elements/mcp_lint.html b/httemplate/elements/mcp_lint.html
new file mode 100644
index 000000000..161415eff
--- /dev/null
+++ b/httemplate/elements/mcp_lint.html
@@ -0,0 +1,40 @@
+% foreach my $lint (@lint) {
+% my $color = ( $lint =~ /unchecked$/ ? '#FF9900' : '#FF0000' );
+ <FONT COLOR="<% $color %>"><% $lint %></FONT><BR>
+% }
+
+<%init>
+
+my(%opt) = @_;
+
+my $conf = new FS::Conf;
+
+my @svc = ();
+if ( $opt{svc} ) {
+ @svc = ref($opt{svc}) ? @{ $opt{svc} } : ( $opt{svc} );
+} elsif ( $opt{cust_main} ) {
+ my $custnum = $opt{cust_main}->custnum;
+ @svc = qsearchs({
+ 'table' => 'cust_svc',
+ 'addl_from' => ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'svcpart' => $conf->config('mcp_svcpart') },
+ 'extra_sql' => " AND custnum = $custnum ",
+ });
+} else {
+ die 'neither svc nor cust_main options passed to mcp_lint';
+}
+
+
+my @lint = ();
+push @lint, 'unchecked' unless @svc;
+foreach my $svc ( @svc ) {
+ my @svc_lint = tron_lint($svc);
+ if ( scalar(@svc) > 1 ) {
+ push @lint, map $svc->title.": $_", @svc_lint;
+ } else {
+ push @lint, @svc_lint;
+ }
+}
+
+</%init>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
new file mode 100644
index 000000000..627f9c857
--- /dev/null
+++ b/httemplate/elements/menu.html
@@ -0,0 +1,427 @@
+<script type="text/javascript" src="<%$fsurl%>elements/cssexpr.js"></script>
+
+% if ( $opt{'position'} eq 'top' ) {
+
+ <script type="text/javascript" src="<%$fsurl%>elements/xmenu.top.js"></script>
+ <link href="<%$fsurl%>elements/xmenu.top.css" type="text/css" rel="stylesheet">
+
+% } else { # elsif ( $opt{'position'} eq 'left' ) {
+
+ <script type="text/javascript" src="<%$fsurl%>elements/xmenu.js"></script>
+ <link href="<%$fsurl%>elements/xmenu.css" type="text/css" rel="stylesheet">
+
+% }
+
+<link href="<%$fsurl%>elements/freeside.css" type="text/css" rel="stylesheet">
+
+<SCRIPT TYPE="text/javascript">
+
+ webfxMenuImagePath = "<%$fsurl%>images/";
+ webfxMenuUseHover = 1;
+ webfxMenuShowTime = 300;
+ webfxMenuHideTime = 500;
+
+ var myBar = new WebFXMenuBar;
+
+% foreach my $item ( keys %menu ) {
+%
+% my( $url_or_submenu, $tooltip ) = @{ $menu{$item} };
+%
+% if ( ref($url_or_submenu) ) {
+%
+% #warn $item;
+%
+% my( $subhtml, $submenuname ) = submenu($url_or_submenu, $item);
+
+ <% $subhtml %>
+ myBar.add(new WebFXMenuButton("<% $item %>", null, "<% $tooltip %>", <% $submenuname %> ));
+
+% } else {
+
+ myBar.add(new WebFXMenuButton("<% $item %>", "<% $url_or_submenu %>", "<% $tooltip %>" ));
+
+% }
+%
+% }
+
+ myBar.show( null, 'vertical' );
+ myBar.width = 154;
+
+</SCRIPT>
+
+<%init>
+my( %opt ) = @_;
+my $conf = new FS::Conf;
+my $fsurl = $opt{'freeside_baseurl'};
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+#Active tickets not assigned to a customer
+
+tie my %report_customers_lists, 'Tie::IxHash',
+ 'by customer number' => [ $fsurl. 'search/cust_main.cgi?browse=custnum', '' ],
+ 'by last name' => [ $fsurl. 'search/cust_main.cgi?browse=last', '' ],
+ 'by company name' => [ $fsurl. 'search/cust_main.cgi?browse=company', '' ],
+;
+$report_customers_lists{'by active trouble tickets'} = [ $fsurl. 'search/cust_main.cgi?browse=tickets', '' ]
+ if $conf->config('ticket_system');
+
+tie my %report_customers_search, 'Tie::IxHash';
+$report_customers_search{'by ordering employee'} = [ $fsurl. 'search/cust_main-otaker.cgi' ]
+ if $curuser->access_right('Configuration');
+
+tie my %report_customers, 'Tie::IxHash';
+$report_customers{'List customers'} = [ \%report_customers_lists, 'List customers' ]
+ if $curuser->access_right('List customers');
+$report_customers{'Search customers'} = [ \%report_customers_search, 'Search customers' ]
+ if keys %report_customers_search;
+$report_customers{'Zip code distribution'} = [ $fsurl. 'search/report_cust_main-zip.html', 'Zip codes by number of customers' ];
+$report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_main.html', 'by status, signup date, agent, etc.' ]
+ if $curuser->access_right('List customers')
+ && $curuser->access_right('List packages');
+
+tie my %report_invoices_open, 'Tie::IxHash',
+ 'All open invoices' => [ $fsurl.'search/cust_bill.html?OPEN_date', 'All invoices with an unpaid balance' ],
+ '15 day open invoices' => [ $fsurl.'search/cust_bill.html?OPEN15_date', 'Invoices 15 days or older with an unpaid balance' ],
+ '30 day open invoices' => [ $fsurl.'search/cust_bill.html?OPEN30_date', 'Invoices 30 days or older with an unpaid balance' ],
+ '60 day open invoices' => [ $fsurl.'search/cust_bill.html?OPEN60_date', 'Invoices 60 days or older with an unpaid balance' ],
+ '90 day open invoices' => [ $fsurl.'search/cust_bill.html?OPEN90_date', 'Invoices 90 days or older with an unpaid balance' ],
+ '120 day open invoices' => [ $fsurl.'search/cust_bill.html?OPEN120_date', 'Invoices 120 days or older with an unpaid balance' ],
+;
+
+tie my %report_invoices, 'Tie::IxHash',
+ 'Open invoices' => [ \%report_invoices_open, 'Open invoices' ],
+ 'All invoices' => [ $fsurl. 'search/cust_bill.html?date', 'List all invoices' ],
+ 'Advanced invoice reports' => [ $fsurl.'search/report_cust_bill.html', 'by agent, date range, etc.' ],
+;
+
+tie my %report_services, 'Tie::IxHash';
+if ( $curuser->access_right('Configuration') ) {
+ $report_services{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi?orderby=active', 'Service definitions by number of active packages' ];
+ $report_services{'separator'} = '';
+}
+foreach my $svcdb ( FS::part_svc->svc_tables() ) {
+
+ my $name = "FS::$svcdb"->table_info->{'name_plural'}
+ || PL( "FS::$svcdb"->table_info->{'name'} );
+ my $lcname = lc($name);
+ my $lcsname = lc("FS::$svcdb"->table_info->{'name'});
+ my $longname = "FS::$svcdb"->table_info->{'longname_plural'} || $name;
+ my $lclongname = lc($longname);
+ my $sorts = "FS::$svcdb"->table_info->{'sorts'} || [ 'svcnum' ];
+ $sorts = [ $sorts ] unless ref($sorts);
+ my %svc_url = ( 'm' => $m,
+ 'action' => 'search',
+ 'svcdb' => $svcdb,
+ );
+
+ tie my %report_svc, 'Tie::IxHash';
+
+ foreach my $sort ( @$sorts ) {
+
+ my $field_info = FS::part_svc->svc_table_fields($svcdb)->{$sort};
+ my $label = $field_info->{'label_sort'} || 'by '.$field_info->{'label'};
+
+ my $title = "All $lcname";
+ $title .= " $label"
+ if scalar(@$sorts) > 1;
+
+ $report_svc{$title} =
+ [ svc_url( %svc_url, 'query' => "magic=all;sortby=$sort" ),
+ '',
+ ];
+ }
+
+ if ( $svcdb eq 'svc_acct' ) {
+ $report_svc{"All $lcname never logged in"} =
+ [ svc_url( %svc_url, 'query' => "magic=nologin;sortby=svcnum" ),
+ '',
+ ];
+ }
+
+ if ( $curuser->access_right('View/link unlinked services') ) {
+ $report_svc{"Unlinked $lcname"} =
+ [ svc_url( %svc_url, 'query' => "magic=unlinked;sortby=". $sorts->[0] ),
+ "Pre-Freeside $lcname without a customer record",
+ ];
+ }
+
+ if ( $svcdb eq 'svc_acct' ) {
+ $report_svc{"Advanced $lcsname reports"} =
+ [ $fsurl."search/report_$svcdb.html", '' ];
+ }
+
+ $report_services{$name} = [ \%report_svc, $longname ];
+
+}
+
+tie my %report_packages, 'Tie::IxHash';
+if ( $curuser->access_right('Edit package definitions')
+ || $curuser->access_right('Edit global package definitions')
+ )
+{
+ $report_packages{'Package definitions'} = [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ];
+ $report_packages{'separator'} = '';
+}
+if ( $curuser->access_right('Financial reports') ) {
+ $report_packages{'Package churn'} = [ $fsurl.'graph/report_cust_pkg.html', 'Orders, suspensions and cancellations summary graph' ];
+ $report_packages{'separator2'} = '';
+}
+$report_packages{'All customer packages'} = [ $fsurl.'search/cust_pkg.cgi?pkgnum', 'List all customer packages', ];
+$report_packages{'Suspended customer packages'} = [ $fsurl.'search/cust_pkg.cgi?magic=suspended', 'List suspended packages' ];
+$report_packages{'Customer packages with unconfigured services'} = [ $fsurl.'search/cust_pkg.cgi?APKG_pkgnum', 'List packages which have provisionable services' ];
+$report_packages{'Advanced package reports'} = [ $fsurl.'search/report_cust_pkg.html', 'by agent, date range, status, package definition' ];
+
+tie my %report_rating, 'Tie::IxHash',
+ 'RADIUS sessions' => [ $fsurl.'search/sqlradius.html', '' ],
+ 'Call Detail Records (CDRs)' => [ $fsurl.'search/report_cdr.html', '' ],
+ 'Time worked' => [ $fsurl.'search/report_rt_transaction.html', '' ],
+;
+
+tie my %report_bill_event, 'Tie::IxHash',
+ 'All billing events' => [ $fsurl.'search/report_cust_event.html', 'All billing events for a date range' ],
+ 'Billing event errors' => [ $fsurl.'search/report_cust_event.html?failed=1', 'Failed credit cards, processor or printer problems, etc.' ],
+ 'All invoice events' => [ $fsurl.'search/cust_bill_event.html', 'Reports on deprecated, old-style invoice events for a date range' ],
+ 'Invoice event errors' => [ $fsurl.'search/cust_bill_event.html?failed=1', 'Reports on deprecated, old-style events for failed credit cards, processor or printer problems, etc.' ],
+;
+
+tie my %report_financial, 'Tie::IxHash',
+ 'Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time.html', 'Sales, credits and receipts summary graph' ],
+ 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ],
+ 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ],
+ 'Payment Report' => [ $fsurl.'search/report_cust_pay.html', 'Payment report (by type and/or date range)' ],
+;
+$report_financial{'Pending Payment Report'} = [ $fsurl.'search/cust_pay_pending.html?magic=_date;statusNOT=done', 'Pending real-time payments' ]
+ if $curuser->access_right('View customer pending payments');
+$report_financial{'Payment Batch Report'} = [ $fsurl.'search/pay_batch.html', 'Payment batches (by status and/or date range)' ]
+ if $conf->exists('batch-enable') || $conf->config('batch-enable_payby');
+$report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ];
+$report_financial{'Prepaid Income'} = [ $fsurl.'search/report_prepaid_income.html', 'Prepaid income (unearned revenue) report' ];
+$report_financial{'Sales Tax Liability'} = [ $fsurl.'search/report_tax.html', 'Sales tax liability report (old taxclass system)' ];
+$report_financial{'Tax Liability'} = [ $fsurl.'search/report_newtax.html', 'Tax liability report (new tax products system)' ]
+ if $conf->exists('enable_taxproducts');
+;
+
+tie my %report_menu, 'Tie::IxHash';
+$report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ]
+ if $curuser->access_right('List customers');
+$report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ]
+ if $curuser->access_right('List invoices');
+$report_menu{'Packages'} = [ \%report_packages, 'Package reports' ]
+ if $curuser->access_right('List packages');
+$report_menu{'Services'} = [ \%report_services, 'Services reports' ]
+ if $curuser->access_right('List services');
+$report_menu{'Usage'} = [ \%report_rating, 'Usage reports' ]
+ if $curuser->access_right('List rating data');
+$report_menu{'Billing events'} = [ \%report_bill_event, 'Billing events' ]
+ if $curuser->access_right('Billing event reports');
+$report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ]
+ if $curuser->access_right('Financial reports');
+$report_menu{'SQL Query'} = [ $fsurl.'search/report_sql.html', 'SQL Query' ]
+ if $curuser->access_right('Raw SQL');
+
+tie my %tools_importing, 'Tie::IxHash',
+ 'Import customers' => [ $fsurl.'misc/cust_main-import.cgi', '' ],
+ 'Import customer comments from CSV file' => [ $fsurl.'misc/cust_main_note-import.html', '' ],
+ 'Import one-time charges from CSV file' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
+ 'Import payments from CSV file' => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
+ 'Import phone numbers (DIDs)' => [ $fsurl.'misc/phone_avail-import.html', '' ],
+ 'Import Call Detail Records (CDRs) from CSV file' => [ $fsurl.'misc/cdr-import.html', '' ],
+ 'Import tax rates from CSV files' => [ $fsurl.'misc/tax-import.cgi', '' ],
+;
+
+tie my %tools_exporting, 'Tie::IxHash',
+ 'Download database dump' => [ $fsurl. 'misc/dump.cgi', '' ],
+;
+
+# <!-- <BR>View active NAS ports:
+# <A HREF="browse/nas.cgi">session server</A> -->
+# <!-- or <A HREF="browse/nas-sqlradius.cgi">RADIUS</A>
+# <BR> -->
+
+tie my %tools_menu, 'Tie::IxHash', ();
+$tools_menu{'Quick payment entry'} = [ $fsurl.'misc/batch-cust_pay.html', 'Enter multiple payments in a batch' ]
+ if $curuser->access_right('Post payment batch');
+$tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_date;open=1;intransit=1', 'Process credit card and electronic check batches' ]
+ if ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
+ && $curuser->access_right('Process batches');
+$tools_menu{'Job Queue'} = [ $fsurl.'search/queue.html', 'View pending job queue' ]
+ if $curuser->access_right('Job queue');
+$tools_menu{'Time Queue'} = [ $fsurl.'search/timeworked.html', 'View pending support time' ]
+ if $curuser->access_right('Time queue');
+$tools_menu{'Importing'} = [ \%tools_importing, 'Import tools' ]
+ if $curuser->access_right('Import');
+$tools_menu{'Exporting'} = [ \%tools_exporting, 'Export tools' ]
+ if $curuser->access_right('Export');
+
+tie my %config_employees, 'Tie::IxHash',
+ 'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ],
+ 'View/Edit employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ],
+;
+
+tie my %config_export_svc_pkg, 'Tie::IxHash', ();
+if ( $curuser->access_right('Configuration') ) {
+ $config_export_svc_pkg{'View/Edit exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ];
+ $config_export_svc_pkg{'View/Edit service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ];
+}
+$config_export_svc_pkg{'View/Edit package definitions'} = [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ]
+ if $curuser->access_right('Edit package definitions')
+ || $curuser->access_right('Edit global package definitions');
+if ( $curuser->access_right('Configuration') ) {
+ $config_export_svc_pkg{'View/Edit package categories'} = [ $fsurl.'browse/pkg_category.html', 'Package categories define groups of package classes, for reporting and convenience purposes.' ];
+ $config_export_svc_pkg{'View/Edit package classes'} = [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ];
+ $config_export_svc_pkg{'View/Edit cancel reason types'} = [ $fsurl.'browse/reason_type.html?class=C', 'Cancel reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_export_svc_pkg{'View/Edit cancel reasons'} = [ $fsurl.'browse/reason.html?class=C', 'Cancel reasons explain why a service was cancelled.' ];
+ $config_export_svc_pkg{'View/Edit suspend reason types'} = [ $fsurl.'browse/reason_type.html?class=S', 'Suspend reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_export_svc_pkg{'View/Edit suspend reasons'} = [ $fsurl.'browse/reason.html?class=S', 'Suspend reasons explain why a service was suspended.' ];
+}
+
+tie my %config_agent, 'Tie::IxHash',
+ 'View/Edit agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ],
+ 'View/Edit agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ],
+ 'View/Edit agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ];
+;
+
+tie my %config_billing_rates, 'Tie::IxHash',
+ 'View/Edit rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ],
+ 'View/Edit regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ],
+ 'View/Edit usage classes' => [ $fsurl.'browse/usage_class.html', 'Usage classes define groups of usage for taxation purposes.' ],
+;
+
+tie my %config_billing, 'Tie::IxHash';
+# 'View/Edit payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ];
+$config_billing{'View/Edit billing events'} = [ $fsurl.'browse/part_event.html', 'Billing actions for customers, invoices and packages' ]
+ if $curuser->access_right('Edit billing events')
+ || $curuser->access_right('Edit global billing events');
+if ( $curuser->access_right('Configuration') ) {
+ $config_billing{'View/Edit invoice events'} = [ $fsurl.'browse/part_bill_event.cgi', 'Deprecated, old-style actions for overdue invoices' ];
+ $config_billing{'View/Edit invoice templates'} = [ $fsurl.'browse/invoice_template.html', 'Edit templates for HTML, plaintext and typeset invoices' ];
+ $config_billing{'View/Edit prepaid cards'} = [ $fsurl.'search/prepay_credit.html', 'View outstanding cards, generate new cards' ];
+ $config_billing{'View/Edit call rates and regions'} = [ \%config_billing_rates, 'Manage rate plans, regions and prefixes for VoIP and call billing' ];
+ $config_billing{'View/Edit locales and tax rates (old tax class system)'} = [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ];
+ $config_billing{'View/Edit tax rates (new tax products system)'} = [ $fsurl.'browse/tax_rate.cgi', 'Edit tax rates for the new tax products system' ];
+ $config_billing{'View/Edit credit reason types'} = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons, for reporting and convenience purposes.' ];
+ $config_billing{'View/Edit credit reasons'} = [ $fsurl.'browse/reason.html?class=R', 'Credit reasons explain why a credit was issued.' ];
+}
+
+tie my %config_dialup, 'Tie::IxHash',
+ 'View/Edit access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ],
+;
+
+tie my %config_broadband, 'Tie::IxHash',
+ 'View/Edit routers' => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ],
+ 'View/Edit address blocks' => [ $fsurl.'browse/addr_block.cgi', 'Manage address blocks and block assignments to broadband routers' ],
+;
+
+tie my %config_misc, 'Tie::IxHash';
+$config_misc{'View/Edit advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service. Tracked for informational purposes' ]
+ if $curuser->access_right('Edit advertising sources')
+ || $curuser->access_right('Edit global advertising sources');
+if ( $curuser->access_right('Configuration') ) {
+ $config_misc{'View/Edit virtual fields'} = [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ];
+ $config_misc{'View/Edit message catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ];
+ $config_misc{'View/Edit inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ];
+}
+
+tie my %config_menu, 'Tie::IxHash';
+if ( $curuser->access_right('Configuration' ) ) {
+ %config_menu = (
+ 'Settings' => [ $fsurl.'config/config-view.cgi', '' ],
+ 'separator' => '', #its a separator!
+ 'Employees' => [ \%config_employees, '' ],
+ );
+}
+$config_menu{'Provisioning, services and packages'} =
+ [ \%config_export_svc_pkg, '' ]
+ if $curuser->access_right('Configuration' )
+ || $curuser->access_right('Edit package definitions')
+ || $curuser->access_right('Edit global package definitions');
+$config_menu{'Resellers'} = [ \%config_agent, '' ]
+ if $curuser->access_right('Configuration');
+$config_menu{'Billing'} = [ \%config_billing, '' ]
+ if $curuser->access_right('Edit billing events')
+ || $curuser->access_right('Edit global billing events');
+$config_menu{'Dialup'} = [ \%config_dialup, '' ]
+ if ( $curuser->access_right('Dialup configuration') );
+$config_menu{'Fixed (username-less) broadband'} = [ \%config_broadband, '' ]
+ if ( $curuser->access_right('Broadband configuration') );
+$config_menu{'Miscellaneous'} = [ \%config_misc, '' ]
+ if $curuser->access_right('Edit advertising sources')
+ || $curuser->access_right('Edit global advertising sources');
+
+tie my %menu, 'Tie::IxHash',
+ 'Billing Main' => [ $fsurl, 'Billing start page', ],
+;
+if ( $conf->config('ticket_system') ) {
+ $menu{'Ticketing Main'} =
+ [
+ ( $conf->config('ticket_system') eq 'RT_External'
+ ? FS::TicketSystem->baseurl()
+ : $fsurl.'rt/'
+ ),
+ 'Ticketing start page',
+ ],
+}
+$menu{'Reports'} = [ \%report_menu, 'Lists, reporting and graphing' ]
+ if keys %report_menu;
+$menu{'Tools'} = [ \%tools_menu, 'Tools' ]
+ if keys %tools_menu;
+$menu{'Configuration'} = [ \%config_menu, 'Configuraiton and setup' ]
+ if $curuser->access_right('Configuration')
+ || $curuser->access_right('Edit package definitions')
+ || $curuser->access_right('Edit global package definitions')
+ || $curuser->access_right('Edit billing events')
+ || $curuser->access_right('Edit global billing events')
+ || $curuser->access_right('Dialup configuration')
+ || $curuser->access_right('Broadband configuration')
+ || $curuser->access_right('Edit advertising sources')
+ || $curuser->access_right('Edit global advertising sources');
+
+use vars qw($gmenunum);
+$gmenunum = 0;
+
+sub submenu {
+ my($submenu, $title) = @_;
+ my $menunum = $gmenunum++;
+
+ #return two args: html, menuname
+
+ "var myMenu$menunum = new WebFXMenu;\n".
+ #"myMenu$menunum.useAutoPosition = true;\n".
+ "myMenu$menunum.emptyText = '$title';\n".
+
+ (
+ join("\n", map {
+
+ if ( !ref( $submenu->{$_} ) ) {
+
+ "myMenu$menunum.add(new WebFXMenuSeparator());";
+
+ } else {
+
+ my($url_or_submenu, $tooltip ) = @{ $submenu->{$_} };
+ if ( ref($url_or_submenu) ) {
+
+ my($subhtml, $submenuname ) = submenu($url_or_submenu, $_); #mmm, recursion
+
+ "$subhtml\n".
+ "myMenu$menunum.add(new WebFXMenuItem(\"$_\", null, \"$tooltip\", $submenuname ));";
+
+ } else {
+
+ "myMenu$menunum.add(new WebFXMenuItem(\"$_\", \"$url_or_submenu\", \"$tooltip\" ));";
+
+ }
+
+ }
+
+ } keys %$submenu )
+ ). "\n".
+ "myMenu$menunum.width = 280;\n",
+
+ "myMenu$menunum";
+
+}
+
+</%init>
+
diff --git a/httemplate/elements/menubar.html b/httemplate/elements/menubar.html
new file mode 100644
index 000000000..ec6c13fea
--- /dev/null
+++ b/httemplate/elements/menubar.html
@@ -0,0 +1,10 @@
+%
+% my($item, $url, @html);
+% while (@_) {
+% ($item, $url) = splice(@_,0,2);
+% next if $item =~ /^\s*Main\s+Menu\s*$/i;
+% push @html, qq!<A HREF="$url">$item</A>!;
+% }
+%
+
+<% join(' | ', @html) %>
diff --git a/httemplate/elements/overlibmws.js b/httemplate/elements/overlibmws.js
new file mode 100644
index 000000000..df2bd1db7
--- /dev/null
+++ b/httemplate/elements/overlibmws.js
@@ -0,0 +1,620 @@
+/*
+ Do not remove or change this notice.
+ overlibmws.js core module - Copyright Foteos Macrides 2002-2008. All rights reserved.
+ Initial: August 18, 2002 - Last Revised: March 22, 2008
+ This module is subject to the same terms of usage as for Erik Bosrup's overLIB,
+ though only a minority of the code and API now correspond with Erik's version.
+ See the overlibmws Change History and Command Reference via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+ Give credit on sites that use overlibmws and submit changes so others can use them as well.
+ You can get Erik's version via: http://www.bosrup.com/web/overlib/
+*/
+
+// PRE-INIT -- Ignore these lines, configuration is below.
+var OLloaded=0,OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0,
+OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLmodalPI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0,OLprintPI=0,
+pmCnt=1,pMtr=new Array(),OLcmdLine=new Array(),OLrunTime=new Array(),OLv,OLudf,OLrefXY,
+OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%");if(typeof OLgateOK=='undefined')var OLgateOK=1;
+var OLp1or2c='inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,pady,below,above,vcenter,donothing',
+OLp1or2co='nofollow,background,offsetx,offsety,fgcolor,bgcolor,cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,'
++'base,status,autostatus,snapx,snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
++'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,vauto,nojustx,nojusty,fgclass,'
++'bgclass,cgclass,capbelow,textpadding,textfontclass,captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,'
++'closecolor,closefont,closesize,closeclick,closetitle,closefontclass,decode',OLp1or2o='text,cap,close,hpos,vpos,padxl,'
++'padxr,padyt,padyb',OLp1co='label',OLp1or2=OLp1or2co+','+OLp1or2o,OLp1=OLp1co+','+'frame';
+OLregCmds(OLp1or2c+','+OLp1or2co+','+OLp1co);
+function OLud(v){return eval('typeof ol_'+v+'=="undefined"')?1:0;}
+
+// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions
+if(OLud('fgcolor'))var ol_fgcolor="#ccccff";
+if(OLud('bgcolor'))var ol_bgcolor="#333399";
+if(OLud('cgcolor'))var ol_cgcolor="#333399";
+if(OLud('textcolor'))var ol_textcolor="#000000";
+if(OLud('capcolor'))var ol_capcolor="#ffffff";
+if(OLud('closecolor'))var ol_closecolor="#eeeeff";
+if(OLud('textfont'))var ol_textfont="Verdana,Arial,Helvetica";
+if(OLud('captionfont'))var ol_captionfont="Verdana,Arial,Helvetica";
+if(OLud('closefont'))var ol_closefont="Verdana,Arial,Helvetica";
+if(OLud('textsize'))var ol_textsize=1;
+if(OLud('captionsize'))var ol_captionsize=1;
+if(OLud('closesize'))var ol_closesize=1;
+if(OLud('fgclass'))var ol_fgclass="";
+if(OLud('bgclass'))var ol_bgclass="";
+if(OLud('cgclass'))var ol_cgclass="";
+if(OLud('textpadding'))var ol_textpadding=2;
+if(OLud('textfontclass'))var ol_textfontclass="";
+if(OLud('captionpadding'))var ol_captionpadding=2;
+if(OLud('captionfontclass'))var ol_captionfontclass="";
+if(OLud('closefontclass'))var ol_closefontclass="";
+if(OLud('close'))var ol_close="Close";
+if(OLud('closeclick'))var ol_closeclick=0;
+if(OLud('closetitle'))var ol_closetitle="Click to Close";
+if(OLud('text'))var ol_text="Default Text";
+if(OLud('cap'))var ol_cap="";
+if(OLud('capbelow'))var ol_capbelow=0;
+if(OLud('background'))var ol_background="";
+if(OLud('width'))var ol_width=200;
+if(OLud('wrap'))var ol_wrap=0;
+if(OLud('wrapmax'))var ol_wrapmax=0;
+if(OLud('height'))var ol_height= -1;
+if(OLud('border'))var ol_border=1;
+if(OLud('base'))var ol_base=0;
+if(OLud('offsetx'))var ol_offsetx=10;
+if(OLud('offsety'))var ol_offsety=10;
+if(OLud('sticky'))var ol_sticky=0;
+if(OLud('nofollow'))var ol_nofollow=0;
+if(OLud('noclose'))var ol_noclose=0;
+if(OLud('mouseoff'))var ol_mouseoff=0;
+if(OLud('offdelay'))var ol_offdelay=300;
+if(OLud('hpos'))var ol_hpos=RIGHT;
+if(OLud('vpos'))var ol_vpos=BELOW;
+if(OLud('status'))var ol_status="";
+if(OLud('autostatus'))var ol_autostatus=0;
+if(OLud('snapx'))var ol_snapx=0;
+if(OLud('snapy'))var ol_snapy=0;
+if(OLud('fixx'))var ol_fixx= -1;
+if(OLud('fixy'))var ol_fixy= -1;
+if(OLud('relx'))var ol_relx=null;
+if(OLud('rely'))var ol_rely=null;
+if(OLud('midx'))var ol_midx=null;
+if(OLud('midy'))var ol_midy=null;
+if(OLud('ref'))var ol_ref="";
+if(OLud('refc'))var ol_refc='UL';
+if(OLud('refp'))var ol_refp='UL';
+if(OLud('refx'))var ol_refx=0;
+if(OLud('refy'))var ol_refy=0;
+if(OLud('fgbackground'))var ol_fgbackground="";
+if(OLud('bgbackground'))var ol_bgbackground="";
+if(OLud('cgbackground'))var ol_cgbackground="";
+if(OLud('padxl'))var ol_padxl=1;
+if(OLud('padxr'))var ol_padxr=1;
+if(OLud('padyt'))var ol_padyt=1;
+if(OLud('padyb'))var ol_padyb=1;
+if(OLud('fullhtml'))var ol_fullhtml=0;
+if(OLud('capicon'))var ol_capicon="";
+if(OLud('frame'))var ol_frame=self;
+if(OLud('timeout'))var ol_timeout=0;
+if(OLud('delay'))var ol_delay=0;
+if(OLud('hauto'))var ol_hauto=0;
+if(OLud('vauto'))var ol_vauto=0;
+if(OLud('nojustx'))var ol_nojustx=0;
+if(OLud('nojusty'))var ol_nojusty=0;
+if(OLud('label'))var ol_label="";
+if(OLud('decode'))var ol_decode=0;
+// ARRAY CONFIGURATION - See overlibConfig.txt for descriptions.
+if(OLud('texts'))var ol_texts=new Array("Text 0","Text 1");
+if(OLud('caps'))var ol_caps=new Array("Caption 0","Caption 1");
+// END CONFIGURATION -- Don't change anything below, all configuration is above.
+
+// INIT -- Runtime variables.
+var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0,o3_offdelay=300,o3_hpos=RIGHT,
+o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="",o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",
+o3_width=200,o3_wrap=0,o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0,o3_snapy=0,
+o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null,o3_ref="",o3_refc='UL',o3_refp='UL',o3_refx=0,
+o3_refy=0,o3_fgbackground="",o3_bgbackground="",o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,
+o3_vpos=BELOW,o3_capicon="",o3_textfont="Verdana,Arial,Helvetica",o3_captionfont="",o3_closefont="",o3_textsize=1,OLcC=null,
+o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0,o3_hauto=0,o3_vauto=0,o3_nojustx=0,o3_nojusty=0,
+o3_close="",o3_closeclick=0,o3_closetitle="",o3_fgclass="",o3_bgclass="",o3_cgclass="",o3_textpadding=2,o3_textfontclass="",
+o3_captionpadding=2,o3_captionfontclass="",o3_closefontclass="",o3_capbelow=0,o3_label="",o3_decode=0,
+CSSOFF=DONOTHING,CSSCLASS=DONOTHING,over=null,OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0,OLfnRef="",OLhover=0,OLx=0,OLy=0,
+OLshowingsticky=0,OLallowmove=0,OLoverHTML="",OLover2HTML="",OLifRef="",OLo2Ref="",OLifX=0,OLifY=0,
+OLua=(OLv=navigator.userAgent)?OLv.toLowerCase():'',
+OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4)?1:0,
+OLns6=(document.getElementById)?1:0,
+OLie4=(document.all)?1:0,
+OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0,
+OLmac=(OLua.indexOf('mac')>=0)?1:0,
+OLsaf=(OLua.indexOf('safari')>=0)?1:0,
+OLkon=(OLua.indexOf('konqueror')>=0)?1:0,
+OLkht=(OLsaf||OLkon)?1:0,
+OLopr=(OLua.indexOf('opera')>=0)?1:0,
+OLop7=(OLopr&&document.createTextNode)?1:0;
+if(OLopr){OLns4=OLns6=OLgek=0;OLie4=(OLop7)?1:0;}
+var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0,
+OLie5=0,OLie55=0;OLie7=0;if(OLie4&&!OLop7){
+if((OLv=OLua.match(/msie (\d\.\d+)\.*/i))&&(OLv=parseFloat(OLv[1]))>=5.0){
+OLie5=1;OLns6=0;if(OLv>=5.5)OLie55=1;if(OLv>=7.0)OLie7=1;}if(OLns6)OLie4=0;}
+if(OLns4)window.onresize=function(){location.reload();};var OLchkMh=1,OLdw;
+if(OLns4||OLie4||OLns6){OLmh();if(window.addEventListener)window.addEventListener("unload",
+OLulCl,false);}else{overlib=nd=cClick=OLpageDefaults=no_overlib;}
+function OLulCl(){if(over)cClick();window.removeEventListener("unload",OLulCl,false);}
+
+/*
+ PUBLIC FUNCTIONS
+*/
+// Loads defaults then args into runtime variables.
+function overlib(){
+if(!(OLloaded&&OLgateOK))return;if((OLexclusivePI)&&OLisExclusive(arguments))return true;if(OLchkMh)OLmh();
+if(OLndt&&!OLtimerid)OLndt=0;if(over)cClick();if(parent!=self){if(parent.OLo2Ref){parent.OLeval(parent.OLo2Ref);
+parent.OLo2Ref="";}if(parent.OLifRef){parent.OLeval(parent.OLifRef);parent.OLifRef="";}}if(OLo2Ref){eval(OLo2Ref);
+OLo2Ref="";}if(OLifRef){eval(OLifRef);OLifRef="";}OLload(OLp1or2);OLload(OLp1);OLfnRef="";OLifX=0;OLifY=0;OLhover=0;
+OLsetRunTimeVar();OLparseTokens('o3_',arguments);if(!(over=OLmkLyr()))return false;if(o3_decode)OLdecode();if(OLprintPI)
+OLchkPrint();if(OLbubblePI)OLchkForBubbleEffect();if(OLdebugPI)OLsetDebugCanShow();if(OLshadowPI)OLinitShadow();
+if(OLiframePI)OLinitIfs();if(OLfilterPI)OLinitFilterLyr();if(OLexclusivePI&&o3_exclusive&&o3_exclusivestatus!="")
+o3_status=o3_exclusivestatus;else if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;else if(o3_autostatus==1&&o3_text!="")
+o3_status=o3_text;if(!o3_delay){return OLmain();}else{OLdelayid=setTimeout("OLmain()",o3_delay);if(o3_status!=""){
+self.status=o3_status;return true;}else if(!(OLop7&&event&&event.type=='mouseover'))return false;}
+}
+function OLeval(s){eval(s);}
+
+// Clears popups if appropriate
+function nd(time){
+if(OLloaded&&OLgateOK){if(!((OLexclusivePI)&&OLisExclusive())){if(time&&over&&!o3_delay){
+if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=(OLhover&&o3_frame==self&&!OLcursorOff())?0:
+setTimeout("cClick()",(o3_timeout=OLndt=time));}else{if(!OLshowingsticky){OLallowmove=0;
+if(over)OLhideObject(over);}}}}return false;
+}
+
+// Close function for stickies
+function cClick(){
+if(OLloaded&&OLgateOK){OLhover=0;if(over){if(OLo2Ref){eval(OLo2Ref);OLo2Ref="";}if(OLovertwoPI&&over==over2)cClick2();
+OLhideObject(over);OLshowingsticky=0;OLallowmove=0;}if(OLmodalPI)OLclearModal();}return false;
+}
+
+// Sets page-specific defaults.
+function OLpageDefaults(){
+OLparseTokens('ol_',arguments);
+}
+
+// Gets object referenced by its id or name
+function OLgetRef(l,d){var r=OLgetRefById(l,d);return (r)?r:OLgetRefByName(l,d);}
+
+// For unsupported browsers.
+function no_overlib(){return false;}
+
+/*
+ OVERLIB MAIN FUNCTION SET
+*/
+function OLmain(){
+o3_delay=0;if(parent!=self&&o3_frame==parent&&parent.OLscrollPI&&parent.over)parent.OLclearScroll();if(o3_frame==self){
+if(o3_noclose)OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);}if(o3_sticky){OLshowingsticky=1;if(OLfnRef&&
+parent!=self&&o3_frame==parent&&parent.overlib){parent.OLifRef=OLfnRef+'cClick()';}}OLdoLyr();OLallowmove=0;if(o3_timeout>0){
+if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_timeout);}OLchkRef();OLdisp(o3_status);
+if(OLdraggablePI)OLcheckDrag();if(o3_status!="")return true;else if(!(OLop7&&event&&event.type=='mouseover'))return false;
+}
+function OLchkRef(){
+if(o3_ref){OLrefXY=OLgetRefXY(o3_ref);if(OLrefXY[0]==null&&OLcrossframePI)OLchkIfRef();
+if(OLrefXY[0]==null){o3_ref="";o3_midx=0;o3_midy=0;}}
+}
+
+// Loads o3_ variables
+function OLload(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=ol_'+m[i]);}
+
+// Chooses LGF
+function OLdoLGF(){
+return (o3_background!=''||o3_fullhtml)?OLcontentBackground(o3_text,o3_background,o3_fullhtml):(o3_cap=="")?
+OLcontentSimple(o3_text):(o3_sticky)?OLcontentCaption(o3_text,o3_cap,o3_close):OLcontentCaption(o3_text,o3_cap,'');
+}
+
+// Makes Layer
+function OLmkLyr(id,f,z){
+id=(id||'overDiv');f=(f||o3_frame);z=(z||1000);var fd=f.document,d=OLgetRefById(id,fd);
+if(!d){if(OLns4)d=fd.layers[id]=new Layer(1024,f);else if(OLie4&&!OLop7){
+fd.body.insertAdjacentHTML('AfterBegin','<div id="'+id+'"></div>');d=fd.all[id];}else{d=fd.createElement('div');
+if(d){d.id=id;fd.body.appendChild(d);}}if(!d)return null;if(OLns4)d.zIndex=z;else{var o=d.style;o.position='absolute';
+o.visibility='hidden';o.zIndex=z;}}return d;
+}
+
+// Creates and writes layer content
+function OLdoLyr(){
+if(o3_sticky&&OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}if(o3_background==''&&!o3_fullhtml){
+if(o3_fgbackground!='')o3_fgbackground=' background="'+o3_fgbackground+'"';
+if(o3_bgbackground!='')o3_bgbackground=' background="'+o3_bgbackground+'"';
+if(o3_cgbackground!='')o3_cgbackground=' background="'+o3_cgbackground+'"';
+if(o3_fgcolor!='')o3_fgcolor=' bgcolor="'+o3_fgcolor+'"';if(o3_bgcolor!='')o3_bgcolor=' bgcolor="'+o3_bgcolor+'"';
+if(o3_cgcolor!='')o3_cgcolor=' bgcolor="'+o3_cgcolor+'"';if(o3_height>0)o3_height=' height="'+o3_height+'"';
+else o3_height='';}if(!OLns4)OLrepositionTo(over,(OLns6?20:0),0);var lyrHtml=OLdoLGF();
+if(o3_wrap&&!o3_fullhtml){OLlayerWrite(lyrHtml);o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLie4){
+var w=OLfd().clientWidth;if(o3_width>=w){if(OLop7){if(OLovertwoPI&&over==over2){var z=over2.style.zIndex;
+o3_frame.document.body.removeChild(over);over2=OLmkLyr('overDiv2',o3_frame,z);over=over2;}else{
+o3_frame.document.body.removeChild(over);over=OLmkLyr();}}o3_width=w-20;}}
+if(o3_wrapmax<1&&o3_frame.innerWidth)o3_wrapmax=o3_frame.innerWidth-40;
+if(o3_wrapmax>0&&o3_width>o3_wrapmax)o3_width=o3_wrapmax;o3_wrap=0;lyrHtml=OLdoLGF();}OLlayerWrite(lyrHtml);
+o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLbubblePI)OLgenerateBubble(lyrHtml);
+}
+
+/*
+ LAYER GENERATION FUNCTIONS
+*/
+// Makes simple table without caption
+function OLcontentSimple(txt){
+var t=OLbgLGF()+OLfgLGF(txt)+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// Makes table with caption and optional close link
+function OLcontentCaption(txt,title,close){
+var closing=(OLprintPI?OLprintCapLGF():''),closeevent='onmouseover',caption,t,cC='javascript:return '+OLfnRef
++(OLovertwoPI&&over==over2?'cClick2();':'cClick();');if(o3_closeclick)closeevent=(o3_closetitle?'title="'
++o3_closetitle+'" ':'')+'onclick';if(o3_capicon!=''&&o3_capicon.indexOf('<img')!=0)o3_capicon='<img src="'+o3_capicon
++'" /> ';if(close){closing+='<td align="right"><a href="'+cC+'" '+closeevent+'="'+cC+'"'+(o3_closefontclass?' class="'
++o3_closefontclass+'">':(OLns4?'><':'')+OLlgfUtil(0,1,'','a',o3_closecolor,o3_closefont,o3_closesize))+close+
+(o3_closefontclass?'':(OLns4?OLlgfUtil(1,1,'','a'):''))+'</a></td>';}caption='<table id="overCap'
++(OLovertwoPI&&over==over2?'2':'')+'"'+OLwd(0)+' border="0" cellpadding="'+o3_captionpadding+'" cellspacing="0"'
++(o3_cgclass?' class="'+o3_cgclass+'"':o3_cgcolor+o3_cgbackground)+'><tr><td'+OLwd(0)+(o3_cgclass?' class="'
++o3_cgclass+'">':'>')+(o3_captionfontclass?'<div'+OLhL(1)+' class="'+o3_captionfontclass+'">':OLlgfUtil(0,1,'','div',
+o3_capcolor,o3_captionfont,o3_captionsize))+o3_capicon+title+OLlgfUtil(1,1,'','div')+'</td>'+closing+'</tr></table>';
+t=OLbgLGF()+(o3_capbelow?OLfgLGF(txt)+caption:caption+OLfgLGF(txt))+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// For BACKGROUND and FULLHTML commands
+function OLcontentBackground(txt,image,hasfullhtml){
+var t;if(hasfullhtml){t=txt;}else{t='<table'+OLwd(1)+' border="0" cellpadding="0" '+'cellspacing="0" '+'height="'
++o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="top"'
++OLwd(2)+'>'+OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+OLlgfUtil(1,0,'','div')
++'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';}
+OLsetBackground(image);return t;
+}
+
+// LGF utilities
+function OLbgLGF(){
+return '<table'+OLwd(1)+o3_height+' border="0" cellpadding="'+o3_border+'" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':o3_bgcolor+o3_bgbackground)+'><tr><td>';
+}
+function OLfgLGF(t){
+return '<table'+OLwd(0)+o3_height+' border="0" cellpadding="'+o3_textpadding+'" cellspacing="0"'+(o3_fgclass?' class="'
++o3_fgclass+'"':o3_fgcolor+o3_fgbackground)+'><tr><td valign="top"'+(o3_fgclass?' class="'+o3_fgclass+'"':'')+'>'
++OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t+(OLprintPI?OLprintFgLGF():'')
++OLlgfUtil(1,0,'','div')+'</td></tr></table>';
+}
+function OLlgfUtil(end,stg,tfc,ele,col,fac,siz){
+if(end)return('</'+(OLns4?'font'+(stg?'></strong':''):ele)+'>');else return(tfc?'<div'+OLhL(1)+' class="'+tfc+'">':
+((ele=='a'?'':'<')+(OLns4?(stg?'strong><':'')+'font color="'+col+'" face="'+OLquoteMultiNameFonts(fac)+'" size="'
++siz:(ele=='a'?'':ele)+' style="'+((ele=='div')?OLhL(0):'')+'color:'+col+(stg?';font-weight:bold':'')+';font-family:'
++OLquoteMultiNameFonts(fac)+';font-size:'+siz+';'+(ele=='span'?'text-decoration:underline;':''))+'">'));
+}
+function OLquoteMultiNameFonts(f){
+var i,v,pM=f.split(',');for(i=0;i<pM.length;i++){v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');
+if(/\s/.test(v) && !/['"]/.test(v)){v="\'"+v+"\'";pM[i]=v;}}return pM.join();
+}
+function OLbaseLGF(){
+return ((o3_base>0&&!o3_wrap)?('<table width="100%" border="0" cellpadding="0" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':'')+'><tr><td height="'+o3_base+'"></td></tr></table>'):'')+'</td></tr></table>';
+}
+function OLwd(a){return(o3_wrap?'':' width="'+(!a?'100%':(a==1?o3_width:(o3_width-o3_padxl-o3_padxr)))+'"');}
+function OLhL(s){return(s?' style="width:100%;"':'width:100%;');}
+
+// Loads image into the div.
+function OLsetBackground(i){
+if(i==''){if(OLns4)over.background.src=null;else{if(OLns6)over.style.width='';over.style.backgroundImage='none';}}
+else{if(OLns4)over.background.src=i;else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i+')';}}
+}
+
+/*
+ HANDLING FUNCTIONS
+*/
+// Displays layer
+function OLdisp(s){
+if(OLmodalPI&&!o3_modalscroll)OLchkModal();if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();
+OLplaceLayer();if(OLmodalPI&&o3_modalscroll)OLchkModal();if(OLndt)OLshowObject(over);
+else OLshowid=setTimeout("OLshowObject(over)",1);OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;
+}
+
+// Decides placement of layer.
+function OLplaceLayer(){
+var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,o=OLfd(),
+nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
+if(!OLkht&&o&&o.clientWidth)iWd=o.clientWidth;
+else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));
+if(SB>20)SB=20;iWd=o3_frame.innerWidth;}
+pgLeft=(OLie4)?o.scrollLeft:o3_frame.pageXOffset;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);
+LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);}
+if(o3_ref!=""||o3_fixx> -1||o3_relx!=null||o3_midx!=null){
+if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='UR'||o3_refp=='LR')X-=5;}
+else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
+if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else
+if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}
+}else{if(o3_midx!=null){
+X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);
+}else{if(o3_relx!=null){
+if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;
+}else{X=o3_fixx+LM;}}}
+}else{
+if(o3_hauto){
+if(o3_hpos==LEFT&&OLx-pgLeft+OLifX<iWd/2&&OLx-pWd-o3_offsetx+OLifX<pgLeft+LM)o3_hpos=RIGHT;else
+if(o3_hpos==RIGHT&&OLx-pgLeft+OLifX>iWd/2&&OLx+pWd+o3_offsetx+OLifX>pgLeft+iWd-SB)o3_hpos=LEFT;}
+X=(o3_hpos==CENTER)?parseInt(OLx-((pWd+CX)/2)+o3_offsetx):
+(o3_hpos==LEFT)?OLx-o3_offsetx-pWd:OLx+o3_offsetx;
+if(o3_snapx>1){
+snp=X % o3_snapx;
+if(o3_hpos==LEFT){X=X-(o3_snapx+snp);}else{X=X+(o3_snapx-snp);}}X+=OLifX;}
+if(!o3_nojustx&&X+pWd>pgLeft+iWd-SB)
+X=iWd+pgLeft-pWd-SB;if(!o3_nojustx&&X-LM<pgLeft)X=pgLeft+LM;
+pgTop=OLie4?o.scrollTop:o3_frame.pageYOffset;
+if(!OLkht&&!nsb&&o&&o.clientHeight)iHt=o.clientHeight;
+else if(o3_frame.innerHeight)iHt=o3_frame.innerHeight;
+if(OLbubblePI&&o3_bubble)pHt=OLbubbleHt;else pHt=OLns4?over.clip.height:over.offsetHeight;
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){TM=(o3_shadowy<0)?Math.abs(o3_shadowy):0;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)BM=CY=5;else
+BM=(o3_shadowy>0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);}
+if(o3_ref!=""||o3_fixy> -1||o3_rely!=null||o3_midy!=null){
+if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
+if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else
+if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}
+}else{if(o3_midy!=null){
+Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);
+}else{if(o3_rely!=null){
+if(o3_rely>=0)Y=pgTop+o3_rely+TM;else Y=pgTop+o3_rely+iHt-pHt-BM;}else{
+Y=o3_fixy+TM;}}}
+}else{
+if(o3_vauto){
+if(o3_vpos==ABOVE&&OLy-pgTop+OLifY<iHt/2&&OLy-pHt-o3_offsety+OLifY<pgTop)o3_vpos=BELOW;else
+if(o3_vpos==BELOW&&OLy-pgTop+OLifY>iHt/2&&OLy+pHt+o3_offsety+((OLns4||OLkht)?17:0)+OLifY>pgTop+iHt-BM)
+o3_vpos=ABOVE;}Y=(o3_vpos==VCENTER)?parseInt(OLy-((pHt+CY)/2)+o3_offsety):
+(o3_vpos==ABOVE)?OLy-(pHt+o3_offsety+BM):OLy+o3_offsety+TM;
+if(o3_snapy>1){
+snp=Y % o3_snapy;
+if(pHt>0&&o3_vpos==ABOVE){Y=Y-(o3_snapy+snp);}else{Y=Y+(o3_snapy-snp);}}Y+=OLifY;}
+if(!o3_nojusty&&Y+pHt+BM>pgTop+iHt)Y=pgTop+iHt-pHt-BM;if(!o3_nojusty&&Y-TM<pgTop)Y=pgTop+TM;
+OLrepositionTo(over,X,Y);
+if(OLshadowPI)OLrepositionShadow(X,Y);if(OLiframePI)OLrepositionIfs(X,Y);
+if(OLns6&&o3_frame.innerHeight){iHt=o3_frame.innerHeight;OLrepositionTo(over,X,Y);}
+if(OLscrollPI)OLchkScroll(X-pgLeft,Y-pgTop);
+}
+
+// Chooses body or documentElement
+function OLfd(f){
+var fd=((f)?f:o3_frame).document,fdc=fd.compatMode,fdd=fd.documentElement;
+return (!OLop7&&fdc&&fdc!='BackCompat'&&fdd&&fdd.clientWidth)?fd.documentElement:fd.body;
+}
+
+// Gets location of REFerence object
+function OLgetRefXY(r,d){
+var o=OLgetRef(r,d),ob=o,rXY=[o3_refx,o3_refy],of;if(!o)return [null,null];if(OLns4){
+if(typeof o.length!='undefined'&&o.length>1){ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;}else{
+if((o.toString().indexOf('Image')!= -1)||(o.toString().indexOf('Anchor')!= -1)){rXY[0]+=o.x;rXY[1]+=o.y;}
+else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');}
+of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];return rXY;
+}
+
+// Seeks REFerence by id
+function OLgetRefById(l,d){
+l=(l||'overDiv');d=(d||o3_frame.document);var j,r;if(d.getElementById)return d.getElementById(l);
+if(OLie4&&d.all)return d.all[l];if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
+for(j=0;j<d.layers.length;j++){r=OLgetRefById(l,d.layers[j].document);if(r)return r;}}return null;
+}
+
+// Seeks REFerence by name
+function OLgetRefByName(l,d){
+d=(d||o3_frame.document);var j,r,v=OLie4?d.all.tags('iframe'):OLns6?d.getElementsByTagName('iframe'):null;
+if(typeof d.images!='undefined'&&d.images[l])return d.images[l];
+if(typeof d.anchors!='undefined'&&d.anchors[l])return d.anchors[l];
+if(v)for(j=0;j<v.length;j++)if(v[j].name==l)return v[j];if(d.layers&&d.layers.length>0)for(j=0;j<d.layers.length;j++){
+r=OLgetRefByName(l,d.layers[j].document);if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}return null;
+}
+
+// Gets layer vs REFerence offsets
+function OLgetRefOffsets(o){
+var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];pW=(OLbubblePI&&o3_bubble)?
+o3_width:OLns4?over.clip.width:over.offsetWidth;pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?
+over.clip.height:over.offsetHeight;if((!OLop7)&&o.toString().indexOf('Image')!= -1){W=o.width;H=o.height;}
+else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){c=o3_refc='UL';}else{W=(OLns4)?o.clip.width:o.offsetWidth;
+H=(OLns4)?o.clip.height:o.offsetHeight;}if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);
+H+=2*parseInt(o.border);}if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];}else if(c=='UR'){
+of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:
+(p=='LR')?[-pW,H-pH]:[0,H];}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:[W,H];}return of;
+}
+
+// Gets x or y location of object
+function OLpageLoc(o,t){
+var l=0,s=o;while(o.offsetParent&&o.offsetParent.tagName.toLowerCase()!='html'){l+=o['offset'+t];o=o.offsetParent;}
+l+=o['offset'+t];while(s=s.parentNode){if((s['scroll'+t]>0)&&s.tagName.toLowerCase()=='div')l-=s['scroll'+t];}return l;
+}
+
+// Moves layer
+function OLmouseMove(e){
+var e=(e||event);OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);OLx=(e.pageX||e.clientX+OLfd().scrollLeft);
+OLy=(e.pageY||e.clientY+OLfd().scrollTop);if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById()||(OLovertwoPI&&
+over2==over&&over==OLgetRefById('overDiv2')))){OLplaceLayer();if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}if(OLhover&&over&&
+o3_frame==self&&OLcursorOff())if(o3_offdelay<1)OLcC();else{if(OLtimerid>0)clearTimeout(OLtimerid);
+OLtimerid=setTimeout("OLcC()",o3_offdelay);}
+}
+
+// Capture mouse and chain other scripts.
+function OLmh(){
+var fN,f,j,k,s,mh=OLmouseMove,w=(OLns4&&window.onmousemove),re=/function[ ]*(\w*)\(/;OLdw=document;if(document.onmousemove||
+w){if(w)OLdw=window;f=OLdw.onmousemove.toString();fN=f.match(re);if(!fN||fN[1]=='anonymous'||fN[1]=='OLmouseMove'){OLchkMh=0;
+return;}if(fN[1])s=fN[1]+'(e)';else{j=f.indexOf('{');k=f.lastIndexOf('}')+1;s=f.substring(j,k);}s+=';OLmouseMove(e);';
+mh=new Function('e',s);}OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE);
+}
+
+/*
+ PARSING
+*/
+function OLparseTokens(pf,ar){
+var i,v,md= -1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
+for(i=0;i<ar.length;i++){if(md<0){if(typeof ar[i]=='number'){OLudf=(par?1:0);i--;}
+else{switch(pf){case 'ol_':ol_text=ar[i];break;default:o3_text=ar[i];}}md=0;}else{
+if(ar[i]==INARRAY){OLudf=0;eval(pf+'text=ol_texts['+ar[++i]+']');continue;}
+if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[++i]+']');continue;}
+if(ar[i]==CAPTION){q(ar[++i],pf+'cap');continue;}
+if(Math.abs(ar[i])==STICKY){t(ar[i],pf+'sticky');continue;}
+if(Math.abs(ar[i])==NOFOLLOW){t(ar[i],pf+'nofollow');continue;}
+if(ar[i]==BACKGROUND){q(ar[++i],pf+'background');continue;}
+if(Math.abs(ar[i])==NOCLOSE){t(ar[i],pf+'noclose');continue;}
+if(Math.abs(ar[i])==MOUSEOFF){t(ar[i],pf+'mouseoff');continue;}
+if(ar[i]==OFFDELAY){p(ar[++i],pf+'offdelay');continue;}
+if(ar[i]==RIGHT||ar[i]==LEFT||ar[i]==CENTER){p(ar[i],pf+'hpos');continue;}
+if(ar[i]==OFFSETX){p(ar[++i],pf+'offsetx');continue;}
+if(ar[i]==OFFSETY){p(ar[++i],pf+'offsety');continue;}
+if(ar[i]==FGCOLOR){q(ar[++i],pf+'fgcolor');continue;}
+if(ar[i]==BGCOLOR){q(ar[++i],pf+'bgcolor');continue;}
+if(ar[i]==CGCOLOR){q(ar[++i],pf+'cgcolor');continue;}
+if(ar[i]==TEXTCOLOR){q(ar[++i],pf+'textcolor');continue;}
+if(ar[i]==CAPCOLOR){q(ar[++i],pf+'capcolor');continue;}
+if(ar[i]==CLOSECOLOR){q(ar[++i],pf+'closecolor');continue;}
+if(ar[i]==WIDTH){p(ar[++i],pf+'width');continue;}
+if(Math.abs(ar[i])==WRAP){t(ar[i],pf+'wrap');continue;}
+if(ar[i]==WRAPMAX){p(ar[++i],pf+'wrapmax');continue;}
+if(ar[i]==HEIGHT){p(ar[++i],pf+'height');continue;}
+if(ar[i]==BORDER){p(ar[++i],pf+'border');continue;}
+if(ar[i]==BASE){p(ar[++i],pf+'base');continue;}
+if(ar[i]==STATUS){q(ar[++i],pf+'status');continue;}
+if(Math.abs(ar[i])==AUTOSTATUS){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
+if(Math.abs(ar[i])==AUTOSTATUSCAP){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
+if(ar[i]==CLOSETEXT){q(ar[++i],pf+'close');continue;}
+if(ar[i]==SNAPX){p(ar[++i],pf+'snapx');continue;}
+if(ar[i]==SNAPY){p(ar[++i],pf+'snapy');continue;}
+if(ar[i]==FIXX){p(ar[++i],pf+'fixx');continue;}
+if(ar[i]==FIXY){p(ar[++i],pf+'fixy');continue;}
+if(ar[i]==RELX){p(ar[++i],pf+'relx');continue;}
+if(ar[i]==RELY){p(ar[++i],pf+'rely');continue;}
+if(ar[i]==MIDX){p(ar[++i],pf+'midx');continue;}
+if(ar[i]==MIDY){p(ar[++i],pf+'midy');continue;}
+if(ar[i]==REF){q(ar[++i],pf+'ref');continue;}
+if(ar[i]==REFC){q(ar[++i],pf+'refc');continue;}
+if(ar[i]==REFP){q(ar[++i],pf+'refp');continue;}
+if(ar[i]==REFX){p(ar[++i],pf+'refx');continue;}
+if(ar[i]==REFY){p(ar[++i],pf+'refy');continue;}
+if(ar[i]==FGBACKGROUND){q(ar[++i],pf+'fgbackground');continue;}
+if(ar[i]==BGBACKGROUND){q(ar[++i],pf+'bgbackground');continue;}
+if(ar[i]==CGBACKGROUND){q(ar[++i],pf+'cgbackground');continue;}
+if(ar[i]==PADX){p(ar[++i],pf+'padxl');p(ar[++i],pf+'padxr');continue;}
+if(ar[i]==PADY){p(ar[++i],pf+'padyt');p(ar[++i],pf+'padyb');continue;}
+if(Math.abs(ar[i])==FULLHTML){t(ar[i],pf+'fullhtml');continue;}
+if(ar[i]==BELOW||ar[i]==ABOVE||ar[i]==VCENTER){p(ar[i],pf+'vpos');continue;}
+if(ar[i]==CAPICON){q(ar[++i],pf+'capicon');continue;}
+if(ar[i]==TEXTFONT){q(ar[++i],pf+'textfont');continue;}
+if(ar[i]==CAPTIONFONT){q(ar[++i],pf+'captionfont');continue;}
+if(ar[i]==CLOSEFONT){q(ar[++i],pf+'closefont');continue;}
+if(ar[i]==TEXTSIZE){q(ar[++i],pf+'textsize');continue;}
+if(ar[i]==CAPTIONSIZE){q(ar[++i],pf+'captionsize');continue;}
+if(ar[i]==CLOSESIZE){q(ar[++i],pf+'closesize');continue;}
+if(ar[i]==TIMEOUT){p(ar[++i],pf+'timeout');continue;}
+if(ar[i]==DELAY){p(ar[++i],pf+'delay');continue;}
+if(Math.abs(ar[i])==HAUTO){t(ar[i],pf+'hauto');continue;}
+if(Math.abs(ar[i])==VAUTO){t(ar[i],pf+'vauto');continue;}
+if(Math.abs(ar[i])==NOJUSTX){t(ar[i],pf+'nojustx');continue;}
+if(Math.abs(ar[i])==NOJUSTY){t(ar[i],pf+'nojusty');continue;}
+if(Math.abs(ar[i])==CLOSECLICK){t(ar[i],pf+'closeclick');continue;}
+if(ar[i]==CLOSETITLE){q(ar[++i],pf+'closetitle');continue;}
+if(ar[i]==FGCLASS){q(ar[++i],pf+'fgclass');continue;}
+if(ar[i]==BGCLASS){q(ar[++i],pf+'bgclass');continue;}
+if(ar[i]==CGCLASS){q(ar[++i],pf+'cgclass');continue;}
+if(ar[i]==TEXTPADDING){p(ar[++i],pf+'textpadding');continue;}
+if(ar[i]==TEXTFONTCLASS){q(ar[++i],pf+'textfontclass');continue;}
+if(ar[i]==CAPTIONPADDING){p(ar[++i],pf+'captionpadding');continue;}
+if(ar[i]==CAPTIONFONTCLASS){q(ar[++i],pf+'captionfontclass');continue;}
+if(ar[i]==CLOSEFONTCLASS){q(ar[++i],pf+'closefontclass');continue;}
+if(Math.abs(ar[i])==CAPBELOW){t(ar[i],pf+'capbelow');continue;}
+if(ar[i]==LABEL){q(ar[++i],pf+'label');continue;}
+if(Math.abs(ar[i])==DECODE){t(ar[i],pf+'decode');continue;}
+if(ar[i]==DONOTHING){continue;}
+i=OLparseCmdLine(pf,i,ar);}}
+if((OLfunctionPI)&&OLudf&&o3_function)o3_text=o3_function();
+if(pf=='o3_')OLfontSize();
+}
+function OLpar(a,v){eval(v+'='+a);}
+function OLparQuo(a,v){eval(v+"='"+OLescSglQt(a)+"'");}
+function OLescSglQt(s){return s.toString().replace(/\\/g,"\\\\").replace(/'/g,"\\'");}
+function OLtoggle(a,v){eval(v+'=('+v+'==0&&'+a+'>=0)?1:0');}
+function OLhasDims(s){return /[%\-a-z]+$/.test(s);}
+function OLfontSize(){
+var i;if(OLhasDims(o3_textsize)){if(OLns4)o3_textsize="2";}else
+if(!OLns4){i=parseInt(o3_textsize);o3_textsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else
+if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else
+if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLprintPI)OLprintDims();
+}
+function OLdecode(){
+var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)&&typeof decodeURIComponent?
+decodeURIComponent:u;if(typeof(window.TypeError)=='function'){if(re.test(t)){eval(new Array('try{','o3_text=d(t);',
+'}catch(e){','o3_text=u(t);','}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){',
+'o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}
+}
+
+/*
+ LAYER FUNCTIONS
+*/
+// Writes to layer
+function OLlayerWrite(t){
+t+="\n";if(OLns4){over.document.write(t);over.document.close();}else if(typeof over.innerHTML!='undefined'){
+if(OLieM)over.innerHTML='';over.innerHTML=t;}else{var range=o3_frame.document.createRange();range.setStartAfter(over);
+var domfrag=range.createContextualFragment(t);while(over.hasChildNodes()){over.removeChild(over.lastChild);}
+over.appendChild(domfrag);}if(OLovertwoPI&&over==over2)OLover2HTML=t;else OLoverHTML=t;
+if(OLprintPI)over.print=o3_print?t:null;
+}
+
+// Makes object visible
+function OLshowObject(o){
+OLshowid=0;o=(OLns4)?o:o.style;if(((OLfilterPI)&&!OLchkFilter(o))||!OLfilterPI)o.visibility="visible";
+if(OLshadowPI)OLshowShadow();if(OLiframePI)OLshowIfs();if(OLhidePI)OLhideUtil(1,1,0);
+}
+
+// Hides object
+function OLhideObject(o){
+if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;}if(OLtimerid>0)clearTimeout(OLtimerid);
+if(OLdelayid>0)clearTimeout(OLdelayid);OLtimerid=0;OLdelayid=0;self.status="";o3_label=ol_label;
+if(o3_frame!=self)o=OLgetRefById();if(o){if(o.onmouseover)o.onmouseover=null;if(OLscrollPI&&o==over)OLclearScroll();
+if(OLdraggablePI)OLclearDrag();if(OLfilterPI)OLcleanupFilter(o);if(OLshadowPI)OLhideShadow();var os=(OLns4)?o:o.style;
+if(((OLfilterPI)&&!OLchkFadeOut(os))||!OLfilterPI){os.visibility="hidden";if(!OLie55||!OLfilterPI||!o3_filter||
+o3_fadeout<0)o.innerHTML='';}if(OLhidePI&&o==over)OLhideUtil(0,0,1);if(OLiframePI)OLhideIfs(o);}
+}
+
+// Moves layer
+function OLrepositionTo(o,xL,yL){
+o=(OLns4)?o:o.style;o.left=(OLns4?xL:xL+'px');o.top=(OLns4?yL:yL+'px');
+}
+
+// Handle NOCLOSE-MOUSEOFF
+function OLoptMOUSEOFF(c){
+if(!c)o3_close="";
+over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}
+}
+function OLcursorOff(){
+var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,left=parseInt(o.left),top=parseInt(o.top),
+right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
+if(OLx<left||OLx>right||OLy<top||OLy>bottom)return true;return false;
+}
+
+/*
+ REGISTRATION
+*/
+function OLsetRunTimeVar(){
+if(OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
+}
+function OLparseCmdLine(pf,i,ar){
+if(OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){var j=OLcmdLine[k](pf,i,ar);if(j>-1){i=j;break;}}}return i;
+}
+function OLregCmds(c){
+if(typeof c!='string')return;var pM=c.split(',');pMtr=pMtr.concat(pM);
+for(var i=0;i<pM.length;i++)eval(pM[i].toUpperCase()+'='+pmCnt++);
+}
+function OLregRunTimeFunc(f){
+if(typeof f=='object')OLrunTime=OLrunTime.concat(f);else OLrunTime[OLrunTime.length++]=f;
+}
+function OLregCmdLineFunc(f){
+if(typeof f=='object')OLcmdLine=OLcmdLine.concat(f);else OLcmdLine[OLcmdLine.length++]=f;
+}
+
+OLloaded=1;
diff --git a/httemplate/elements/overlibmws_crossframe.js b/httemplate/elements/overlibmws_crossframe.js
new file mode 100644
index 000000000..dd6422313
--- /dev/null
+++ b/httemplate/elements/overlibmws_crossframe.js
@@ -0,0 +1,53 @@
+/*
+ overlibmws_crossframe.js plug-in module - Copyright Foteos Macrides 2003-2008. All rights reserved.
+ For support of FRAME.
+ Initial: August 3, 2003 - Last Revised: January 16, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('frame');
+
+function OLparseCrossframe(pf,i,ar){
+var k=i,v;
+if(k<ar.length){
+if(ar[k]==FRAME){v=ar[++k];if(pf=='ol_')ol_frame=v;else OLoptFRAME(v);return k;}}
+return -1;
+}
+
+function OLgetFrameRef(thisFrame,ofrm){
+var i,v,retVal='';for(i=0;i<thisFrame.length;i++){if((((thisFrame[i].length>0)))&&(((OLns4))||
+((OLie4)&&(v=thisFrame[i].document.all.tags('iframe'))!=null&&v.length==0)||
+((OLns6)&&(v=thisFrame[i].document.getElementsByTagName('iframe'))!=null&&v.length==0))){
+retVal=OLgetFrameRef(thisFrame[i],ofrm);if(retVal=='')continue;}
+else if(thisFrame[i]!=ofrm)continue;retVal='['+i+']'+retVal;break;}
+return retVal;
+}
+
+function OLoptFRAME(frm){
+o3_frame=OLmkLyr('overDiv',frm)?frm:self;if(o3_frame!=self){var l,tFrm=OLgetFrameRef(top.frames,o3_frame),
+sFrm=OLgetFrameRef(top.frames,ol_frame);if(sFrm.length==tFrm.length) {l=tFrm.lastIndexOf('[');if(l){
+while(sFrm.substring(0,l)!=tFrm.substring(0,l))l=tFrm.lastIndexOf('[',l-1);tFrm=tFrm.substr(l);sFrm=sFrm.substr(l);}}
+var i,k,cnt=0,p='',str=tFrm;while((k=str.lastIndexOf('['))!= -1){cnt++;str=str.substring(0,k);}
+for(i=0;i<cnt;i++)p=p+'parent.';OLfnRef=p+'frames'+sFrm+'.';var n=window.name,o;
+if((n&&parent!=self&&o3_frame==parent)&&(o=OLgetRef(n,parent.document))){if(OLie4&&!OLop7){
+OLx=event.clientX+OLfd().scrollLeft;OLy=event.clientY+OLfd().scrollTop;}
+OLifX=OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd().scrollLeft:self.pageXOffset);
+OLifY=OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd().scrollTop:self.pageYOffset);}}
+}
+
+function OLchkIfRef(){
+var n=(parent!=self&&o3_frame==parent)?window.name:'',o=n?OLgetRef(n):null;
+if(o){var oR=OLgetRef(o3_ref,document);if(oR){OLrefXY=OLgetRefXY(o3_ref,document);
+OLrefXY[0]+=(OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd(self).scrollLeft:self.pageXOffset));
+OLrefXY[1]+=(OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd(self).scrollTop:self.pageYOffset));}}
+}
+
+OLregCmdLineFunc(OLparseCrossframe);
+
+OLcrossframePI=1;
+OLloaded=1;
diff --git a/httemplate/elements/overlibmws_draggable.js b/httemplate/elements/overlibmws_draggable.js
new file mode 100644
index 000000000..1bf0ecfd1
--- /dev/null
+++ b/httemplate/elements/overlibmws_draggable.js
@@ -0,0 +1,85 @@
+/*
+ overlibmws_draggable.js plug-in module - Copyright Foteos Macrides 2002-2008. All rights reserved.
+ For support of the DRAGGABLE feature.
+ Initial: August 24, 2002 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLdraggableCmds='draggable,dragcap,dragid';
+OLregCmds(OLdraggableCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('draggable'))var ol_draggable=0;
+if(OLud('dragcap'))var ol_dragcap=0;
+if(OLud('dragid'))var ol_dragid='';
+// END CONFIGURATION
+
+var o3_draggable=0,o3_dragcap=0,o3_dragid='',o3_dragging=0,OLdrg=null,OLmMv,
+OLcX,OLcY,OLcbX,OLcbY;function OLloadDraggable(){OLload(OLdraggableCmds);}
+function OLparseDraggable(pf,i,ar){var t=OLtoggle,k=i;if(k<ar.length){
+if(Math.abs(ar[k])==DRAGGABLE){t(ar[k],pf+'draggable');return k;}
+if(Math.abs(ar[k])==DRAGCAP){t(ar[k],pf+'dragcap');return k;}
+if(ar[k]==DRAGID){OLparQuo(ar[++k],pf+'dragid');return k;}}return -1;
+}
+
+function OLcheckDrag(){
+if(o3_draggable){if(o3_sticky&&(o3_frame==self))OLinitDrag();else o3_draggable=0;}
+}
+function OLinitDrag(){
+OLmMv=OLdw.onmousemove;o3_dragging=0;
+if(OLns4){document.captureEvents(Event.MOUSEDOWN|Event.CLICK);
+document.onmousedown=OLgrabEl;document.onclick=function(e){return routeEvent(e);}}
+else{var dvido=(o3_dragid)?OLgetRef(o3_dragid):null,capid=(OLovertwoPI&&over==over2?
+'overCap2':'overCap');if(dvido)dvido.onscroll=function(){OLdw.onmousemove=OLmMv;
+OLinitDrag();};OLdrg=(o3_cap&&o3_dragcap)?OLgetRef(capid):over;
+if(!OLdrg||!OLdrg.style)OLdrg=over;OLdrg.onmousedown=OLgrabEl;OLsetDrgCur(1);}
+}
+function OLsetDrgCur(d){if(!OLns4&&OLdrg)OLdrg.style.cursor=(d?'move':'auto');}
+
+function OLgrabEl(e){
+var e=(e||event);
+var cKy=(OLns4?e.modifiers&Event.ALT_MASK:(e.altKey||(OLop7&&e.ctrlKey)));o3_dragging=1;
+if(cKy){OLsetDrgCur(0);document.onmouseup=function(){OLsetDrgCur(1);o3_dragging=0;}
+return(OLns4?routeEvent(e):true);}
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(OLie4)over.onselectstart=function(){return false;}
+if(OLns4){OLcX=OLx;OLcY=OLy;document.captureEvents(Event.MOUSEUP)}else{
+OLcX=OLx-(OLns4?over.left:parseInt(over.style.left));
+OLcY=OLy-(OLns4?over.top:parseInt(over.style.top));
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLcbX=OLx-(parseInt(bkdrop.style.left));
+OLcbY=OLy-(parseInt(bkdrop.style.top));}}OLdw.onmousemove=OLmoveEl;
+document.onmouseup=function(){
+if(OLie4)over.onselectstart=null;o3_dragging=0;OLdw.onmousemove=OLmMv;}
+return(OLns4?routeEvent(e):false);
+}
+
+function OLmoveEl(e){
+var e=(e||event);
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(o3_dragging){if(OLns4){over.moveBy(OLx-OLcX,OLy-OLcY);
+if(OLshadowPI&&bkdrop&&o3_shadow)bkdrop.moveBy(OLx-OLcX,OLy-OLcY);}
+else{OLrepositionTo(over,OLx-OLcX,OLy-OLcY);
+if((OLiframePI)&&OLie55&&OLifsP1)OLrepositionTo(OLifsP1,OLx-OLcX,OLy-OLcY);
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLrepositionTo(bkdrop,OLx-OLcbX,OLy-OLcbY);
+if((OLiframePI)&&OLie55&&OLifsSh)OLrepositionTo(OLifsSh,OLx-OLcbX,OLy-OLcbY);}}
+if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}if(OLns4){OLcX=OLx;OLcY=OLy;}
+return false;
+}
+
+function OLclearDrag(){
+if(OLns4){document.releaseEvents(Event.MOUSEDOWN|Event.MOUSEUP|Event.CLICK);
+document.onmousedown=document.onclick=null;}else{
+if(OLdrg)OLdrg.onmousedown=null;over.onmousedown=null;OLsetDrgCur(0);}
+document.onmouseup=null;o3_dragging=0;
+}
+
+OLregRunTimeFunc(OLloadDraggable);
+OLregCmdLineFunc(OLparseDraggable);
+
+OLdraggablePI=1;
+OLloaded=1;
diff --git a/httemplate/elements/overlibmws_iframe.js b/httemplate/elements/overlibmws_iframe.js
new file mode 100644
index 000000000..4c937d3d7
--- /dev/null
+++ b/httemplate/elements/overlibmws_iframe.js
@@ -0,0 +1,93 @@
+/*
+ overlibmws_iframe.js plug-in module - Copyright Foteos Macrides 2003-2008. All rights reserved.
+ Masks system controls to prevent obscuring of popops for IE v5.5 or higher.
+ Initial: October 19, 2003 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+ http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+
+var OLifsP1=null,OLifsSh=null,OLifsP2=null;
+
+// IFRAME SHIM SUPPORT FUNCTIONS
+function OLinitIfs(){
+if(!OLie55)return;
+if((OLovertwoPI)&&over2&&over==over2){
+var o=o3_frame.document.all['overIframeOvertwo'];
+if(!o||OLifsP2!=o){OLifsP2=null;OLgetIfsP2Ref();}return;}
+o=o3_frame.document.all['overIframe'];
+if(!o||OLifsP1!=o){OLifsP1=null;OLgetIfsRef();}
+if((OLshadowPI)&&o3_shadow){o=o3_frame.document.all['overIframeShadow'];
+if(!o||OLifsSh!=o){OLifsSh=null;OLgetIfsShRef();}}
+}
+
+function OLsetIfsRef(o,i,z){
+o.id=i;o.src='javascript:false;';o.scrolling='no';var os=o.style;os.position='absolute';
+os.top='0px';os.left='0px';os.width='1px';os.height='1px';os.visibility='hidden';
+os.zIndex=over.style.zIndex-z;os.filter='Alpha(style=0,opacity=0)';
+}
+
+function OLgetIfsRef(){
+if(OLifsP1||!OLie55)return;
+OLifsP1=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP1,'overIframe',2);
+o3_frame.document.body.appendChild(OLifsP1);
+}
+
+function OLgetIfsShRef(){
+if(OLifsSh||!OLie55)return;
+OLifsSh=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsSh,'overIframeShadow',3);
+o3_frame.document.body.appendChild(OLifsSh);
+}
+
+function OLgetIfsP2Ref(){
+if(OLifsP2||!OLie55)return;
+OLifsP2=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP2,'overIframeOvertwo',1);
+o3_frame.document.body.appendChild(OLifsP2);
+}
+
+function OLsetDispIfs(o,w,h){
+var os=o.style;
+os.width=w+'px';os.height=h+'px';os.clip='rect(0px '+w+'px '+h+'px 0px)';
+o.filters.alpha.enabled=true;
+}
+
+function OLdispIfs(){
+if(!OLie55)return;
+var wd=over.offsetWidth,ht=over.offsetHeight;
+if(OLfilterPI&&o3_filter&&o3_filtershadow){wd+=5;ht+=5;}
+if((OLovertwoPI)&&over2&&over==over2){
+if(!OLifsP2)return;
+OLsetDispIfs(OLifsP2,wd,ht);return;}
+if(!OLifsP1)return;
+OLsetDispIfs(OLifsP1,wd,ht);
+if((!OLshadowPI)||!o3_shadow||!OLifsSh)return;
+OLsetDispIfs(OLifsSh,wd,ht);
+}
+
+function OLshowIfs(){
+if(OLifsP1){OLifsP1.style.visibility="visible";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="visible";}
+}
+
+function OLhideIfs(o){
+if(!OLie55||o!=over)return;
+if(OLifsP1)OLifsP1.style.visibility="hidden";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="hidden";
+}
+
+function OLrepositionIfs(X,Y){
+if(OLie55){if((OLovertwoPI)&&over2&&over==over2){
+if(OLifsP2)OLrepositionTo(OLifsP2,X,Y);}
+else{if(OLifsP1){OLrepositionTo(OLifsP1,X,Y);if((OLshadowPI)&&o3_shadow&&OLifsSh)
+OLrepositionTo(OLifsSh,X+o3_shadowx,Y+o3_shadowy);}}}
+}
+
+OLiframePI=1;
+OLloaded=1;
diff --git a/httemplate/elements/pager.html b/httemplate/elements/pager.html
new file mode 100644
index 000000000..a53300f53
--- /dev/null
+++ b/httemplate/elements/pager.html
@@ -0,0 +1,55 @@
+% my %opt = @_;
+% my $pager = '';
+%
+% if ( $opt{'total'} != $opt{'num_rows'} && $opt{'maxrecords'} ) {
+%
+% unless ( $opt{'offset'} == 0 ) {
+% $cgi->param('offset', $opt{'offset'} - $opt{'maxrecords'});
+
+ <A HREF="<% $cgi->self_url %>"><B><FONT SIZE="+1">Previous</FONT></B></A>
+
+% }
+%
+% my $page = 0;
+% my $prevpage = 0;
+% my $over = 0;
+% my $step = $opt{total} / 10; # 10 evenly spaced
+% for ( my $poff = 0; $poff < $opt{total}; $poff += $opt{maxrecords} ) {
+% $page++;
+%
+% next unless
+% $page <= 4 #first four
+% || $page >= ( $opt{total} / $opt{maxrecords} ) - 3 #last four
+% || abs( ($opt{offset}-$poff) / $opt{maxrecords} ) <= 3 #w/i 3 of current
+% || $poff > $over # evenly spaced
+% ;
+%
+% $over += $step if $poff > $over;
+%
+% if ( $opt{'offset'} == $poff ) {
+
+ <FONT SIZE="+2"><% $page %></FONT>
+
+% } else {
+% $cgi->param('offset', $poff);
+%
+% if ( $page > $prevpage+1 ) {
+ ...
+% }
+
+ <A HREF="<% $cgi->self_url %>"><% $page %></A>
+
+% }
+%
+% $prevpage = $page;
+%
+% }
+%
+% unless ( $opt{'offset'} + $opt{'maxrecords'} > $opt{'total'} ) {
+% $cgi->param('offset', $opt{'offset'} + $opt{'maxrecords'});
+
+ <A HREF="<% $cgi->self_url %>"><B><FONT SIZE="+1">Next</FONT></B></A>
+%
+% }
+%
+% }
diff --git a/httemplate/elements/phonenumber.html b/httemplate/elements/phonenumber.html
new file mode 100644
index 000000000..60414a644
--- /dev/null
+++ b/httemplate/elements/phonenumber.html
@@ -0,0 +1,40 @@
+<% include('/elements/init_overlib.html') %>
+
+% if ( length($number) ) {
+
+ <% $number %>
+
+% if ( $opt{'callable'} && $curuser->option('vonage-username') ) {
+
+ <% include('/elements/popup_link.html',
+ 'action' =>
+ 'https://secure.click2callu.com/tpcc/makecall'.
+ '?username='. uri_escape($curuser->option('vonage-username')).
+ '&password='. uri_escape($curuser->option('vonage-password')).
+ "&fromnumber=$vonage_number".
+ "&tonumber=$snumber",
+ 'width' => 240,
+ 'height' => 64,
+ 'actionlabel' => 'Initiating call',
+ 'label' => qq!<IMG SRC="${fsurl}images/red_telephone_mimooh_01.png" BORDER=0 ALT="Call this number">!,
+ )
+ %>
+
+% }
+%
+% } else {
+
+ &nbsp;
+
+% }
+<%init>
+
+my( $number, %opt ) = @_;
+( my $snumber = $number ) =~ s/\D//g;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+( my $vonage_number = $curuser->option('vonage-fromnumber') ) =~ s/\D//g;
+$vonage_number =~ /^1/ or $vonage_number = "1$vonage_number";
+
+</%init>
diff --git a/httemplate/elements/popup_link-cust_main.html b/httemplate/elements/popup_link-cust_main.html
new file mode 100644
index 000000000..6d92301b1
--- /dev/null
+++ b/httemplate/elements/popup_link-cust_main.html
@@ -0,0 +1,42 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/cust_popup_link.html', { #hashref or a list, either way
+
+ #required
+ 'action' => 'content.html', # uri for content of popup which should
+ # be suitable for appending keywords
+ 'label' => 'click me', # text of <A> tag
+ 'cust_main' => $cust_main # a FS::cust_main object
+
+ #strongly recommended (you want a title, right?)
+ 'actionlabel => 'You clicked', # popup title
+
+ #opt
+ 'width' => '540',
+ 'color' => '#ff0000',
+ 'closetext' => 'Go Away', # the value '' removes the link
+ )
+
+</%doc>
+% if ( $params->{'cust_main'} ) {
+<% include('/elements/popup_link.html', $params ) %>\
+% }
+<%init>
+
+my $params = { 'closetext' => 'Close' };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'action'} .=
+ ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
+ 'custnum='. $params->{'cust_main'}->custnum;
+
+</%init>
diff --git a/httemplate/elements/popup_link-cust_pkg.html b/httemplate/elements/popup_link-cust_pkg.html
new file mode 100644
index 000000000..cd8d5c069
--- /dev/null
+++ b/httemplate/elements/popup_link-cust_pkg.html
@@ -0,0 +1,47 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/pkg_popup_link.html', { #hashref or a list, either way
+
+ #required
+ 'action' => 'content.html', # uri for content of popup which should
+ # be suitable for appending '&stuff...'
+ 'label' => 'click me', # text of <A> tag
+ 'cust_pkg' => $cust_pkg # a FS::cust_pkg object
+
+ #strongly recommended (you want a title, right?)
+ 'actionlabel => 'You clicked', # popup title
+
+ #opt
+ 'width' => '540',
+ 'color' => '#ff0000',
+ 'closetext' => 'Go Away', # the value '' removes the link
+ )
+
+</%doc>
+% if ( $params->{'cust_pkg'} ) {
+<% include('/elements/popup_link.html', $params ) %>\
+% }
+<%init>
+
+my $params = { 'closetext' => 'Close',
+ 'width' => 768,
+ };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'action'} .=
+ ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
+ 'pkgnum='. $params->{'cust_pkg'}->pkgnum;
+
+$params->{'actionlabel'} .=
+ ' package '. $params->{'cust_pkg'}->pkgnum; #XXX pkgnum? really?
+
+</%init>
diff --git a/httemplate/elements/popup_link-cust_svc.html b/httemplate/elements/popup_link-cust_svc.html
new file mode 100644
index 000000000..8255ffc04
--- /dev/null
+++ b/httemplate/elements/popup_link-cust_svc.html
@@ -0,0 +1,47 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/svc_popup_link.html', { #hashref or a list, either way
+
+ #required
+ 'action' => 'content.html', # uri for content of popup which should
+ # be suitable for appending '?svcnum='
+ 'label' => 'click me', # text of <A> tag
+ 'cust_svc' => $cust_svc # a FS::cust_svc object
+
+ #strongly recommended (you want a title, right?)
+ 'actionlabel => 'You clicked', # popup title
+
+ #opt
+ 'width' => '540',
+ 'color' => '#ff0000',
+ 'closetext' => 'Go Away', # the value '' removes the link
+ )
+
+</%doc>
+% if ( $params->{'cust_svc'} ) {
+<% include( '/elements/popup_link.html', $params ) %>\
+% }
+<%init>
+
+my $params = { 'closetext' => 'Close',
+ 'width' => 392,
+ };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'action'} .=
+ ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
+ 'svcnum='. $params->{'cust_svc'}->svcnum;
+
+$params->{'actionlabel'} .=
+ ' service '. $params->{'cust_svc'}->svcnum; #XXX svcnum? really?
+
+</%init>
diff --git a/httemplate/elements/popup_link.html b/httemplate/elements/popup_link.html
new file mode 100644
index 000000000..20193873f
--- /dev/null
+++ b/httemplate/elements/popup_link.html
@@ -0,0 +1,49 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/popup_link.html', { #hashref or a list, either way is fine
+
+ #required
+ 'action' => 'content.html', # uri for content of popup
+ 'label' => 'click me', # text of <A> tag
+
+ #strongly recommended
+ 'actionlabel => 'You clicked', # popup title
+
+ #opt
+ 'width' => 540,
+ 'height' => 336,
+ 'color' => '#ff0000',
+ 'closetext' => 'Go Away', # the value '' removes the link
+
+ #uncommon opt
+ 'aname' => "target", # link NAME= value, useful for #targets
+ 'target' => '_parent',
+ } )
+
+</%doc>
+% if ($params->{'action'} && $label) {
+<A HREF="javascript:void(0);"
+ onClick="<% $onclick %>"
+ <% $params->{'aname'} ? 'NAME="'. $params->{'aname'}. '"' : '' %>
+ <% $params->{'target'} ? 'TARGET="'. $params->{'target'}. '"' : '' %>
+><% $label %></A>\
+% }
+<%init>
+
+my $params;
+if (ref($_[0]) eq 'HASH') {
+ #$params = { %$params, %{ $_[0] } };
+ $params = shift;
+} else {
+ #$params = { %$params, @_ };
+ $params = { @_ };
+}
+
+my $label = $params->{'label'};
+my $onclick = include('/elements/popup_link_onclick.html', $params);
+
+</%init>
diff --git a/httemplate/elements/popup_link_onclick.html b/httemplate/elements/popup_link_onclick.html
new file mode 100644
index 000000000..f539f4bbd
--- /dev/null
+++ b/httemplate/elements/popup_link_onclick.html
@@ -0,0 +1,74 @@
+<%doc>
+
+Example:
+
+ include('/elements/init_overlib.html')
+
+ include( '/elements/popup_link_onclick.html', { #hashref or a list, either way
+
+ #required
+ 'action' => 'content.html', # uri for content of popup
+
+ #strongly recommended
+ 'actionlabel => 'You clicked', # popup title
+
+ #opt
+ 'width' => 540,
+ 'height' => 336,
+ 'color' => '#ff0000',
+ 'closetext' => 'Go Away', # the value '' removes the link
+
+ #uncommon opt
+ 'frame' => 0, #bool
+ 'scrolling' => 'yes', #scrollbars:
+ # 'auto' (default if omitted), 'yes' or 'no'.
+ 'nofalse' => 0, #bool, eliminates "return false;"
+
+ } )
+
+</%doc>
+% if ($action) {
+<% $onclick %>\
+% }
+<%init>
+
+my( $action, $actionlabel, $frame ) = ( '', '', '' );
+my( $width, $height ) = ( 540, 336 );
+my $closetext = 'Close';
+my $color = '#333399';
+my $scrolling = 'auto';
+
+my $params;
+if (ref($_[0]) eq 'HASH') {
+ #$params = { %$params, %{ $_[0] } };
+ $params = shift;
+} else {
+ #$params = { %$params, @_ };
+ $params = { @_ };
+}
+
+$action = $params->{'action'} if exists $params->{'action'};
+$actionlabel = $params->{'actionlabel'} if exists $params->{'actionlabel'};
+$width = $params->{'width'} if exists $params->{'width'};
+$height = $params->{'height'} if exists $params->{'height'};
+$color = $params->{'color'} if exists $params->{'color'};
+$closetext = $params->{'closetext'} if exists $params->{'closetext'};
+$frame = $params->{'frame'} if exists $params->{'frame'};
+$scrolling = $params->{'scrolling'} if exists $params->{'scrolling'};
+
+#stupid safari is caching the "location" of popup iframs, and submitting them
+#instead of displaying them. this should prevent that.
+my $popup_name = 'popup-'.time. "-$$-". rand() * 2**32;
+
+my $onclick =
+ "overlib( OLiframeContent('$action', $width, $height, '$popup_name', 0, '$scrolling' ), ".
+ "CAPTION, '$actionlabel', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, ".
+ "DRAGGABLE, CLOSECLICK, ".
+ "BGCOLOR, '$color', CGCOLOR, '$color', CLOSETEXT, '$closetext'".
+ ( $frame ? ", FRAME, $frame" : '' ).
+ ");";
+
+$onclick .= " return false;"
+ unless $params->{'nofalse'};
+
+</%init>
diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html
new file mode 100644
index 000000000..194fc7480
--- /dev/null
+++ b/httemplate/elements/progress-init.html
@@ -0,0 +1,87 @@
+<% include('/elements/xmlhttp.html',
+ 'method' => 'POST',
+ 'url' => $action,
+ 'subs' => [ 'start_job' ],
+ 'key' => $key,
+ )
+%>
+
+<% include('/elements/init_overlib.html') %>
+
+<SCRIPT TYPE="text/javascript">
+
+function <%$key%>process () {
+
+ //alert('<%$key%>process for form <%$formname%>');
+
+ if ( document.<%$formname%>.submit.disabled == false ) {
+ document.<%$formname%>.submit.disabled=true;
+ }
+
+ overlib( 'Submitting job to server...', WIDTH, 444, HEIGHT, 168, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
+
+ var Hash = new Array();
+ var x = 0;
+ var fieldName;
+ for (var i = 0; i<document.<%$formname%>.elements.length; i++) {
+ field = document.<%$formname%>.elements[i];
+ if ( <% join(' || ', map { "(field.name.indexOf('$_') > -1)" } @$fields ) %>
+ )
+ {
+ if ( field.type == 'select-multiple' ) {
+ //alert('select-multiple ' + field.name);
+ for (var j=0; j < field.options.length; j++) {
+ if ( field.options[j].selected ) {
+ //alert(field.name + ' => ' + field.options[j].value);
+ Hash[x++] = field.name;
+ Hash[x++] = field.options[j].value;
+ }
+ }
+ } else if ( ( field.type != 'radio' && field.type != 'checkbox' )
+ || ( ( field.type == 'radio' || field.type == 'checkbox' )
+ && document.<%$formname%>.elements[i].checked
+ )
+ )
+ {
+ Hash[x++] = field.name;
+ Hash[x++] = field.value;
+ }
+ }
+ }
+
+ // jsrsPOST = true;
+ // jsrsExecute( '<% $action %>', <%$key%>myCallback, 'start_job', Hash );
+
+ //alert('start_job( ' + Hash + ', <%$key%>myCallback )' );
+ //alert('start_job()' );
+ <%$key%>start_job( Hash, <%$key%>myCallback );
+
+}
+
+function <%$key%>myCallback( jobnum ) {
+
+ overlib( OLiframeContent('<%$p%>elements/progress-popup.html?jobnum=' + jobnum + ';<%$url_or_message_link%>;formname=<%$formname%>' , 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
+
+}
+
+</SCRIPT>
+
+<%init>
+
+my( $formname, $fields, $action, $url_or_message, $key ) = @_;
+$key = '' unless defined $key;
+
+my $url_or_message_link;
+if ( ref($url_or_message) ) { #its a message or something
+ $url_or_message_link = 'message='. uri_escape( $url_or_message->{'message'} );
+ $url_or_message_link .= ';url='. uri_escape( $url_or_message->{'url'} )
+ if $url_or_message->{'url'};
+} else {
+ $url_or_message_link = "url=$url_or_message";
+}
+
+#stupid safari is caching the "location" of popup iframs, and submitting them
+#instead of displaying them. this should prevent that.
+my $popup_name = 'popup-'.time. "-$$-". rand() * 2**32;
+
+</%init>
diff --git a/httemplate/elements/progress-popup.html b/httemplate/elements/progress-popup.html
new file mode 100644
index 000000000..0bd71ff4a
--- /dev/null
+++ b/httemplate/elements/progress-popup.html
@@ -0,0 +1,114 @@
+%
+% my $jobnum = $cgi->param('jobnum');
+% my $url = $cgi->param('url');
+% my $message = $cgi->param('message');
+% my $formname = scalar($cgi->param('formname'));
+%
+
+<HTML>
+ <HEAD>
+ <TITLE></TITLE>
+ </HEAD>
+ <BODY BGCOLOR="#ccccff" onLoad="refreshStatus()">
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'elements/jsrsServer.html',
+ 'subs' => [ 'job_status' ],
+ )
+%>
+<SCRIPT TYPE="text/javascript" src="<%$fsurl%>elements/qlib/control.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" src="<%$fsurl%>elements/qlib/imagelist.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" src="<%$fsurl%>elements/qlib/progress.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript">
+function refreshStatus () {
+ //jsrsExecute( '<%$p%>elements/jsrsServer.html', updateStatus, 'job_status', '<% $jobnum %>' );
+
+ job_status( '<% $jobnum %>', updateStatus );
+}
+function updateStatus( status_statustext ) {
+
+ //var Array = status_statustext.split("\n");
+ var statusArray = eval('(' + status_statustext + ')');
+ var status = statusArray[0];
+ var statustext = statusArray[1];
+
+ //if ( status == 'progress' ) {
+ //IE workaround, no i have no idea why
+ if ( status.indexOf('progress') > -1 ) {
+ document.getElementById("progress_percent").innerHTML = statustext + '%';
+ bar1.set(statustext);
+ bar1.update;
+ //jsrsExecute( '<%$p%>elements/jsrsServer.html', updateStatus, 'job_status', '<% $jobnum %>' );
+ job_status( '<% $jobnum %>', updateStatus );
+ } else if ( status.indexOf('complete') > -1 ) {
+% if ( $message ) {
+%
+% my $onClick = $url
+% ? "window.top.location.href = \\'$url\\';"
+% : 'parent.nd(1);';
+
+ document.getElementById("progress_message").innerHTML = "<% $message %>";
+ document.getElementById("progress_bar").innerHTML = '';
+ document.getElementById("progress_percent").innerHTML =
+ '<INPUT TYPE="button" VALUE="OK" onClick="<% $onClick %>">';
+ document.getElementById("progress_jobnum").innerHTML = '';
+
+% unless ( $url ) {
+ if ( parent.document.<%$formname%>.submit.disabled == true ) {
+ parent.document.<%$formname%>.submit.disabled=false;
+ }
+% }
+
+% } elsif ( $url ) {
+
+ window.top.location.href = '<% $url %>';
+% } else {
+
+ alert('job done but no url or message specified');
+% }
+
+ } else if ( status.indexOf('error') > -1 ) {
+ document.getElementById("progress_message").innerHTML = '<FONT SIZE="+1" COLOR="#FF0000">Error: ' + statustext + '</FONT>';
+ document.getElementById("progress_bar").innerHTML = '';
+ document.getElementById("progress_percent").innerHTML = '<INPUT TYPE="button" VALUE="OK" onClick="parent.nd(1);">';
+ document.getElementById("progress_jobnum").innerHTML = '';
+ if ( parent.document.<%$formname%>.submit.disabled == true ) {
+ parent.document.<%$formname%>.submit.disabled=false;
+ }
+ } else {
+ alert('XXX unknown status returned from server: ' + status);
+ }
+
+}
+</SCRIPT>
+
+ <TABLE WIDTH="100%">
+ <TR>
+ <TD ALIGN="center" ID="progress_message">
+ Server processing job...
+ </TD>
+ </TR><TR>
+ <TD ALIGN="center" ID="progress_bar">
+ <SCRIPT TYPE="text/javascript">
+ // Create imagelist
+ SEGS = new QImageList(4, 23, "<%$fsurl%>images/progressbar-empty.png", "<%$fsurl%>images/progressbar-full.png");
+ // Create bars
+ bar1 = new QProgress(null, "bar1", SEGS, 100);
+ // bar1.set(0);
+ // bar1.update;
+ </SCRIPT>
+ </TD>
+ </TR><TR>
+ <TD ALIGN="center">
+ <DIV ID="progress_percent">%</DIV>
+ </TD>
+ </TR><TR>
+ <TD ALIGN="center" ID="progress_jobnum">
+ (progress of job #<% $jobnum %>)
+ </TD>
+ </TR>
+ </TABLE>
+
+ </BODY>
+</HTML>
+
diff --git a/httemplate/elements/qlib/box.js b/httemplate/elements/qlib/box.js
new file mode 100644
index 000000000..537aac4c8
--- /dev/null
+++ b/httemplate/elements/qlib/box.js
@@ -0,0 +1,29 @@
+/**
+ * QLIB 1.0 Box Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBox(parent, name, res, x, y, width, height, body, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ if (this.res = res) {
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = width - 0;
+ this.height = (typeof(height) == "number") ? height : null;
+ this.body = body || "&nbsp;";
+ var j = QBox.arguments.length;
+ this.visible = (j > 8) ? visible : true;
+ this.effects = (j > 9) ? effects : (res.effects || 0);
+ this.opacity = (j > 10) ? opacity : (res.opacity != null ? res.opacity : 100);
+ this.zindex = (j > 11) ? zindex : null;
+ this.create();
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QBox.prototype = new QBoxCtrl();
diff --git a/httemplate/elements/qlib/boxctrl.js b/httemplate/elements/qlib/boxctrl.js
new file mode 100644
index 000000000..417b204e4
--- /dev/null
+++ b/httemplate/elements/qlib/boxctrl.js
@@ -0,0 +1,48 @@
+/**
+ * QLIB 1.0 Box Abstraction
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBoxCtrl_content() {
+ with (this) {
+ if (res) {
+ this.cwidth = width - res.L - res.R - 8;
+ this.cheight = height && (height - res.T - res.B - 8);
+ var ec = '"><table border="0" cellspacing="0" cellpadding="0"><tr><td></td></tr></table></td>';
+ document.write('<table class="qbox" border="0" cellspacing="0" cellpadding="0" width="' +
+ (width - 8) + (height != null ? '" height="' + (height - 8) : '') + '"><tr><td width="' +
+ res.L + '" height="' + res.T + '"><img src="' + res.TL.src + '" border="0" width="' +
+ res.L + '" height="' + res.T + '"></td><td width="' + cwidth + '" height="' + res.T +
+ '" background="' + res.TC.src + ec + '<td width="' + res.R + '" height="' + res.T +
+ '"><img src="' + res.TR.src + '" border="0" width="' + res.R + '" height="' + res.T +
+ '"></td></tr><tr><td width="' + res.L + (cheight != null ? '" height="' + cheight : '') +
+ '" background="' + res.ML.src + ec + '<td width="' + cwidth + '" bgcolor="' + res.bgcolor +
+ (cheight != null ? '" height="' + cheight : '') + (res.bgtile ? '" background="' +
+ res.bgtile.src : '') + '" align="left" valign="top" class="body" unselectable="on">');
+ if (typeof(body) == "function") {
+ this.body();
+ } else {
+ document.write(body);
+ }
+ document.write('</td><td width="' + res.R + (cheight != null ? '" height="' + cheight : '') +
+ '" background="' + res.MR.src + ec + '</tr><tr><td width="' + res.L + '" height="' + res.B +
+ '"><img src="' + res.BL.src + '" border="0" width="' + res.L + '" height="' + res.B +
+ '"></td><td width="' + cwidth + '" height="' + res.B + '" background="' + res.BC.src + ec +
+ '<td width="' + res.R + '" height="' + res.B + '"><img src="' + res.BR.src +
+ '" border="0" width="' + res.R + '" height="' + res.B + '"></td></tr></table><br>');
+ }
+ }
+}
+
+function QBoxCtrl() {
+ this.res = false;
+ this.body = "&nbsp;";
+ this.cwidth = this.cheight = 0;
+ this.content = QBoxCtrl_content;
+}
+QBoxCtrl.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/boxres.js b/httemplate/elements/qlib/boxres.js
new file mode 100644
index 000000000..087817211
--- /dev/null
+++ b/httemplate/elements/qlib/boxres.js
@@ -0,0 +1,42 @@
+/**
+ * QLIB 1.0 Box Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QBoxRes(t, r, b, l, tc, tr, mr, br, bc, bl, ml, tl, bgcolor, bgtile, effects, opacity) {
+ var args = QBoxRes.arguments.length;
+ this.T = t;
+ this.R = r;
+ this.B = b;
+ this.L = l;
+ this.TC = new Image();
+ this.TC.src = tc;
+ this.TR = new Image(r, t);
+ this.TR.src = tr;
+ this.MR = new Image();
+ this.MR.src = mr;
+ this.BR = new Image(r, b);
+ this.BR.src = br;
+ this.BC = new Image();
+ this.BC.src = bc;
+ this.BL = new Image(l, b);
+ this.BL.src = bl;
+ this.ML = new Image();
+ this.ML.src = ml;
+ this.TL = new Image(l, t);
+ this.TL.src = tl;
+ this.bgcolor = bgcolor || "#FFFFFF";
+ if (bgtile) {
+ this.bgtile = new Image();
+ this.bgtile.src = bgtile;
+ } else {
+ this.bgtile = false;
+ }
+ this.effects = (args > 13) ? effects : null;
+ this.opacity = (args > 14) ? opacity : null;
+}
diff --git a/httemplate/elements/qlib/button.js b/httemplate/elements/qlib/button.js
new file mode 100644
index 000000000..05247d5f8
--- /dev/null
+++ b/httemplate/elements/qlib/button.js
@@ -0,0 +1,74 @@
+/**
+ * QLIB 1.0 Button Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QButton_update() {
+ with (this) {
+ image.src = ((!enabled && res.imgD) || (value ? res.imgP : res.imgN)).src;
+ }
+}
+
+function QButton_doEvent() {
+ with (this) {
+ if (enabled) {
+ if (res.style == 1) {
+ this.value = value ? 0 : 1;
+ update();
+ }
+ onClick(value, tag);
+ }
+ }
+ return false;
+}
+
+function QButton_enable(state) {
+ this.enabled = state;
+ this.update();
+}
+
+function QButton_set(value) {
+ if (this.enabled) {
+ this.value = value ? 1 : 0;
+ this.update();
+ }
+ return true;
+}
+
+function QButton(parent, name, res, tooltip) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.tip = tooltip || "";
+ this.enabled = true;
+ this.value = 0;
+ this.set = QButton_set;
+ this.enable = QButton_enable;
+ this.update = QButton_update;
+ this.doEvent = QButton_doEvent;
+ this.onClick = QControl.event;
+ with (this) {
+ document.write('<a href="#" hidefocus="true" unselectable="on"' +
+ (tip ? ' title="' + tip + '"' : '') + ' onClick="return ' + name +
+ '.doEvent()" onMouseOver="' + (res.style == 2 ? name + '.set(1);' : '') +
+ 'window.top.status=' + name + '.tip;return true" onMouseOut="' +
+ (!res.style || (res.style == 2) ? name + '.set();' : '') + 'window.top.status=\'\'"' +
+ (!res.style ? ' onMouseDown="return ' + name + '.set(1)" onMouseUp="return ' + name + '.set()"' : '') +
+ '><img class="qbutton" name="' + id + '" src="' + res.imgN.src + '" border="0" width="' +
+ res.width + '" height="' + res.height + '"></a>');
+ this.image = document.images[id] || new Image(1, 1);
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QButton.prototype = new QControl();
+QButton.NORMAL = 0;
+QButton.CHECKBOX = 1;
+QButton.WEB = 2;
+QButton.SIGNAL = 3;
diff --git a/httemplate/elements/qlib/buttonres.js b/httemplate/elements/qlib/buttonres.js
new file mode 100644
index 000000000..97f6dfccc
--- /dev/null
+++ b/httemplate/elements/qlib/buttonres.js
@@ -0,0 +1,23 @@
+/**
+ * QLIB 1.0 Button Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QButtonRes(style, width, height, normal, pressed, disabled) {
+ this.style = style;
+ this.width = width;
+ this.height = height;
+ this.imgN = new Image(width, height);
+ this.imgN.src = normal;
+ this.imgP = new Image(width, height);
+ this.imgP.src = pressed;
+ if (disabled) {
+ this.imgD = new Image(width, height);
+ this.imgD.src = disabled;
+ }
+}
diff --git a/httemplate/elements/qlib/control.js b/httemplate/elements/qlib/control.js
new file mode 100644
index 000000000..f50206e27
--- /dev/null
+++ b/httemplate/elements/qlib/control.js
@@ -0,0 +1,51 @@
+/**
+ * QLIB 1.0 Base Abstract Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QControl_init(parent, name) {
+ this.parent = parent || self;
+ this.window = (parent && parent.window) || self;
+ this.document = (parent && parent.document) || self.document;
+ this.name = (parent && parent.name) ? (parent.name + "." + name) : ("self." + name);
+ this.id = "Q";
+ var h = this.hash(this.name);
+ for (var j=0; j<8; j++) {
+ this.id += QControl.HEXTABLE.charAt(h & 15);
+ h >>>= 4;
+ }
+}
+
+function QControl_hash(str) {
+ var h = 0;
+ if (str) {
+ for (var j=str.length-1; j>=0; j--) {
+ h ^= QControl.ANTABLE.indexOf(str.charAt(j)) + 1;
+ for (var i=0; i<3; i++) {
+ var m = (h = h<<7 | h>>>25) & 150994944;
+ h ^= m ? (m == 150994944 ? 1 : 0) : 1;
+ }
+ }
+ }
+ return h;
+}
+
+function QControl_nop() {
+}
+
+function QControl() {
+ this.init = QControl_init;
+ this.hash = QControl_hash;
+ this.window = self;
+ this.document = self.document;
+ this.tag = null;
+}
+QControl.ANTABLE = "w5Q2KkFts3deLIPg8Nynu_JAUBZ9YxmH1XW47oDpa6lcjMRfi0CrhbGSOTvqzEV";
+QControl.HEXTABLE = "0123456789ABCDEF";
+QControl.nop = QControl_nop;
+QControl.event = QControl_nop;
diff --git a/httemplate/elements/qlib/counter.js b/httemplate/elements/qlib/counter.js
new file mode 100644
index 000000000..72aeddbdb
--- /dev/null
+++ b/httemplate/elements/qlib/counter.js
@@ -0,0 +1,81 @@
+/**
+ * QLIB 1.0 Animated Digital Counter
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QCounter_update() {
+ with (this) {
+ var v = Math.max(value, 0);
+ var mod;
+ for (var j=0; j<size; j++) {
+ mod = Math.floor(v % 10);
+ images[j].src = (v >= 1) || (!j) ? res.list[mod].src : res.list[10].src;
+ v /= 10;
+ }
+ }
+}
+
+function QCounter_count(value, step) {
+ this._cntt = false;
+ this.value += step;
+ if ((step * (this.value - value)) >= 0) {
+ this.value = value - 0; // convert to number
+ } else {
+ this._cntt = setTimeout(this.name + ".count(" + value + "," + step + ")", 50);
+ }
+ this.update();
+}
+
+function QCounter_set(value) {
+ this.setval = value;
+ if (value != this.value) {
+ if (this._cntt) {
+ clearTimeout(this._cntt);
+ this._cntt = false;
+ }
+ var dv = value - this.value;
+ if (this.effect == 2) {
+ dv = dv / Math.min(10, Math.abs(dv));
+ } else if (this.effect == 3) {
+ dv = dv / Math.abs(dv);
+ }
+ this.count(value, dv);
+ }
+}
+
+function QCounter(parent, name, res, size, effect) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.setval = this.value = 0;
+ this.size = size || 4;
+ this.effect = effect || 2;
+ this._cntt = false;
+ this.images = new Array(this.size);
+ this.set = QCounter_set;
+ this.update = QCounter_update;
+ this.count = QCounter_count;
+ with (this) {
+ document.write('<table class="qcounter" width="' + (res.width * size) + '" height="' + res.height +
+ '" border="0" cellspacing="0" cellpadding="0" unselectable="on"><tr>');
+ for (var j=(size - 1); j>=0; j--) {
+ document.write('<td width="' + res.width + '" height="' + res.height +
+ '" unselectable="on"><img name="' + id + j + '" src="' + (j ? res.list[10].src : res.list[0].src) +
+ '" border="0" width="' + res.width + '" height="' + res.height + '"></td>');
+ images[j] = document.images[id + j] || new Image(1, 1);
+ }
+ document.write('</tr></table>');
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QCounter.prototype = new QControl();
+QCounter.INSTANT = 1;
+QCounter.FAST = 2;
+QCounter.SLOW = 3;
diff --git a/httemplate/elements/qlib/imagelist.js b/httemplate/elements/qlib/imagelist.js
new file mode 100644
index 000000000..9f12de053
--- /dev/null
+++ b/httemplate/elements/qlib/imagelist.js
@@ -0,0 +1,25 @@
+/**
+ * QLIB 1.0 ImageList Resource
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QImageList(width, height) {
+ var len = QImageList.arguments.length - 2;
+ if (len > 0) {
+ this.list = new Array(len);
+ this.length = len;
+ this.width = width;
+ this.height = height;
+ var im;
+ for (var j=0; j<len; j++) {
+ im = new Image(width, height);
+ im.src = QImageList.arguments[j + 2];
+ this.list[j] = im;
+ }
+ }
+} \ No newline at end of file
diff --git a/httemplate/elements/qlib/label.js b/httemplate/elements/qlib/label.js
new file mode 100644
index 000000000..2d8b1e710
--- /dev/null
+++ b/httemplate/elements/qlib/label.js
@@ -0,0 +1,72 @@
+/**
+ * QLIB 1.0 Text Label
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QLabel_set_ie(value) {
+ this.label.innerText = (this.value = value) || "\xA0";
+}
+
+function QLabel_set_dom2(value) {
+ with (this.label) {
+ replaceChild(this.document.createTextNode((this.value = value) || "\xA0"), firstChild);
+ }
+}
+
+function QLabel_set_ns4(value) {
+ this.value = value || "";
+ with (this) {
+ document.open();
+ document.write('<div class="qlabel">' + (clickable ? '<a href="#" title="' + tooltip + '" onClick="return ' +
+ name + '.doEvent()" onMouseOut="window.top.status=\'\'" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true">' + value + '</a>' : value) + '</div>');
+ document.close();
+ }
+}
+
+function QLabel_doEvent() {
+ this.onClick(this.value, this.tag);
+ return false;
+}
+
+function QLabel(parent, name, value, clickable, tooltip) {
+ this.init(parent, name);
+ this.value = value || "";
+ this.clickable = clickable || false;
+ this.tooltip = tooltip || "";
+ this.doEvent = QLabel_doEvent;
+ this.onClick = QControl.event;
+ with (this) {
+ if (document.getElementById || document.all) {
+ document.write(clickable ? '<div class="qlabel" unselectable="on"><a id="' + id + '" href="#" title="' +
+ tooltip + '" onClick="return ' + name + '.doEvent()" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true" onMouseOut="window.top.status=\'\'" hidefocus="true" unselectable="on">' +
+ (value || '&nbsp;') + '</a></div>' : '<div id="' + id + '" class="qlabel" unselectable="on">' +
+ (value || '&nbsp;') + '</div>');
+ this.label = document.getElementById ? document.getElementById(id) :
+ (document.all.item ? document.all.item(id) : document.all[id]);
+ this.set = (label && (label.innerText ? QLabel_set_ie :
+ (label.replaceChild && QLabel_set_dom2))) || QControl.nop;
+ } else if (document.layers) {
+ var suffix = "";
+ for (var j=value.length; j<QLabel.TEXTQUOTA; j++) suffix += " &nbsp;";
+ document.write('<div><ilayer id="i' + id + '"><layer id="' + id + '"><div class="qlabel">' +
+ (clickable ? '<a href="#" title="' + tooltip + '" onClick="return ' + name +
+ '.doEvent()" onMouseOver="window.top.status=' + name +
+ '.tooltip;return true" onMouseOut="window.top.status=\'\'">' + value + suffix + '</a>' :
+ value + suffix) + '</div></layer></ilayer></div>');
+ this.label = (this.label = document.layers["i" + id]) && label.document.layers[id];
+ this.document = label && label.document;
+ this.set = (label && document) ? QLabel_set_ns4 : QControl.nop;
+ } else {
+ document.write("Object is not supported");
+ }
+ }
+}
+QLabel.prototype = new QControl();
+QLabel.TEXTQUOTA = 50;
diff --git a/httemplate/elements/qlib/messagebox.js b/httemplate/elements/qlib/messagebox.js
new file mode 100644
index 000000000..2e458393d
--- /dev/null
+++ b/httemplate/elements/qlib/messagebox.js
@@ -0,0 +1,57 @@
+/**
+ * QLIB 1.0 Message Box Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QMessageBox_alert(msg) {
+ if (typeof(msg) == "string") {
+ this.label.set(this.value = msg);
+ }
+ this.center();
+ this.focus();
+ this.show(true);
+}
+
+function QMessageBox_close() {
+ with (this.parent) {
+ if (!onClose(tag)) show(false);
+ }
+}
+
+function QMessageBox_body() {
+ with (this) {
+ document.write('<table border="0" width="' + cwidth + '"><tr><td align="left" valign="top" unselectable="on">');
+ this.label = new QLabel(this, "label", value);
+ document.write('</td></tr><tr><td height="' + (bres.height + 14) + '" align="center" valign="bottom" unselectable="on">');
+ this.button = new QButton(this, "button", bres, "Close");
+ document.write('</td></tr></table>');
+ button.onClick = QMessageBox_close;
+ }
+}
+
+function QMessageBox(parent, name, box, btn, msg, effects, opacity) {
+ this.init(parent, name);
+ if ((this.res = box) && (this.bres = btn)) {
+ this.value = typeof(msg) == "string" ? msg : "";
+ this.width = Math.max(200, Math.floor(Math.sqrt(555 * this.value.length)));
+ this.height = null;
+ this.x = this.y = 0;
+ this.visible = false;
+ this.zindex = null;
+ this.body = QMessageBox_body;
+ var j = QMessageBox.arguments.length;
+ this.effects = j > 5 ? effects : (box.effects != null ? box.effects : 0);
+ this.opacity = j > 6 ? opacity : (box.opacity != null ? box.opacity : 100);
+ this.create();
+ this.alert = QMessageBox_alert;
+ this.onClose = QControl.event;
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QMessageBox.prototype = new QBoxCtrl();
diff --git a/httemplate/elements/qlib/progress.js b/httemplate/elements/qlib/progress.js
new file mode 100644
index 000000000..2de077eac
--- /dev/null
+++ b/httemplate/elements/qlib/progress.js
@@ -0,0 +1,73 @@
+/**
+ * QLIB 1.0 Progress Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QProgress_update() {
+ with (this) {
+ var i = low;
+ for (var j=0; j<size; j++) {
+ images[j].src = i < value ? imgsrc1 : imgsrc0;
+ i += delta;
+ }
+ }
+}
+
+function QProgress_set(value) {
+ this.value = value - 0;
+ this.update();
+}
+
+function QProgress_setBounds(low, high) {
+ this.low = Math.min(low, high);
+ this.high = Math.max(low, high);
+ this.delta = (this.high - this.low) / this.size;
+ this.update();
+}
+
+function QProgress(parent, name, res, size, style) {
+ this.init(parent, name);
+ if (res) {
+ this.res = res;
+ this.value = 0;
+ this.low = 0;
+ this.high = 100;
+ this.size = size || 10;
+ this.delta = 100 / this.size;
+ this.style = style || 0;
+ this.images = new Array(this.size);
+ this.imgsrc0 = res.list[0] && res.list[0].src;
+ this.imgsrc1 = res.list[1] && res.list[1].src;
+ this.set = QProgress_set;
+ this.update = QProgress_update;
+ this.setBounds = QProgress_setBounds;
+ with (this) {
+ var hor = this.style < 2;
+ var rev = this.style % 2;
+ document.write('<table class="qprogress" border="0" cellspacing="0" cellpadding="0" unselectable="on" ' +
+ (hor ? 'width="' + (size * res.width) + '" height="' + res.height + '"><tr>' : 'width="' + res.width +
+ '" height="' + (size * res.height) + '">'));
+ for (var j=0; j<size; j++) {
+ document.write((hor ? '' : '<tr>') + '<td width="' + res.width + '" height="' + res.height +
+ '" unselectable="on"><img name="' + id + (rev ? size - j - 1 : j) + '" src="' + res.list[0].src +
+ '" border="0" width="' + res.width + '" height="' + res.height + '"></td>' + (hor ? '' : '</tr>'));
+ }
+ document.write((hor ? '</tr>' : '') + '</table>');
+ for (var j=0; j<size; j++) {
+ images[j] = document.images[id + j] || new Image(1, 1);
+ }
+ }
+ } else {
+ this.document.write("invalid resource");
+ }
+}
+QProgress.prototype = new QControl();
+QProgress.NORMAL = 0;
+QProgress.REVERSE = 1;
+QProgress.FALL = 2;
+QProgress.RISE = 3;
diff --git a/httemplate/elements/qlib/sound.js b/httemplate/elements/qlib/sound.js
new file mode 100644
index 000000000..3d1aaf660
--- /dev/null
+++ b/httemplate/elements/qlib/sound.js
@@ -0,0 +1,47 @@
+/**
+ * QLIB 1.0 Preloaded Sound
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QSound_play(loop) {
+ this._out.loop = loop || 0;
+ this._out.src = this._buf.src;
+}
+
+function QSound_stop() {
+ this._out.loop = 0;
+ this._out.src = "";
+}
+
+function QSound_setVolume(volume) {
+ this._out.volume = this.volume = volume;
+}
+
+function QSound(parent, name, src, volume) {
+ this.init(parent, name);
+ this.volume = volume || 0;
+ this.play = this.stop = this.setVolume = QControl.nop;
+ with (this) {
+ document.write('<bgsound id="' + id + '" src="" volume="' + volume + '">');
+ if (document.all && document.all.item) {
+ this._out = document.all.item(id);
+ if (_out && (typeof _out.src != "undefined") && (_out.volume === volume)) {
+ document.write('<bgsound id="b' + id + '" src="' + src + '" volume="-10000">');
+ this._buf = document.all.item("b" + id);
+ if (_buf) {
+ this.play = QSound_play;
+ this.stop = QSound_stop;
+ this.setVolume = QSound_setVolume;
+
+ _out.onreadystatechange = new Function("alert(0)");
+ }
+ }
+ }
+ }
+}
+QSound.prototype = new QControl();
diff --git a/httemplate/elements/qlib/sprite.js b/httemplate/elements/qlib/sprite.js
new file mode 100644
index 000000000..72a68fb7c
--- /dev/null
+++ b/httemplate/elements/qlib/sprite.js
@@ -0,0 +1,125 @@
+/**
+ * QLIB 1.0 Sprite Object
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QSprite_load(src) {
+ if (src) {
+ this.face = new Image(this.cwidth, this.cheight);
+ this.face.src = src;
+ this.valid = false;
+ }
+}
+
+function QSprite_show(show) {
+ if (show && !this.valid && this.face.complete) {
+ this._img.src = this.face.src;
+ this.valid = true;
+ }
+ this._show(show);
+}
+
+function QSprite_moveTo(x, y) {
+ this.stop();
+ this._move(x, y);
+}
+
+function QSprite_slideTo(x, y) {
+ this.stop();
+ if (this.visible) {
+ this.doSlide(++this._spro, x, y);
+ } else {
+ this.moveTo(x, y);
+ }
+}
+
+function QSprite_shake() {
+ this.stop();
+ if (this.visible) {
+ this.doShake(++this._spro, 0, this.x, this.y);
+ }
+}
+
+function QSprite_stop() {
+ this._spro++;
+ if (this._sprt) {
+ clearTimeout(this._sprt);
+ this._sprt = false;
+ }
+}
+
+function QSprite_doSlide(id, x, y) {
+ if (this._spro == id) {
+ this._sprt = false;
+ var dx = Math.round(x - this.x);
+ var dy = Math.round(y - this.y);
+ if (dx || dy) {
+ if (dx) dx = dx > 0 ? Math.ceil(dx/4) : Math.floor(dx/4);
+ if (dy) dy = dy > 0 ? Math.ceil(dy/4) : Math.floor(dy/4);
+ this._move(this.x + dx, this.y + dy);
+ this._sprt = setTimeout(this.name + ".doSlide(" + id + "," + x + "," + y + ")", 30);
+ } else {
+ this._move(x, y);
+ }
+ }
+}
+
+function QSprite_doShake(id, phase, x, y) {
+ if (this._spro == id) {
+ this._sprt = false;
+ if (phase < 20) {
+ var m = 3 * Math.sin(.16 * phase);
+ this._move(x + m * Math.sin(phase), y + m * Math.cos(phase));
+ this._sprt = setTimeout(this.name + ".doShake(" + id + "," + (++phase) + "," + x + "," + y + ")", 20);
+ } else {
+ this._move(x, y);
+ }
+ }
+}
+
+function QSprite_doClick() {
+ if (!this._sprt) {
+ this.onClick(this.tag);
+ }
+ return false;
+}
+
+function QSprite(parent, name, x, y, width, height, src, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = (this.cwidth = width - 0) + 8;
+ this.height = (this.cheight = height - 0) + 8;
+ var j = QSprite.arguments.length;
+ this.visible = (j > 7) ? visible : true;
+ this.effects = (j > 8) ? effects : 0;
+ this.opacity = (j > 9) ? opacity : 100;
+ this.zindex = (j > 10) ? zindex : null;
+ this.valid = !!src;
+ this.content = '<a href="#" title="" onclick="return false" onmousedown="return ' + this.name +
+ '.doClick()" onmouseover="window.top.status=\'\';return true" hidefocus="true" unselectable="on"><img name="' +
+ this.id + '" src="' + (src || '') + '" border="0" width="' + this.cwidth + '" height="' + this.cheight +
+ '" alt="" unselectable="on"></a>';
+ this.doClick = QSprite_doClick;
+ this.doSlide = QSprite_doSlide;
+ this.doShake = QSprite_doShake;
+ this.onClick = QControl.event;
+ this.create();
+ this.face = this._img = this.document.images[this.id] || new Image(1, 1);
+ this._spro = 0;
+ this._sprt = false;
+ this._show = this.show;
+ this._move = this.moveTo;
+ this.load = QSprite_load;
+ this.show = QSprite_show;
+ this.moveTo = QSprite_moveTo;
+ this.slideTo = QSprite_slideTo;
+ this.shake = QSprite_shake;
+ this.stop = QSprite_stop;
+}
+QSprite.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/window.js b/httemplate/elements/qlib/window.js
new file mode 100644
index 000000000..6056fda9b
--- /dev/null
+++ b/httemplate/elements/qlib/window.js
@@ -0,0 +1,25 @@
+/**
+ * QLIB 1.0 Window Control
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QWindow(parent, name, x, y, width, height, content, visible, effects, opacity, zindex) {
+ this.init(parent, name);
+ this.x = x - 0;
+ this.y = y - 0;
+ this.width = width - 0;
+ this.height = (typeof(height) == "number") ? height : null;
+ this.content = content;
+ var j = QWindow.arguments.length;
+ this.visible = (j > 7) ? visible : true;
+ this.effects = (j > 8) ? effects : 0;
+ this.opacity = (j > 9) ? opacity : 100;
+ this.zindex = (j > 10) ? zindex : null;
+ this.create();
+}
+QWindow.prototype = new QWndCtrl();
diff --git a/httemplate/elements/qlib/wndctrl.js b/httemplate/elements/qlib/wndctrl.js
new file mode 100644
index 000000000..b3bde4e92
--- /dev/null
+++ b/httemplate/elements/qlib/wndctrl.js
@@ -0,0 +1,322 @@
+/**
+ * QLIB 1.0 Window Abstraction
+ * Copyright (C) 2002 2003, Quazzle.com Serge Dolgov
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * http://qlib.quazzle.com
+ */
+
+function QWndCtrl_center_ie4() {
+ var b = this.document.body;
+ this.moveTo(b.scrollLeft + Math.max(0, Math.floor((b.clientWidth -
+ this.width) / 2)), b.scrollTop + 100);
+}
+
+function QWndCtrl_center_moz() {
+ this.moveTo(self.pageXOffset + Math.max(0, Math.floor((self.innerWidth -
+ this.width) / 2)), self.pageYOffset + 100);
+}
+
+function QWndCtrl_setEffects_ie4(fx) {
+ this.effects = fx;
+ with (this.wnd) {
+ filters[0].enabled = (fx & 256) != 0;
+ filters[1].enabled = (fx & 512) != 0;
+ filters[2].enabled = (fx & 1024) != 0;
+ filters[4].enabled = (fx & 2048) != 0;
+ }
+}
+
+function QWndCtrl_setEffects_moz(fx) {
+ this.effects = fx;
+}
+
+function QWndCtrl_setOpacity_ie4(op) {
+ this.opacity = Math.max(0, Math.min(100, Math.floor(op - 0)));
+ this.wnd.filters[3].opacity = this.opacity;
+ this.wnd.filters[3].enabled = (this.opacity < 100);
+}
+
+function QWndCtrl_setOpacity_moz(op) {
+ this.opacity = Math.max(0, Math.min(100, Math.floor(op - 0)));
+ this.wnd.style.MozOpacity = this.opacity + "%";
+}
+
+function QWndCtrl_setSize_css(w, h) {
+ this.wnd.style.width = (this.width = Math.floor(w - 0)) + "px";
+ this.wnd.style.height = typeof(h) == "number" ? (this.height = Math.floor(h)) + "px" : "auto";
+}
+
+function QWndCtrl_setSize_ns4(w, h) {
+ this.wnd.clip.width = this.width = Math.floor(w - 0);
+ if (typeof(h) == "number") {
+ this.wnd.clip.height = this.height = Math.floor(h);
+ }
+}
+
+function QWndCtrl_focus() {
+ this.setZIndex(QWndCtrl.TOPZINDEX++);
+}
+
+function QWndCtrl_setZIndex_css(z) {
+ this.wnd.style.zIndex = this.zindex = z || 0;
+}
+
+function QWndCtrl_setZIndex_ns4(z) {
+ this.wnd.zIndex = this.zindex = z || 0;
+}
+
+function QWndCtrl_moveTo_css(x, y) {
+ this.wnd.style.left = (this.x = Math.floor(x - 0)) + "px";
+ this.wnd.style.top = (this.y = Math.floor(y - 0)) + "px";
+}
+
+function QWndCtrl_moveTo_ns4(x, y) {
+ this.wnd.moveTo(this.x = Math.floor(x - 0), this.y = Math.floor(y - 0));
+}
+
+function QWndCtrl_fxhandler() {
+ this.fxhandler = QControl.nop;
+ this.onShow(this.visible, this.tag);
+}
+
+function QWndCtrl_show_ie4(show) {
+ if (this.visible != show) {
+ var fx = false;
+ switch (show ? this.effects & 15 : (this.effects & 240) >>> 4) {
+ case 1:
+ fx = this.wnd.filters[5];
+ break;
+ case 2:
+ (fx = this.wnd.filters[6]).transition = show ? 1 : 0;
+ break;
+ case 3:
+ (fx = this.wnd.filters[6]).transition = show ? 3 : 2;
+ break;
+ case 4:
+ (fx = this.wnd.filters[6]).transition = show ? 5 : 4;
+ break;
+ case 5:
+ (fx = this.wnd.filters[6]).transition = show ? 14 : 13;
+ break;
+ case 6:
+ (fx = this.wnd.filters[6]).transition = show ? 16 : 15;
+ break;
+ case 7:
+ (fx = this.wnd.filters[6]).transition = 12;
+ break;
+ case 8:
+ (fx = this.wnd.filters[6]).transition = 8;
+ break;
+ case 9:
+ (fx = this.wnd.filters[6]).transition = 9;
+ }
+ if (fx) {
+ fx.apply();
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.fxhandler = QWndCtrl_fxhandler;
+ fx.play(0.3);
+ } else {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_fade_moz(op, step) {
+ this._wndt = false;
+ if (step) {
+ op += step;
+ if ((op > 0) && (op < this.opacity)) {
+ this.wnd.style.MozOpacity = op + "%";
+ this._wndt = setTimeout(this.name + ".fade(" + op + "," + step + ")", 50);
+ } else {
+ if (op <= 0) {
+ this.wnd.style.visibility = "hidden";
+ this.visible = false;
+ }
+ this.wnd.style.MozOpacity = this.opacity + "%";
+ this.onShow(this.visible, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_show_moz(show) {
+ if (this.visible != show) {
+ if (this._wndt) {
+ clearTimeout(this._wndt);
+ this._wndt = false;
+ }
+ var step = show ? ((this.effects & 15) == 1) && Math.floor(this.opacity / 5) :
+ ((this.effects & 240) == 16) && -Math.floor(this.opacity / 5);
+ if (step) {
+ if (this.visible) {
+ this.fade(this.opacity - 0, step);
+ } else {
+ this.wnd.style.MozOpacity = "0%";
+ this.wnd.style.visibility = "visible";
+ this.visible = true;
+ this.fade(0, step);
+ }
+ } else {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+ }
+}
+
+function QWndCtrl_show_css(show) {
+ if (this.visible != show) {
+ this.wnd.style.visibility = (this.visible = show) ? "visible" : "hidden";
+ this.onShow(show, this.tag);
+ }
+}
+
+function QWndCtrl_show_ns4(show) {
+ if (this.visible != show) {
+ this.wnd.visibility = (this.visible = show) ? "show" : "hidden";
+ this.onShow(show, this.tag);
+ }
+}
+
+function QWndCtrl_create_dom2() {
+ with (this) {
+ this.fxhandler = QControl.nop;
+ var ie4 = document.body && document.body.filters;
+ var moz = document.body && document.body.style &&
+ typeof(document.body.style.MozOpacity) == "string";
+ document.write('<div unselectable="on" id="' + id +
+ (ie4 ? '" onfilterchange="' + name + '.fxhandler()': '') +
+ '" style="position:absolute;left:' + x + 'px;top:' + y +
+ 'px;width:' + width + (height != null ? 'px;height:' + height : '') +
+ 'px;visibility:' + (visible ? 'visible' : 'hidden') +
+ ';overflow:hidden' + (zindex ? ';z-index:' + zindex : '') +
+ (ie4 ? ';filter:Gray(enabled=' + (effects & 256 ? '1' : '0') +
+ ') Xray(enabled=' + (effects & 512 ? '1' : '0') +
+ ') Invert(enabled=' + (effects & 1024 ? '1' : '0') +
+ ') alpha(enabled=' + (opacity < 100 ? '1' : '0') + ',opacity=' + opacity +
+ ') shadow(enabled=' + (effects & 2048 ? '1' : '0') +
+ ',direction=135) BlendTrans(enabled=0) RevealTrans(enabled=0)' : '') +
+ (moz && (opacity < 100) ? ';-moz-opacity:' + opacity + '%' : '') +
+ '"><div unselectable="on" class="qwindow">');
+ if (typeof(content) == "function") {
+ this.content();
+ } else {
+ document.write(content);
+ }
+ document.write('</div></div>');
+ if (this.wnd = document.getElementById ? document.getElementById(id) :
+ (document.all.item ? document.all.item(id) : document.all[id])) {
+ if (wnd.style) {
+ ie4 = ie4 && wnd.filters;
+ moz = moz && typeof(wnd.style.MozOpacity) == "string";
+ this.moveTo = QWndCtrl_moveTo_css;
+ this.setZIndex = QWndCtrl_setZIndex_css;
+ this.focus = QWndCtrl_focus;
+ this.setSize = QWndCtrl_setSize_css;
+ this.show = ie4 ? QWndCtrl_show_ie4 : (moz ? QWndCtrl_show_moz : QWndCtrl_show_css);
+ this.fade = moz ? QWndCtrl_fade_moz : QControl.nop;
+ this.setOpacity = ie4 ? QWndCtrl_setOpacity_ie4 : (moz ? QWndCtrl_setOpacity_moz : QControl.nop);
+ this.setEffects = ie4 ? QWndCtrl_setEffects_ie4 : (moz ? QWndCtrl_setEffects_moz : QControl.nop);
+ this.center = self.innerWidth ? QWndCtrl_center_moz :
+ (document.body && document.body.clientWidth ? QWndCtrl_center_ie4 : QControl.nop);
+ }
+ }
+ }
+}
+
+function QWndCtrl_create_ns4(finalize) {
+ with (this) {
+ if (finalize) {
+ if (_wnde) {
+ parent.window.onload = _wnde;
+ parent.window.onload();
+ }
+ document.open();
+ document.write('<div class="qwindow">');
+ this.content();
+ document.write('</div>');
+ document.close();
+ } else {
+ document.write('<layer id="' + id + '" left="' + x + '" top="' + y +
+ '" width="' + width + '" visibility="' + (visible ? 'show' : 'hidden') +
+ (height != null ? '" height="' + height + '" clip="' + width + ',' + height : '') +
+ (zindex ? '" z-index="' + zindex : '') + (typeof(content) != "function" ?
+ '"><div class="qwindow">' + content + '</div></layer>' : '">&nbsp;</layer>'));
+ if (this.window = this.wnd = document.layers[id]) {
+ if (this.document = wnd.document) {
+ this.show = QWndCtrl_show_ns4;
+ this.moveTo = QWndCtrl_moveTo_ns4;
+ this.setZIndex = QWndCtrl_setZIndex_ns4;
+ this.focus = QWndCtrl_focus;
+ this.center = QWndCtrl_center_moz;
+ this.setSize = QWndCtrl_setSize_ns4;
+ if (typeof(content) == "function") {
+ this._wnde = parent.window.onload;
+ parent.window.onload = new Function(name + ".create(true)");
+ }
+ }
+ }
+ }
+ }
+}
+
+function QWndCtrl_create_na() {
+ this.document.write('Object is not supported.');
+ this.wnd = null;
+}
+
+function QWndCtrl_create() {
+ with (this) {
+ this.create = (document.getElementById || document.all) ? QWndCtrl_create_dom2 :
+ (document.layers ? QWndCtrl_create_ns4 : QWndCtrl_create_na);
+ create();
+ }
+}
+
+function QWndCtrl() {
+ this.x = this.y = 0;
+ this.width = this.height = 0;
+ this.content = "";
+ this.visible = true;
+ this.effects = 0;
+ this.opacity = 100;
+ this.zindex = null;
+ this._wndt = this._wnde = false;
+ this.create = QWndCtrl_create;
+ this.show = QControl.nop;
+ this.focus = QControl.nop;
+ this.center = QControl.nop;
+ this.moveTo = QControl.nop;
+ this.setSize = QControl.nop;
+ this.setOpacity = QControl.nop;
+ this.setEffects = QControl.nop;
+ this.setZIndex = QControl.nop;
+ this.onShow = QControl.event;
+}
+QWndCtrl.prototype = new QControl();
+QWndCtrl.TOPZINDEX = 1000;
+QWndCtrl.GRAY = 256;
+QWndCtrl.XRAY = 512;
+QWndCtrl.INVERT = 1024;
+QWndCtrl.SHADOW = 2048;
+QWndCtrl.FADEIN = 1;
+QWndCtrl.FADEOUT = 16;
+QWndCtrl.BOXIN = 2;
+QWndCtrl.BOXOUT = 32;
+QWndCtrl.CIRCLEIN = 3;
+QWndCtrl.CIRCLEOUT = 48;
+QWndCtrl.WIPEIN = 4;
+QWndCtrl.WIPEOUT = 64;
+QWndCtrl.HBARNIN = 5;
+QWndCtrl.HBARNOUT = 80;
+QWndCtrl.VBARNIN = 6;
+QWndCtrl.VBARNOUT = 96;
+QWndCtrl.DISSOLVEIN = 7;
+QWndCtrl.DISSOLVEOUT = 112;
+QWndCtrl.HBLINDSIN = 8;
+QWndCtrl.HBLINDSOUT = 128;
+QWndCtrl.VBLINDSIN = 9;
+QWndCtrl.VBLINDSOUT = 144;
diff --git a/httemplate/elements/search-cust_main.html b/httemplate/elements/search-cust_main.html
new file mode 100644
index 000000000..dbcc2ed0b
--- /dev/null
+++ b/httemplate/elements/search-cust_main.html
@@ -0,0 +1,181 @@
+<INPUT TYPE="hidden" NAME="<% $opt{'field_name'} %>" VALUE="<% $value %>">
+
+<!-- some false laziness w/ misc/batch-cust_pay.html, though not as bad as i'd thought at first... -->
+
+<INPUT TYPE = "text"
+ NAME = "<% $opt{'field_name'} %>_search"
+ ID = "<% $opt{'field_name'} %>_search"
+ SIZE = "32"
+ VALUE="<% $cust_main ? $cust_main->name : '(cust #, name or company)' %>"
+ onFocus="clearhint_<% $opt{'field_name'} %>_search(this);"
+ onClick="clearhint_<% $opt{'field_name'} %>_search(this);"
+ onChange="smart_<% $opt{'field_name'} %>_search(this);"
+>
+
+% if ( $opt{'find_button'} ) {
+ <INPUT TYPE = "button"
+ VALUE = 'Find',
+ NAME = "<% $opt{'field_name'} %>_findbutton"
+ onClick = "smart_<% $opt{'field_name'} %>_search(this.form.<% $opt{'field_name'} %>_search);"
+ >
+% }
+
+<SELECT NAME="<% $opt{'field_name'} %>_select" ID="<% $opt{'field_name'} %>_select" STYLE="color:#ff0000; display:none" onChange="select_<% $opt{'field_name'} %>(this);">
+</SELECT>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi',
+ 'subs' => [ 'smart_search' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function clearhint_<% $opt{'field_name'} %>_search (what) {
+
+ what.style.color = '#000000';
+
+ if ( what.value == '(cust #, name or company)' )
+ what.value = '';
+
+ if ( what.value.indexOf('Customer not found: ') == 0 )
+ what.value = what.value.substr(20);
+
+ }
+
+ function smart_<% $opt{'field_name'} %>_search(what) {
+
+ var customer = what.value;
+
+ if ( customer == 'searching...' || customer == ''
+ || customer.indexOf('Customer not found: ') == 0 )
+ return;
+
+ if ( what.getAttribute('magic') == 'nosearch' ) {
+ what.setAttribute('magic', '');
+ return;
+ }
+
+ //what.value = 'searching...'
+ what.disabled = true;
+ what.style.color= '#000000';
+ what.style.backgroundColor = '#dddddd';
+
+ var customer_select = document.getElementById('<% $opt{'field_name'} %>_select');
+
+ //alert("search for customer " + customer);
+
+ function <% $opt{'field_name'} %>_search_update(customers) {
+
+ //alert('customers returned: ' + customers);
+
+ var customerArray = eval('(' + customers + ')');
+
+ what.disabled = false;
+ what.style.backgroundColor = '#ffffff';
+
+ if ( customerArray.length == 0 ) {
+
+ what.form.<% $opt{'field_name'} %>.value = '';
+
+ what.value = 'Customer not found: ' + what.value;
+ what.style.color = '#ff0000';
+
+ what.style.display = '';
+ customer_select.style.display = 'none';
+
+ } else if ( customerArray.length == 1 ) {
+
+ //alert('one customer found: ' + customerArray[0]);
+
+ what.form.<% $opt{'field_name'} %>.value = customerArray[0][0];
+ what.value = customerArray[0][1];
+
+ what.style.display = '';
+ customer_select.style.display = 'none';
+
+ } else {
+
+ //alert('multiple customers found, have to create select dropdown');
+
+ //blank the current list
+ for ( var i = customer_select.length; i >= 0; i-- )
+ customer_select.options[i] = null;
+
+ opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000');
+
+ //add the multiple customers
+ for ( var s = 0; s < customerArray.length; s++ )
+ opt(customer_select, customerArray[s][0], customerArray[s][1], '#000000');
+
+ opt(customer_select, 'cancel', '(Edit search string)', '#000000');
+
+ what.style.display = 'none';
+ customer_select.style.display = '';
+
+ }
+
+ }
+
+ smart_search( customer, <% $opt{'field_name'} %>_search_update );
+
+
+ }
+
+ function select_<% $opt{'field_name'} %> (what) {
+
+ var custnum = what.options[what.selectedIndex].value;
+ var customer = what.options[what.selectedIndex].text;
+
+ var customer_obj = document.getElementById('<% $opt{'field_name'} %>_search');
+
+ if ( custnum == '' ) {
+ //what.style.color = '#ff0000';
+
+ } else if ( custnum == 'cancel' ) {
+
+ customer_obj.style.color = '#000000';
+
+ what.style.display = 'none';
+ customer_obj.style.display = '';
+ customer_obj.focus();
+
+ } else {
+
+ what.form.<% $opt{'field_name'} %>.value = custnum;
+
+ customer_obj.value = customer;
+ customer_obj.style.color = '#000000';
+
+ what.style.display = 'none';
+ customer_obj.style.display = '';
+
+ }
+
+ }
+
+ function opt(what,value,text,color) {
+ var optionName = new Option(text, value, false, false);
+ optionName.style.color = color;
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+</SCRIPT>
+<%init>
+
+my( %opt ) = @_;
+$opt{'field_name'} ||= 'custnum';
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $cust_main = '';
+if ( $value ) {
+ $cust_main = qsearchs({
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $value },
+ 'extra_sql' => " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql,
+ });
+}
+
+</%init>
diff --git a/httemplate/elements/select-access_group.html b/httemplate/elements/select-access_group.html
new file mode 100644
index 000000000..299a66a45
--- /dev/null
+++ b/httemplate/elements/select-access_group.html
@@ -0,0 +1,16 @@
+%
+% my( $groupnum, %opt ) = @_;
+%
+% %opt{'records'} = delete $opt{'access_group'}
+% if $opt{'access_group'};
+%
+%
+<% include( '/elements/select-table.html',
+ 'table' => 'access_group',
+ 'name_col' => 'groupname',
+ 'value' => $groupnum,
+ 'empty_label' => '(none)',
+ #'hashref' => { 'disabled' => '' },
+ %opt,
+ )
+%>
diff --git a/httemplate/elements/select-agent.html b/httemplate/elements/select-agent.html
new file mode 100644
index 000000000..897c98248
--- /dev/null
+++ b/httemplate/elements/select-agent.html
@@ -0,0 +1,31 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'agent',
+ 'name_col' => 'agent',
+ 'value' => $agentnum || '',
+ 'agent_virt' => 1,
+ 'empty_label' => 'all',
+ 'hashref' => { 'disabled' => '' },
+ 'order_by' => ' ORDER BY agent',
+ 'disable_empty' => $disable_empty,
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $agentnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'records'} = delete $opt{'agents'}
+ if $opt{'agents'};
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $disable_empty = 0;
+if ( $opt{'agent_null_right'} ) {
+ if ( $curuser->access_right($opt{'agent_null_right'}) ) {
+ $disable_empty = 0;
+ } else {
+ $disable_empty = 1;
+ }
+}
+
+</%init>
diff --git a/httemplate/elements/select-agent_type.html b/httemplate/elements/select-agent_type.html
new file mode 100644
index 000000000..ba59cd397
--- /dev/null
+++ b/httemplate/elements/select-agent_type.html
@@ -0,0 +1,21 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'agent_type',
+ 'name_col' => 'atype',
+ 'value' => $typenum || '',
+ 'empty_label' => 'all',
+ 'hashref' => { 'disabled' => '' },
+ #'extra_sql' => ' AND '.
+ # $FS::CurrentUser::CurrentUser->agentnums_sql.
+ # ' ORDER BY agent',
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $typenum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'records'} = delete $opt{'agent_types'}
+ if $opt{'agent_types'};
+
+</%init>
diff --git a/httemplate/elements/select-agent_types.html b/httemplate/elements/select-agent_types.html
new file mode 100644
index 000000000..400b453b3
--- /dev/null
+++ b/httemplate/elements/select-agent_types.html
@@ -0,0 +1,30 @@
+%# if ( $cgi->param('clone') ) { #XXX
+% if ( $opt{'disabled'} ) {
+
+ <INPUT TYPE="hidden" NAME="agent_type" VALUE="">
+
+% } elsif ( scalar(@all_agent_types) == 1) {
+
+ <INPUT TYPE="hidden" NAME="agent_type" VALUE="<% $all_agent_types[0] %>">
+
+% } else {
+
+ <% include( 'select-table.html',
+ 'element_name' => 'agent_type',
+ 'table' => 'agent_type',
+ 'name_col' => 'atype',
+ #'value' => \@agent_type,
+ 'element_etc' => 'size="10"',
+ %opt,
+ 'multiple' => '1', #cause edit.html is dum
+ )
+ %>
+
+% }
+<%init>
+
+my %opt = @_;
+
+my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
+
+</%init>
diff --git a/httemplate/elements/select-areacode.html b/httemplate/elements/select-areacode.html
new file mode 100644
index 000000000..aa2d73b65
--- /dev/null
+++ b/httemplate/elements/select-areacode.html
@@ -0,0 +1,91 @@
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/areacodes.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_areacodes' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $opt{'prefix'} %>state_changed(what, callback) {
+
+ what.form.<% $opt{'prefix'} %>areacode.disabled = 'disabled';
+ what.form.<% $opt{'prefix'} %>areacode.style.display = 'none';
+ var areacodewait = document.getElementById('<% $opt{'prefix'} %>areacodewait');
+ areacodewait.style.display = '';
+ var areacodeerror = document.getElementById('<% $opt{'prefix'} %>areacodeerror');
+ areacodeerror.style.display = 'none';
+
+ what.form.<% $opt{'prefix'} %>exchange.disabled = 'disabled';
+ what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
+
+ state = what.options[what.selectedIndex].value;
+
+ function <% $opt{'prefix'} %>update_areacodes(areacodes) {
+
+ // blank the current areacode
+ for ( var i = what.form.<% $opt{'prefix'} %>areacode.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>areacode.options[i] = null;
+ // blank the current exchange too
+ for ( var i = what.form.<% $opt{'prefix'} %>exchange.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>exchange.options[i] = null;
+ opt(what.form.<% $opt{'prefix'} %>exchange, '', 'Select city / exchange');
+ // blank the current phonenum too
+ for ( var i = what.form.<% $opt{'prefix'} %>phonenum.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>phonenum.options[i] = null;
+ opt(what.form.<% $opt{'prefix'} %>phonenum, '', 'Select phone number');
+
+% if ($opt{empty}) {
+ opt(what.form.<% $opt{'prefix'} %>areacode, '', '<% $opt{empty} %>');
+% }
+
+ // add the new areacodes
+ var areacodeArray = eval('(' + areacodes + ')' );
+ for ( var s = 0; s < areacodeArray.length; s++ ) {
+ var areacodeLabel = areacodeArray[s];
+ if ( areacodeLabel == "" )
+ areacodeLabel = '(n/a)';
+ opt(what.form.<% $opt{'prefix'} %>areacode, areacodeArray[s], areacodeLabel);
+ }
+
+ areacodewait.style.display = 'none';
+ if ( areacodeArray.length >= 1 ) {
+ what.form.<% $opt{'prefix'} %>areacode.disabled = '';
+ what.form.<% $opt{'prefix'} %>areacode.style.display = '';
+ } else {
+ var areacodeerror = document.getElementById('<% $opt{'prefix'} %>areacodeerror');
+ areacodeerror.style.display = '';
+ }
+
+ //run the callback
+ if ( callback != null )
+ callback();
+ }
+
+ // go get the new areacodes
+ <% $opt{'prefix'} %>get_areacodes( state, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_areacodes );
+
+ }
+
+</SCRIPT>
+
+<DIV ID="areacodewait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding area codes</B></DIV>
+
+<DIV ID="areacodeerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different state</B></DIV>
+
+<SELECT NAME="<% $opt{'prefix'} %>areacode" onChange="<% $opt{'prefix'} %>areacode_changed(this); <% $opt{'onchange'} %>" <% $opt{'disabled'} %>>
+ <OPTION VALUE="">Select area code</OPTION>
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{disabled} = 'disabled' unless exists $opt{disabled};
+
+</%init>
diff --git a/httemplate/elements/select-cdrbatch.html b/httemplate/elements/select-cdrbatch.html
new file mode 100644
index 000000000..866ba2516
--- /dev/null
+++ b/httemplate/elements/select-cdrbatch.html
@@ -0,0 +1,38 @@
+% if ( scalar(@{ $opt{'cdrbatches'} }) ) {
+
+ <SELECT NAME="<% $opt{'name'} || 'cdrbatch' %>">
+
+ <OPTION VALUE="__ALL__">All
+ <OPTION VALUE="">(blank)
+
+% foreach my $cdrbatch ( @{ $opt{'cdrbatches'} } ) {
+ <OPTION VALUE="<% $cdrbatch %>"<% $cdrbatch eq $selected_cdrbatch ? ' SELECTED' : '' %>><% $cdrbatch %>
+% }
+
+ </SELECT>
+
+% } else {
+
+ <INPUT TYPE="hidden" NAME="cdrbatch" VALUE="__ALL__">
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $selected_cdrbatch = $opt{'curr_value'}; # || $opt{'value'} necessary?
+
+my $conf = new FS::Conf;
+
+unless ( $opt{'cdrbatches'} ) {
+
+ my $sth = dbh->prepare('SELECT DISTINCT cdrbatch FROM cdr')
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my %cdrbatches = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
+ @{ $opt{'cdrbatches'} } = grep $_, keys %cdrbatches;
+
+}
+
+</%init>
+
diff --git a/httemplate/elements/select-country.html b/httemplate/elements/select-country.html
new file mode 100644
index 000000000..45b0ccd5f
--- /dev/null
+++ b/httemplate/elements/select-country.html
@@ -0,0 +1,127 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-country.html',
+ #recommended
+ country => $current_country,
+
+ #optional
+ prefix => $optional_unique_prefix,
+ onchange => $javascript,
+ disabled => 0, #bool
+ disable_empty => 1, #defaults to 1, disable the empty option
+ empty_label => 'all', #label for empty option
+ disable_stateupdate => 0, #bool - disabled update of the select-state.html
+ style => [ 'attribute:value', 'another:value' ],
+ );
+
+</%doc>
+% unless ( $opt{'disable_stateupdate'} ) {
+
+ <% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/states.cgi',
+ 'subs' => [ $pre. 'get_states' ],
+ )
+ %>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $pre %>country_changed(what, callback) {
+
+ country = what.options[what.selectedIndex].value;
+
+ function <% $pre %>update_states(states) {
+
+ // blank the current state list
+ for ( var i = what.form.<% $pre %>state.length; i >= 0; i-- )
+ what.form.<% $pre %>state.options[i] = null;
+
+ // add the new states
+ var statesArray = eval('(' + states + ')' );
+ for ( var s = 0; s < statesArray.length; s=s+2 ) {
+ var stateLabel = statesArray[s+1];
+ if ( stateLabel == "" )
+ stateLabel = '(n/a)';
+ opt(what.form.<% $pre %>state, statesArray[s], stateLabel);
+ }
+
+ //run the callback
+ if ( callback != null )
+ callback();
+ }
+
+ // go get the new states
+ <% $pre %>get_states( country, <% $pre %>update_states );
+
+ }
+
+ </SCRIPT>
+
+% }
+
+<SELECT NAME = "<% $pre %>country"
+ ID = "<% $pre %>country"
+ onChange = "<% $onchange %>"
+ <% $opt{'disabled'} %>
+ <% $style %>
+>
+
+% unless ( $opt{'disable_empty'} ) {
+ <OPTION VALUE=""><% $opt{'empty_label'} || '(all)' %>
+% }
+
+% foreach my $country ( @all_countries ) {
+
+ <OPTION VALUE="<% $country |h %>"
+ <% $country eq $opt{'country'} ? ' SELECTED' : '' %>
+ ><% code2country($country). " ($country)" %>
+
+% }
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+foreach my $opt (qw( country prefix onchange disabled disable_stateupdate )) {
+ $opt{$opt} = '' unless exists($opt{$opt}) && defined($opt{$opt});
+}
+
+$opt{'disable_empty'} = 1 unless exists($opt{'disable_empty'});
+
+my $pre = $opt{'prefix'};
+
+my $onchange =
+ ( $opt{'disable_stateupdate'} ? '' : $pre.'country_changed(this); ' ).
+ $opt{'onchange'};
+
+$opt{'style'} ||= [];
+my $style =
+ scalar(@{$opt{style}})
+ ? 'STYLE="'. join(';', @{$opt{style}}). '"'
+ : '';
+
+my $conf = new FS::Conf;
+my $default = $conf->config('countrydefault') || 'US';
+
+my @all_countries = (
+ sort { ($b eq $default) <=> ($a eq $default)
+ or code2country($a) cmp code2country($b)
+ }
+ map { $_->country }
+ qsearch({
+ 'select' => 'country',
+ 'table' => 'cust_main_county',
+ 'hashref' => {},
+ 'extra_sql' => 'GROUP BY country',
+ })
+ );
+
+</%init>
diff --git a/httemplate/elements/select-county.html b/httemplate/elements/select-county.html
new file mode 100644
index 000000000..59f235a23
--- /dev/null
+++ b/httemplate/elements/select-county.html
@@ -0,0 +1,160 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-county.html',
+ #recommended
+ country => $current_country,
+ state => $current_state,
+ county => $current_county,
+
+ #optional
+ prefix => $optional_unique_prefix,
+ onchange => $javascript,
+ disabled => 0, #bool
+ disable_empty => 1, #defaults to 1, disable the empty option
+ empty_label => 'all', #label for empty option
+ style => [ 'attribute:value', 'another:value' ],
+ );
+
+</%doc>
+% if ( $countyflag ) {
+
+ <% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/counties.cgi',
+ 'subs' => [ $pre. 'get_counties' ],
+ )
+ %>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $pre %>state_changed(what, callback) {
+
+ state = what.options[what.selectedIndex].value;
+ country = what.form.<% $pre %>country.options[what.form.<% $pre %>country.selectedIndex].value;
+
+ function <% $pre %>update_counties(counties) {
+
+ // blank the current county list
+ for ( var i = what.form.<% $pre %>county.length; i >= 0; i-- )
+ what.form.<% $pre %>county.options[i] = null;
+
+ // add the new counties
+ var countiesArray = eval('(' + counties + ')' );
+ for ( var s = 0; s < countiesArray.length; s++ ) {
+ var countyLabel = countiesArray[s];
+ if ( countyLabel == "" )
+ countyLabel = '(n/a)';
+ opt(what.form.<% $pre %>county, countiesArray[s], countyLabel);
+ }
+
+ var countyFormLabel = document.getElementById('<% $pre %>countylabel');
+
+ if ( countiesArray.length > 1 ) {
+ what.form.<% $pre %>county.style.display = '';
+ countyFormLabel.style.visibility = 'visible';
+ } else {
+ what.form.<% $pre %>county.style.display = 'none';
+ countyFormLabel.style.visibility = 'hidden';
+ }
+
+ //run the callback
+ if ( callback != null )
+ callback();
+ }
+
+ // go get the new counties
+ <% $pre %>get_counties( state, country, <% $pre %>update_counties );
+
+ }
+
+ </SCRIPT>
+
+ <SELECT NAME = "<% $pre %>county"
+ ID = "<% $pre %>county"
+ onChange= "<% $opt{'onchange'} %>"
+ <% $opt{'disabled'} %>
+ <% $style %>
+ >
+
+% unless ( $opt{'disable_empty'} ) {
+ <OPTION VALUE="" <% $opt{county} eq '' ? 'SELECTED' : '' %>><% $opt{empty_label} %>
+% }
+
+% foreach my $county ( @counties ) {
+
+ <OPTION VALUE="<% $county |h %>"
+ <% $county eq $opt{'county'} ? 'SELECTED' : '' %>
+ ><% $county eq $opt{'empty_data_value'} ? $opt{'empty_data_label'} : $county %>
+
+% }
+
+ </SELECT>
+
+% } else {
+
+ <SCRIPT TYPE="text/javascript">
+ function <% $pre %>state_changed(what) {
+ }
+ </SCRIPT>
+
+ <SELECT NAME = "<% $pre %>county"
+ ID = "<% $pre %>county"
+ STYLE = "display:none"
+ >
+ <OPTION SELECTED VALUE="<% $opt{'county'} |h %>">
+ </SELECT>
+
+% }
+
+<%init>
+
+my %opt = @_;
+foreach my $opt (qw( county state country prefix onchange disabled
+ empty_value )) {
+ $opt{$opt} = '' unless exists($opt{$opt}) && defined($opt{$opt});
+}
+
+$opt{'disable_empty'} = 1 unless exists($opt{'disable_empty'});
+
+my $pre = $opt{'prefix'};
+
+$opt{'style'} ||= [];
+my $style =
+ scalar(@{$opt{style}})
+ ? 'STYLE="'. join(';', @{$opt{style}}). '"'
+ : '';
+
+my @counties = ();
+if ( $countyflag ) {
+
+ @counties = map { length($_) ? $_ : $opt{'empty_data_value'} }
+ counties( $opt{'state'}, $opt{'country'} );
+
+ # this is very hacky
+ unless ( scalar(@counties) > 1 ) {
+ if ( $opt{'disabled'} =~ /STYLE=/i ) {
+ $opt{'disabled'} =~ s/STYLE="([^"]+)"/STYLE="$1; display:none"/i;
+ } else {
+ $opt{'disabled'} .= ' STYLE="display:none"';
+ }
+ }
+
+}
+
+</%init>
+<%once>
+
+my $sql = "SELECT COUNT(*) FROM cust_main_county".
+ " WHERE county IS NOT NULL AND county != ''";
+my $sth = dbh->prepare($sql) or die dbh->errstr;
+$sth->execute or die $sth->errstr;
+my $countyflag = $sth->fetchrow_arrayref->[0];
+
+</%once>
diff --git a/httemplate/elements/select-cust-fields.html b/httemplate/elements/select-cust-fields.html
new file mode 100644
index 000000000..98feaf85c
--- /dev/null
+++ b/httemplate/elements/select-cust-fields.html
@@ -0,0 +1,24 @@
+%
+% my( $cust_fields, %opt ) = @_;
+%
+% use FS::ConfDefaults;
+% $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ];
+%
+% tie my %hash, 'Tie::IxHash', @{ $opt{'avail_fields'} };
+%
+%
+
+
+<SELECT NAME="cust_fields">
+
+ <OPTION VALUE="">(configured default)
+%
+% foreach my $value ( keys %hash ) {
+
+
+ <OPTION VALUE="<% $value %>"><% $hash{$value} %>
+% }
+
+
+</SELECT>
+
diff --git a/httemplate/elements/select-cust-part_pkg.html b/httemplate/elements/select-cust-part_pkg.html
new file mode 100644
index 000000000..292662921
--- /dev/null
+++ b/httemplate/elements/select-cust-part_pkg.html
@@ -0,0 +1,41 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-cust-part_pkg.html',
+
+ #required
+ 'cust_main' => $cust_main, #or 'custnum' ?
+
+ #strongly recommended (you want your forms to be "sticky" on errors, right?)
+ 'curr_value' => 'current_value',
+
+ #opt
+ 'part_pkg' => \@records,
+
+ #select-table.html options
+ )
+
+</%doc>
+
+<% include( '/elements/select-part_pkg.html',
+ 'empty_label' => 'Select package', #? need here in case removed
+ #from select-part_pkg ??
+ %opt,
+ )
+%>
+<%init>
+
+my( %opt ) = @_;
+
+my $cust_main = $opt{'cust_main'}
+ or die "cust_main not specified";
+
+$opt{'extra_sql'} .=
+ ' AND ( agentnum IS NOT NULL '.
+ ' OR 0 < ( SELECT COUNT(*) FROM type_pkgs '.
+ ' WHERE typenum = '. $cust_main->agent->typenum.
+ ' AND type_pkgs.pkgpart = part_pkg.pkgpart )'.
+ ' )';
+
+</%init>
diff --git a/httemplate/elements/select-cust_main-status.html b/httemplate/elements/select-cust_main-status.html
new file mode 100644
index 000000000..2e0b6cb24
--- /dev/null
+++ b/httemplate/elements/select-cust_main-status.html
@@ -0,0 +1,30 @@
+<SELECT NAME="<% $opt{'field'} || 'status' %>"
+ <% $opt{'multiple'} ? 'MULTIPLE' : '' %>
+ <% $onchange %>
+>
+
+ <OPTION VALUE="">all
+
+% foreach my $option ( @{ $opt{'statuses'} } ) {
+
+ <OPTION VALUE="<% $option %>"
+ <% $option eq $curr_value ? 'SELECTED' : '' %>
+ ><% $option %>
+
+% }
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{'statuses'} ||= [ FS::cust_main->statuses() ]; # { disabled=>'' } )
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
diff --git a/httemplate/elements/select-cust_pkg-status.html b/httemplate/elements/select-cust_pkg-status.html
new file mode 100644
index 000000000..2d545c047
--- /dev/null
+++ b/httemplate/elements/select-cust_pkg-status.html
@@ -0,0 +1,30 @@
+<SELECT NAME="<% $opt{'field'} || 'status' %>"
+ <% $opt{'multiple'} ? 'MULTIPLE' : '' %>
+ <% $onchange %>
+>
+
+ <OPTION VALUE="">all
+
+% foreach my $option ( @{ $opt{'statuses'} } ) {
+
+ <OPTION VALUE="<% $option %>"
+ <% $option eq $curr_value ? 'SELECTED' : '' %>
+ ><% $option %>
+
+% }
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{'statuses'} ||= [ FS::cust_pkg->statuses() ]; # { disabled=>'' } )
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
diff --git a/httemplate/elements/select-did.html b/httemplate/elements/select-did.html
new file mode 100644
index 000000000..069516476
--- /dev/null
+++ b/httemplate/elements/select-did.html
@@ -0,0 +1,84 @@
+<%doc>
+
+Example:
+
+ include('/elements/select-did.html',
+ 'field' => 'phonenum',
+
+ 'svcpart' => 5,
+ #OR
+ 'object' => $svc_phone,
+ );
+
+</%doc>
+% if ( $use_selector ) {
+
+ <TABLE>
+
+ <TR>
+ <TD>
+ <% include('/elements/select-state.html',
+ 'country' => $country,
+ 'disable_empty' => 0,
+ 'empty_label' => 'Select state',
+ )
+ %>
+ </TD>
+ <TD>
+ <% include('/elements/select-areacode.html',
+ 'svcpart' => $svcpart,
+ 'empty' => 'Select area code',
+ )
+ %>
+ </TD>
+ <TD>
+ <% include('/elements/select-exchange.html',
+ 'svcpart' => $svcpart,
+ 'empty' => 'Select exchange',
+ )
+ %>
+ </TD>
+ <TD>
+ <% include('/elements/select-phonenum.html',
+ 'svcpart' => $svcpart,
+ 'empty' => 'Select phone number',
+ )
+ %>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD><FONT SIZE="-1">State</FONT></TD>
+ <TD><FONT SIZE="-1">Area code</FONT></TD>
+ <TD><FONT SIZE="-1">City / Exchange</FONT></TD>
+ <TD><FONT SIZE="-1">Phone number</FONT></TD>
+ </TR>
+
+ </TABLE>
+
+% } else {
+
+ <% include( '/elements/input-text.html', %opt, 'type'=>'text' ) %>
+
+% }
+<%init>
+
+my %opt = @_;
+
+my $conf = new FS::Conf;
+my $country = $conf->config('countrydefault') || 'US';
+
+#XXX make sure this comes through on errors too
+my $svcpart = $opt{'svcpart'} || $opt{'object'}->svcpart;
+
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @exports = $part_svc->part_export_did;
+if ( scalar(@exports) > 1 ) {
+ die "more than one DID-providing export attached to svcpart $svcpart";
+}
+
+my $use_selector = scalar(@exports) ? 1 : 0;
+
+</%init>
diff --git a/httemplate/elements/select-domain.html b/httemplate/elements/select-domain.html
new file mode 100644
index 000000000..a9998da06
--- /dev/null
+++ b/httemplate/elements/select-domain.html
@@ -0,0 +1,13 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'svc_domain',
+ 'name_col' => 'domain',
+ 'empty_label' => 'all',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ #' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'agent_virt' => 1,
+ 'agent_null-right' => 'View/link unlinked services',
+ @_,
+ )
+%>
diff --git a/httemplate/elements/select-exchange.html b/httemplate/elements/select-exchange.html
new file mode 100644
index 000000000..012e7c6b7
--- /dev/null
+++ b/httemplate/elements/select-exchange.html
@@ -0,0 +1,86 @@
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/exchanges.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_exchanges' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $opt{'prefix'} %>areacode_changed(what, callback) {
+
+ what.form.<% $opt{'prefix'} %>exchange.disabled = 'disabled';
+ what.form.<% $opt{'prefix'} %>exchange.style.display = 'none';
+ var exchangewait = document.getElementById('<% $opt{'prefix'} %>exchangewait');
+ exchangewait.style.display = '';
+ var exchangeerror = document.getElementById('<% $opt{'prefix'} %>exchangeerror');
+ exchangeerror.style.display = 'none';
+
+ what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
+
+ areacode = what.options[what.selectedIndex].value;
+
+ function <% $opt{'prefix'} %>update_exchanges(exchanges) {
+
+ // blank the current exchange
+ for ( var i = what.form.<% $opt{'prefix'} %>exchange.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>exchange.options[i] = null;
+ // blank the current phonenum too
+ for ( var i = what.form.<% $opt{'prefix'} %>phonenum.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>phonenum.options[i] = null;
+ opt(what.form.<% $opt{'prefix'} %>phonenum, '', 'Select phone number');
+
+% if ($opt{empty}) {
+ opt(what.form.<% $opt{'prefix'} %>exchange, '', '<% $opt{empty} %>');
+% }
+
+ // add the new exchanges
+ var exchangeArray = eval('(' + exchanges + ')' );
+ for ( var s = 0; s < exchangeArray.length; s++ ) {
+ var exchangeLabel = exchangeArray[s];
+ if ( exchangeLabel == "" )
+ exchangeLabel = '(n/a)';
+ opt(what.form.<% $opt{'prefix'} %>exchange, exchangeArray[s], exchangeLabel);
+ }
+
+ exchangewait.style.display = 'none';
+ if ( exchangeArray.length >= 1 ) {
+ what.form.<% $opt{'prefix'} %>exchange.disabled = '';
+ what.form.<% $opt{'prefix'} %>exchange.style.display = '';
+ } else {
+ var exchangeerror = document.getElementById('<% $opt{'prefix'} %>exchangeerror');
+ exchangeerror.style.display = '';
+ }
+
+ //run the callback
+ if ( callback != null )
+ callback();
+ }
+
+ // go get the new exchanges
+ <% $opt{'prefix'} %>get_exchanges( areacode, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_exchanges );
+
+ }
+
+</SCRIPT>
+
+<DIV ID="exchangewait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding cities / exchanges</B></DIV>
+
+<DIV ID="exchangeerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different area code</B></DIV>
+
+<SELECT NAME="<% $opt{'prefix'} %>exchange" onChange="<% $opt{'prefix'} %>exchange_changed(this); <% $opt{'onchange'} %>" <% $opt{'disabled'} %>>
+ <OPTION VALUE="">Select city / exchange</OPTION>
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{disabled} = 'disabled' unless exists $opt{disabled};
+
+</%init>
diff --git a/httemplate/elements/select-month_year.html b/httemplate/elements/select-month_year.html
new file mode 100644
index 000000000..34476bc94
--- /dev/null
+++ b/httemplate/elements/select-month_year.html
@@ -0,0 +1,62 @@
+%
+%
+% my %opt = @_;
+%
+% my $prefix = $opt{'prefix'} || '';
+% my $disabled = $opt{'disabled'} || '';
+% my $empty = $opt{'empty_option'} || '';
+% my $start_year = $opt{'start_year'};
+% my $end_year = $opt{'end_year'} || '2037';
+%
+% my @mon;
+% if ( $opt{'show_month_abbr'} ) {
+% @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+% } else {
+% @mon = ( 1 .. 12 );
+% }
+%
+% my $date = $opt{'selected_date'} || '';
+% $date = '' if $date eq '-';
+% #$date ||= '01-2000' unless $empty;
+%
+% my $mon = $opt{'selected_mon'} || 0;
+% my $year = $opt{'selected_year'} || 0;
+% if ( $date ) {
+% if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
+% ( $mon, $year ) = ( $2, $1 );
+% } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+% ( $mon, $year ) = ( $1, $3 );
+% } else {
+% die "unrecognized expiration date format: $date";
+% }
+% }
+%
+% unless ( $start_year ) {
+% my @t = localtime;
+% $start_year = $t[5] + 1900;
+% }
+% $start_year = $year if $start_year > $year && $year > 0;
+%
+%
+
+
+<SELECT NAME="<% $prefix %>_month" SIZE="1" <% $disabled%>>
+
+<% $empty ? '<OPTION VALUE="">' : '' %>
+% foreach ( 1 .. 12 ) {
+
+ <OPTION<% $_ == $mon ? ' SELECTED' : '' %> VALUE="<% $_ %>"><% $mon[$_-1] %>
+% }
+
+
+</SELECT>/<SELECT NAME="<% $prefix %>_year" SIZE="1" <% $disabled%>>
+
+<% $empty ? '<OPTION VALUE="">' : '' %>
+% for ( $start_year .. $end_year ) {
+
+ <OPTION<% $_ == $year ? ' SELECTED' : '' %> VALUE="<% $_ %>"><% $_ %>
+% }
+
+
+</SELECT>
+
diff --git a/httemplate/elements/select-otaker.html b/httemplate/elements/select-otaker.html
new file mode 100644
index 000000000..2a689f39d
--- /dev/null
+++ b/httemplate/elements/select-otaker.html
@@ -0,0 +1,27 @@
+<SELECT NAME="otaker">
+
+% unless ( $opt{'multiple'} || $opt{'disable_empty'} ) {
+ <OPTION VALUE="">all</OPTION>
+% }
+
+% foreach my $otaker ( @{ $opt{'otakers'} } ) {
+ <OPTION VALUE="<% $otaker %>"><% $otaker %></OPTION>
+% }
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+unless ( $opt{'otakers'} ) {
+
+ my $sth = dbh->prepare("SELECT username FROM access_user".
+ " WHERE disabled = '' or disabled IS NULL")
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ $opt{'otakers'} = [ map { $_->[0] } @{$sth->fetchall_arrayref} ];
+
+}
+
+</%init>
diff --git a/httemplate/elements/select-part_pkg.html b/httemplate/elements/select-part_pkg.html
new file mode 100644
index 000000000..52b1ccaf1
--- /dev/null
+++ b/httemplate/elements/select-part_pkg.html
@@ -0,0 +1,38 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-part_pkg.html',
+
+ #strongly recommended (you want your forms to be "sticky" on errors, right?)
+ 'curr_value' => 'current_value',
+
+ #opt
+ 'part_pkg' => \@records,
+
+ #select-table.html options
+ )
+
+</%doc>
+
+<% include( '/elements/select-table.html',
+ 'table' => 'part_pkg',
+ 'agent_virt' => 1,
+ 'agent_null' => 1,
+ 'name_col' => 'pkg',
+ 'empty_label' => 'Select package', #should this be the default?
+ 'label_callback' => sub { shift->pkg_comment },
+ 'hashref' => { 'disabled' => '' },
+ %opt,
+ )
+%>
+<%init>
+
+my( %opt ) = @_;
+
+$opt{'records'} = delete $opt{'part_pkg'}
+ if $opt{'part_pkg'};
+
+$opt{'extra_sql'} .= ' AND '. FS::part_pkg->curuser_pkgs_sql;
+
+</%init>
diff --git a/httemplate/elements/select-part_referral.html b/httemplate/elements/select-part_referral.html
new file mode 100644
index 000000000..c4b8829c8
--- /dev/null
+++ b/httemplate/elements/select-part_referral.html
@@ -0,0 +1,20 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'part_referral',
+ 'name_col' => 'referral',
+ 'value' => $refnum,
+ 'empty_label' => 'Select advertising source',
+ 'hashref' => { 'disabled' => '' },
+ 'extra_sql' => ' AND '.
+ FS::part_referral->acl_agentnum_sql(1),
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $refnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'records'} = delete $opt{'part_referrals'}
+ if $opt{'part_referrals'};
+
+</%init>
diff --git a/httemplate/elements/select-payby.html b/httemplate/elements/select-payby.html
new file mode 100644
index 000000000..3f19cb952
--- /dev/null
+++ b/httemplate/elements/select-payby.html
@@ -0,0 +1,40 @@
+<SELECT NAME="<% $opt{'field'} || 'payby' %>"
+ <% $opt{'multiple'} ? 'MULTIPLE' : '' %>
+ <% $onchange %>
+>
+
+% unless ( $opt{'multiple'} ) {
+ <OPTION VALUE="" <% '' eq $value ? 'SELECTED' : '' %> >all
+% }
+
+% foreach my $option ( keys %{ $opt{'paybys'} } ) {
+% my $sel = ( ref($value) && $value->{$option} ) || $option eq $value;
+
+ <OPTION VALUE="<% $option %>"
+ <% $sel ? 'SELECTED' : '' %>
+ ><% $opt{'paybys'}->{$option} %>
+
+% }
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+my $method = 'payby';
+$method = 'cust_payby' if $opt{'payby_type'} eq 'cust';
+#$method = 'event_payby' if $opt{'payby_type'} eq 'event';
+#$method = 'pay_payby' if $opt{'payby_type'} eq 'pay';
+
+unless ( $opt{'paybys'} ) {
+ tie %{ $opt{'paybys'} }, 'Tie::IxHash', FS::payby->$method();
+}
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
diff --git a/httemplate/elements/select-phonenum.html b/httemplate/elements/select-phonenum.html
new file mode 100644
index 000000000..b98d140e4
--- /dev/null
+++ b/httemplate/elements/select-phonenum.html
@@ -0,0 +1,84 @@
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/phonenums.cgi',
+ 'subs' => [ $opt{'prefix'}. 'get_phonenums' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function <% $opt{'prefix'} %>exchange_changed(what, callback) {
+
+ what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
+ what.form.<% $opt{'prefix'} %>phonenum.style.display = 'none';
+ var phonenumwait = document.getElementById('<% $opt{'prefix'} %>phonenumwait');
+ phonenumwait.style.display = '';
+ var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror');
+ phonenumerror.style.display = 'none';
+
+ exchange = what.options[what.selectedIndex].value;
+
+ function <% $opt{'prefix'} %>update_phonenums(phonenums) {
+
+ // blank the current phonenum
+ for ( var i = what.form.<% $opt{'prefix'} %>phonenum.length; i >= 0; i-- )
+ what.form.<% $opt{'prefix'} %>phonenum.options[i] = null;
+
+% if ($opt{empty}) {
+ opt(what.form.<% $opt{'prefix'} %>phonenum, '', '<% $opt{empty} %>');
+% }
+
+ // add the new phonenums
+ var phonenumArray = eval('(' + phonenums + ')' );
+ for ( var s = 0; s < phonenumArray.length; s++ ) {
+ var phonenumLabel = phonenumArray[s];
+ if ( phonenumLabel == "" )
+ phonenumLabel = '(n/a)';
+ opt(what.form.<% $opt{'prefix'} %>phonenum, phonenumArray[s], phonenumLabel);
+ }
+
+ //var phonenumFormLabel = document.getElementById('<% $opt{'prefix'} %>phonenumlabel');
+
+ what.form.<% $opt{'prefix'} %>phonenum.disabled = '';
+
+ phonenumwait.style.display = 'none';
+ if ( phonenumArray.length >= 1 ) {
+ what.form.<% $opt{'prefix'} %>phonenum.disabled = '';
+ what.form.<% $opt{'prefix'} %>phonenum.style.display = '';
+ } else {
+ var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror');
+ phonenumerror.style.display = '';
+ }
+
+ //run the callback
+ if ( callback != null )
+ callback();
+ }
+
+ // go get the new phonenums
+ <% $opt{'prefix'} %>get_phonenums( exchange, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_phonenums );
+
+ }
+
+</SCRIPT>
+
+<DIV ID="phonenumwait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding phone numbers</B></DIV>
+
+<DIV ID="phonenumerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different city/exchange</B></DIV>
+
+<SELECT NAME="<% $opt{'prefix'} %>phonenum" notonChange="<% $opt{'prefix'} %>phonenum_changed(this); <% $opt{'onchange'} %>" <% $opt{'disabled'} %>>
+ <OPTION VALUE="">Select phone number</OPTION>
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{disabled} = 'disabled' unless exists $opt{disabled};
+
+</%init>
diff --git a/httemplate/elements/select-pkg_class.html b/httemplate/elements/select-pkg_class.html
new file mode 100644
index 000000000..f30259e55
--- /dev/null
+++ b/httemplate/elements/select-pkg_class.html
@@ -0,0 +1,18 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'pkg_class',
+ 'name_col' => 'classname',
+ 'value' => $classnum,
+ 'empty_label' => '(none)',
+ 'hashref' => { 'disabled' => '' },
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'records'} = delete $opt{'pkg_class'}
+ if $opt{'pkg_class'};
+
+</%init>
diff --git a/httemplate/elements/select-rate.html b/httemplate/elements/select-rate.html
new file mode 100644
index 000000000..83a7add06
--- /dev/null
+++ b/httemplate/elements/select-rate.html
@@ -0,0 +1,9 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'rate',
+ 'name_col' => 'ratename',
+ 'empty_label' => 'Select rate plan',
+ #'hashref' => { 'disabled' => '' },
+ 'order_by' => ' ORDER BY ratenum', #ratename ?
+ @_,
+ )
+%>
diff --git a/httemplate/elements/select-state.html b/httemplate/elements/select-state.html
new file mode 100644
index 000000000..9b358e24d
--- /dev/null
+++ b/httemplate/elements/select-state.html
@@ -0,0 +1,66 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-state.html',
+ #recommended
+ country => $current_country,
+ state => $current_state,
+
+ #optional
+ prefix => $optional_unique_prefix,
+ onchange => $javascript,
+ disabled => 0, #bool
+ disable_empty => 1, #defaults to 1, disable the empty option
+ empty_label => 'all', #label for empty option
+ disable_countyupdate => 0, #bool - disabled update of the select-state.html
+ style => [ 'attribute:value', 'another:value' ],
+ );
+
+</%doc>
+
+<SELECT NAME = "<% $pre %>state"
+ ID = "<% $pre %>state"
+ onChange = "<% $onchange %>"
+ <% $opt{'disabled'} %>
+ <% $style %>
+>
+
+% unless ( $opt{'disable_empty'} ) {
+ <OPTION VALUE=""<% $opt{state} eq '' ? ' SELECTED' : '' %>><% $opt{empty_label} %>
+% }
+
+% foreach my $state ( keys %states ) {
+
+ <OPTION VALUE="<% $state |h %>"<% $state eq $opt{'state'} ? ' SELECTED' : '' %>><% $states{$state} || '(n/a)' %>
+
+% }
+
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+foreach my $opt (qw( state country prefix onchange disabled empty_label )) {
+ $opt{$opt} = '' unless exists($opt{$opt}) && defined($opt{$opt});
+}
+
+$opt{'disable_empty'} = 1 unless exists($opt{'disable_empty'});
+
+my $pre = $opt{'prefix'};
+
+my $onchange =
+ ( $opt{'disable_countyupdate'} ? '' : $pre.'state_changed(this); ' ).
+ $opt{'onchange'};
+
+$opt{'style'} ||= [];
+my $style =
+ scalar(@{$opt{style}})
+ ? 'STYLE="'. join(';', @{$opt{style}}). '"'
+ : '';
+
+tie my %states, 'Tie::IxHash', states_hash( $opt{'country'} );
+
+</%init>
+
diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html
new file mode 100644
index 000000000..4efbcbaf3
--- /dev/null
+++ b/httemplate/elements/select-table.html
@@ -0,0 +1,164 @@
+<%doc>
+
+Example:
+
+ include( '/elements/select-table.html',
+
+ ##
+ # required
+ ##
+ 'table' => 'table_name',
+ 'name_col' => 'name_column',
+
+ #strongly recommended (you want your forms to be "sticky" on errors, right?)
+ 'curr_value' => 'current_value',
+ #'value' => #deprecated form of 'curr_value',
+
+ ##
+ # optional
+ ##
+
+ #search params
+ 'hashref' => {},
+ 'addl_from' => '',
+ 'extra_sql' => '',
+ 'agent_virt' => 0, #set true and make sure the result is JOINed to
+ #something with agentnum (usually cust_main)
+ 'agent_null' => 0, #set true to always show un-agented entries
+ 'agent_null_right' => '', #right to see un-agented entries
+ #or
+ 'records' => \@records, #instead of search params
+
+ #basic params controlling the resulting <SELECT>
+ 'pre_options' => [ 'value' => 'option' ], #before normal options
+ 'empty_label' => '', #better specify it though, the default might change
+ 'multiple' => 0, # bool
+ 'disable_empty' => 0, # bool (implied by multiple)
+ 'label_callback' => sub { my $record = shift; return "label"; },
+
+ #more params controlling HTML stuff about the <SELECT>
+ 'element_name' => '', #HTML element name, defaults to the name of
+ # the primary key column
+ 'field' => '', #synonym for element_name
+ 'element_etc' => '', #additional attributes (i.e. "DISABLED") for the
+ #<SELECT> element
+ 'onchange' => '', #javascript code
+
+ #special return options
+ 'js_only' => 0, #set true to return only the JS portions (i.e. nothing)
+ 'html_only' => 0, #set true to return only the HTML portions (no-op, i.e. return everything)
+
+ #debugging
+ 'debug' => 0, #set true to enable
+
+ )
+
+</%doc>
+% unless ( $opt{'js_only'} ) {
+
+<SELECT <% $opt{'multiple'} ? 'MULTIPLE' : '' %>
+ NAME = "<% $opt{'element_name'} || $opt{'field'} || $key %>"
+ ID = "<% $opt{'id'} || $key %>"
+ <% $onchange %>
+ <% $opt{'element_etc'} %>
+>
+
+% while ( @pre_options ) {
+ <OPTION VALUE="<% shift(@pre_options) %>"><% shift(@pre_options) %>
+
+% }
+
+% unless ( $opt{'multiple'} || $opt{'disable_empty'} ) {
+ <OPTION VALUE=""><% $opt{'empty_label'} || 'all' %>
+% }
+
+% foreach my $record ( sort { $a->$name_col() cmp $b->$name_col() } @records ) {
+% my $recvalue = $record->$key();
+ <OPTION VALUE="<% $recvalue %>"
+ <% ref($value) && $value->{$recvalue} || $value == $recvalue
+ ? ' SELECTED' : ''
+ %>
+ ><% $opt{'label_callback'}
+ ? &{ $opt{'label_callback'} }( $record )
+ : $record->$name_col()
+ %>
+% }
+
+</SELECT>
+
+%}
+<%init>
+
+my( %opt ) = @_;
+
+warn "elements/select-table.html: \n". Dumper(%opt)
+ if exists $opt{debug} && $opt{debug};
+
+my $onchange = '';
+if ( $opt{'onchange'} ) {
+ $onchange = $opt{'onchange'};
+ $onchange .= '(this)' unless $onchange =~ /\(\w*\);?$/;
+ $onchange =~ s/\(what\);/\(this\);/g; #ugh, terrible hack. all onchange
+ #callbacks should act the same
+ $onchange = 'onChange="'. $onchange. '"';
+}
+
+my $dbdef_table = dbdef->table($opt{'table'})
+ or die "can't find dbdef for ". $opt{'table'}. " table\n";
+
+my $key = $dbdef_table->primary_key; #? $opt{'primary_key'} ||
+
+my $name_col = $opt{'name_col'};
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+$value = [ split(/\s*,\s*/, $value) ] if $opt{'multiple'} && $value =~ /,/;
+
+#my $addl_from = $opt{'addl_from'} || '';
+my $extra_sql = $opt{'extra_sql'} || '';
+my $hashref = $opt{'hashref'} || {};
+
+if ( $opt{'agent_virt'} ) {
+ $extra_sql .=
+ ( $extra_sql =~ /WHERE/i || scalar(keys %$hashref ) ? ' AND ' : ' WHERE ' ).
+ $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null' => $opt{'agent_null'},
+ 'null_right' => $opt{'agent_null_right'},
+ );
+}
+
+my @records = ();
+if ( $opt{'records'} ) {
+ @records = @{ $opt{'records'} };
+} else {
+ @records = qsearch( {
+ 'table' => $opt{'table'},
+ 'addl_from' => $opt{'addl_from'},
+ 'hashref' => $hashref,
+ 'extra_sql' => $extra_sql,
+ 'order_by' => ( $opt{'order_by'} || "ORDER BY $name_col" ),
+ });
+}
+
+unless ( ! $value
+ or ref($value)
+ or ! exists( $opt{hashref}->{disabled} ) #??
+ or grep { $value == $_->$key() } @records
+ ) {
+ delete $opt{hashref}->{disabled};
+ $opt{hashref}->{$key} = $value;
+ my $record = qsearchs( {
+ 'table' => $opt{table},
+ 'addl_from' => $opt{'addl_from'},
+ 'hashref' => $hashref,
+ 'extra_sql' => $extra_sql,
+ });
+ push @records, $record if $record;
+}
+
+if ( ref( $value ) eq 'ARRAY' ) {
+ $value = { map { $_ => 1 } @$value };
+}
+
+my @pre_options = $opt{pre_options} ? @{ $opt{pre_options} } : ();
+
+</%init>
diff --git a/httemplate/elements/select-taxclass.html b/httemplate/elements/select-taxclass.html
new file mode 100644
index 000000000..2504a5b1d
--- /dev/null
+++ b/httemplate/elements/select-taxclass.html
@@ -0,0 +1,41 @@
+% if ( $conf->exists('enable_taxclasses') ) {
+
+ <SELECT NAME="<% $opt{'name'} || 'taxclass' %>">
+
+% if ( $conf->exists('require_taxclasses') ) {
+ <OPTION VALUE="(select)">Select tax class
+% } else {
+ <OPTION VALUE="">
+% }
+
+% foreach my $taxclass ( @{ $opt{'taxclasses'} } ) {
+ <OPTION VALUE="<% $taxclass %>"<% $taxclass eq $selected_taxclass ? ' SELECTED' : '' %>><% $taxclass %>
+% }
+
+ </SELECT>
+
+% } else {
+
+ <INPUT TYPE="hidden" NAME="taxclass" VALUE="<% $selected_taxclass %>">
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $selected_taxclass = $opt{'curr_value'}; # || $opt{'value'} necessary?
+
+my $conf = new FS::Conf;
+
+unless ( $opt{'taxclasses'} ) {
+
+ #my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
+ my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my %taxclasses = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
+ @{ $opt{'taxclasses'} } = grep $_, keys %taxclasses;
+
+}
+
+</%init>
diff --git a/httemplate/elements/select-taxoverride.html b/httemplate/elements/select-taxoverride.html
new file mode 100644
index 000000000..8b1c528eb
--- /dev/null
+++ b/httemplate/elements/select-taxoverride.html
@@ -0,0 +1,28 @@
+ <INPUT NAME = "<% $name %>"
+ ID = "<% $name %>"
+ TYPE = "hidden"
+ VALUE = "<% $value %>"
+ >
+ <A href="javascript:void(0)" onclick="<% $onclick %>">
+ <% $value ? "Edit $class tax overrides" : "Override $class taxes" %>
+ </A>
+<%init>
+
+my %opt = @_;
+my $name = $opt{element_name} || $opt{field} || 'tax_override';
+my $value = length($opt{curr_value}) ? $opt{curr_value} : $opt{value};
+
+my %usage_class = map { ($_->classnum => $_->classname) }
+ qsearch('usage_class', {});
+$usage_class{setup} = 'Setup';
+$usage_class{recur} = 'Recurring';
+
+my $usage;
+$name =~ /^tax_override_(\w+)$/ && ( $usage = $1 );
+
+my $class = lc($usage_class{$usage} || "Usage class $usage")
+ if $usage;
+
+my $onclick = $opt{onclick} || "overlib( OLiframeContent('part_pkg_taxoverride.html?element_name=$name;selected='+document.getElementById('$name').value, 1100, 600, 'tax_product_popup'), CAPTION, 'Edit $class product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK); return false;";
+
+</%init>
diff --git a/httemplate/elements/select-taxproduct.html b/httemplate/elements/select-taxproduct.html
new file mode 100644
index 000000000..0f6ef5583
--- /dev/null
+++ b/httemplate/elements/select-taxproduct.html
@@ -0,0 +1,28 @@
+<% $opt{'prefix'} %><INPUT NAME = "<% $name %>"
+ ID = "<% $name %>"
+ TYPE = "hidden"
+ VALUE = "<% $value |h %>"
+ >
+ <INPUT NAME = "<% $name %>_description"
+ ID = "<% $name %>_description"
+ TYPE = "text"
+ VALUE = "<% $description %>"
+ SIZE = "12"
+ onClick = "<% $onclick %>"><% $opt{'postfix'} %>
+<%init>
+
+my %opt = @_;
+my $name = $opt{element_name} || $opt{field} || 'taxproductnum';
+my $value = length($opt{curr_value}) ? $opt{curr_value} : $opt{value};
+my $description = $opt{'taxproduct_description'};
+
+unless ( $description || ! $value ) {
+ my $part_pkg_taxproduct =
+ qsearchs( 'part_pkg_taxproduct', { 'taxproductnum'=> $value } );
+ $description = $part_pkg_taxproduct->description
+ if $part_pkg_taxproduct;
+}
+
+my $onclick = $opt{onclick} || "overlib( OLiframeContent('${p}/browse/part_pkg_taxproduct.cgi?_type=select&id=${name}&taxproductnum='+document.getElementById('${name}').value, 1000, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK); return false;";
+
+</%init>
diff --git a/httemplate/elements/selectlayers.html b/httemplate/elements/selectlayers.html
new file mode 100644
index 000000000..82f5dd1a7
--- /dev/null
+++ b/httemplate/elements/selectlayers.html
@@ -0,0 +1,216 @@
+<%doc>
+
+Example:
+
+ include( '/elements/selectlayers.html',
+ 'field' => $key, # SELECT element NAME (passed as form field)
+ # also used as ID and a unique key for layers and
+ # functions
+ 'curr_value' => $selected_layer,
+ 'options' => [ 'option1', 'option2' ],
+ 'labels' => { 'option1' => 'Option 1 Label',
+ 'option2' => 'Option 2 Label',
+ },
+
+ #XXX put this handling it its own selectlayers-fields.html element?
+ 'layer_prefix' => 'prefix_', #optional prefix for fieldnames
+ 'layer_fields' => [ 'layer' => [ 'fieldname',
+ { label => 'fieldname2',
+ type => 'text', #implemented:
+ # text, money, fixed,
+ # hidden, checkbox,
+ # checkbox-multiple,
+ # select, select-agent,
+ # select-pkg_class,
+ # select-part_referral,
+ # select-table,
+ #XXX tbd:
+ # more?
+ },
+ ...
+ ],
+ 'layer2' => [ 'l2fieldname',
+ ...
+ ],
+
+ #current values for layer fields above
+ 'layer_values' => { 'layer' => { 'fieldname' => 'current_value',
+ 'fieldname2' => 'field2value',
+ ...
+ },
+ 'layer2' => { 'l2fieldname' => 'l2value',
+ ...
+ },
+ ...
+ },
+
+ #or manual control, instead of layer_fields and layer_values above
+ #called with args: my( $layer, $layer_fields, $layer_values, $layer_prefix )
+ 'layer_callback' =>
+
+ 'html_between => '', #optional HTML displayed between the SELECT and the
+ #layers, scalar or coderef ('field' passed as a param)
+ 'onchange' => '', #javascript code run when the SELECT changes
+ # ("what" is the element)
+ 'js_only' => 0, #set true to return only the JS portions
+ 'html_only' => 0, #set true to return only the HTML portions
+ 'select_only' => 0, #set true to return only the <SELECT> HTML
+ 'layers_only' => 0, #set true to return only the layers <DIV> HTML
+ )
+
+</%doc>
+% unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
+ <SCRIPT TYPE="text/javascript">
+% }
+% unless ( grep $opt{$_}, qw(html_only select_only layers_only) ) {
+ //alert('start function define');
+ function <% $key %>changed(what) {
+
+ <% $opt{'onchange'} %>
+
+ var <% $key %>layer = what.options[what.selectedIndex].value;
+
+% foreach my $layer ( keys %$options ) {
+
+ if (<% $key %>layer == "<% $layer %>" ) {
+
+% foreach my $not ( grep { $_ ne $layer } keys %$options ) {
+% my $element = "document.getElementById('${key}d$not').style";
+ <% $element %>.display = "none";
+ <% $element %>.zIndex = 0;
+% }
+
+% my $element = "document.getElementById('${key}d$layer').style";
+ <% $element %>.display = "";
+ <% $element %>.zIndex = 1;
+
+ }
+% }
+
+ //<% $opt{'onchange'} %>
+
+ }
+ //alert('end function define');
+% }
+% unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
+ </SCRIPT>
+% }
+%
+% unless ( grep $opt{$_}, qw(js_only layers_only) ) {
+
+ <SELECT NAME = "<% $key %>"
+ ID = "<% $key %>"
+ previousValue = "<% $selected %>"
+ previousText = "<% $options{$selected} %>"
+ onChange="<% $key %>changed(this);"
+ >
+
+% foreach my $option ( keys %$options ) {
+
+ <OPTION VALUE="<% $option %>"
+ <% $option eq $selected ? ' SELECTED' : '' %>
+ ><% $options->{$option} %></OPTION>
+
+% }
+
+ </SELECT>
+
+% }
+% unless ( grep $opt{$_}, qw(js_only select_only layers_only) ) {
+
+<% ref($between) ? &{$between}($key) : $between %>
+
+% }
+%
+% unless ( grep $opt{$_}, qw(js_only select_only) ) {
+
+% foreach my $layer ( keys %$options ) {
+
+ <DIV ID="<% $key %>d<% $layer %>"
+ STYLE="<% $layer eq $selected
+ ? 'display: "" ; z-index: 1'
+ : 'display: none; z-index: 0'
+ %>"
+ >
+
+ <% &{$layer_callback}($layer, $layer_fields, $layer_values, $layer_prefix) %>
+
+ </DIV>
+
+% }
+
+% }
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%once>
+<%init>
+
+my %opt = @_;
+
+#use Data::Dumper;
+#warn Dumper(%opt);
+
+my $key = $opt{field}; # || 'generate_one' #?
+
+tie my %options, 'Tie::IxHash',
+ map { $_ => $opt{'labels'}->{$_} }
+ @{ $opt{'options'} }; #just arrayref for now
+
+my $between = exists($opt{html_between}) ? $opt{html_between} : '';
+my $options = \%options;
+
+my $selected = exists($opt{curr_value}) ? $opt{curr_value} : '';
+
+#XXX eek. also eek $layer_fields in the layer_callback() call...
+my $layer_fields = $opt{layer_fields};
+my $layer_values = $opt{layer_values};
+my $layer_prefix = $opt{layer_prefix};
+
+my $layer_callback = $opt{layer_callback} || \&layer_callback;
+
+sub layer_callback {
+ my( $layer, $layer_fields, $layer_values, $layer_prefix ) = @_;
+
+ return '' unless $layer && exists $layer_fields->{$layer};
+ tie my %fields, 'Tie::IxHash', @{ $layer_fields->{$layer} };
+
+ #XXX this should become an element itself... (false laziness w/edit.html)
+ # but at least all the elements inside are the shared mason elements now
+
+ return '' unless keys %fields;
+ my $html = "<TABLE>";
+
+ foreach my $field ( keys %fields ) {
+
+ my $lf = ref($fields{$field})
+ ? $fields{$field}
+ : { 'label'=>$fields{$field} };
+
+ my $value = $layer_values->{$layer}{$field};
+
+ my $type = $lf->{type} || 'text';
+
+ my $include = $type;
+ $include = "input-$include" if $include =~ /^(text|money)$/;
+ $include = "tr-$include" unless $include eq 'hidden';
+
+ $html .= include( "/elements/$include.html",
+ %$lf,
+ 'field' => "$layer_prefix$field",
+ 'id' => "$layer_prefix$field", #separate?
+ #don't want field0_label0...?
+ 'label_id' => $layer_prefix.$field."_label",
+
+ 'value' => ( $lf->{'value'} || $value ), #hmm.
+ 'curr_value' => $value,
+ );
+
+ }
+ $html .= '</TABLE>';
+ return $html;
+}
+
+</%init>
diff --git a/httemplate/elements/small_custview.html b/httemplate/elements/small_custview.html
new file mode 100644
index 000000000..9060d897d
--- /dev/null
+++ b/httemplate/elements/small_custview.html
@@ -0,0 +1,3 @@
+% my $conf = new FS::Conf;
+
+<% small_custview( shift, shift || scalar($conf->config('countrydefault')), @_ ) %>
diff --git a/httemplate/elements/table-grid.html b/httemplate/elements/table-grid.html
new file mode 100644
index 000000000..e1e6c36dc
--- /dev/null
+++ b/httemplate/elements/table-grid.html
@@ -0,0 +1,25 @@
+<STYLE TYPE="text/css">
+
+.grid table { border: solid; empty-cells: show }
+.grid TH { padding-left: 3px; padding-right: 3px; border: 1px solid #dddddd; border-bottom: dashed 1px black; border-right: none }
+.grid TD { padding-left: 3px; padding-right: 3px; empty-cells: show; border: 1px solid #cccccc; border-bottom: none; border-right: none }
+
+.inv table { border: none }
+.inv TH { border: none }
+.inv TD { border: none }
+
+</STYLE>
+
+<TABLE CLASS="grid" CELLSPACING=<% $opt{cellspacing} %> CELLPADDING=<% $opt{cellpadding} %> BORDER=1 BORDERCOLOR="#000000" <% $opt{bgcolor} %> STYLE="border: solid 1px black; empty-cells: show">
+
+<%init>
+
+my %opt = @_;
+$opt{cellspacing} ||= 0;
+$opt{cellpadding} ||= 0;
+
+$opt{bgcolor} =~ s/^#//;
+$opt{bgcolor} = 'BGCOLOR="#'. $opt{bgcolor}. '"' if length($opt{bgcolor});
+
+</%init>
+
diff --git a/httemplate/elements/table.html b/httemplate/elements/table.html
new file mode 100644
index 000000000..8152b65d8
--- /dev/null
+++ b/httemplate/elements/table.html
@@ -0,0 +1,11 @@
+%
+% my $color = shift;
+% if ( $color ) {
+%
+
+ <TABLE BGCOLOR="<% $color %>" BORDER=1 WIDTH="100%" CELLSPACING=0 CELLPADDING=2 BORDERCOLOR="#999999">
+% } else {
+
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2 BORDERCOLOR="#999999">
+% }
+
diff --git a/httemplate/elements/tablebreak-tr-title.html b/httemplate/elements/tablebreak-tr-title.html
new file mode 100644
index 000000000..ee2831231
--- /dev/null
+++ b/httemplate/elements/tablebreak-tr-title.html
@@ -0,0 +1,14 @@
+</TABLE>
+
+<TABLE <% $id %> BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+
+<% include('tr-title.html', @_ ) %>
+
+<%init>
+
+my %opt = @_;
+
+my $id = '';
+$id = 'ID="'. $opt{'table_id'}. '"' if $opt{'table_id'};
+
+</%init>
diff --git a/httemplate/elements/tr-checkbox-multiple.html b/httemplate/elements/tr-checkbox-multiple.html
new file mode 100644
index 000000000..bb90a820b
--- /dev/null
+++ b/httemplate/elements/tr-checkbox-multiple.html
@@ -0,0 +1,40 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+
+% foreach my $option ( @{ $opt{options} } ) { #just arrayref for now
+
+ <INPUT TYPE = "checkbox"
+ NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id}.'_'.$option %>"
+ VALUE = "<% $option %>"
+ <% ref($value) && $value->{$option} || $value eq $option
+ ? ' CHECKED' : ''
+ %>
+ <% $onchange %>
+
+ >&nbsp;<% $labels->{$option} %>
+
+ <BR>
+
+% }
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $labels = $opt{'option_labels'} || $opt{'labels'};
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-checkbox.html b/httemplate/elements/tr-checkbox.html
new file mode 100644
index 000000000..2e6d1f107
--- /dev/null
+++ b/httemplate/elements/tr-checkbox.html
@@ -0,0 +1,25 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+ <INPUT TYPE = "checkbox"
+ NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id} %>"
+ VALUE = "<% $opt{value} %>"
+ <% $opt{curr_value} eq $opt{value} ? ' CHECKED' : '' %>
+ <% $onchange %>
+ >
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-checkboxes-table.html b/httemplate/elements/tr-checkboxes-table.html
new file mode 100644
index 000000000..0099427be
--- /dev/null
+++ b/httemplate/elements/tr-checkboxes-table.html
@@ -0,0 +1,20 @@
+% unless ( $opt{'js_only'} ) {
+
+ <% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+% }
+
+ <% include( '/elements/checkboxes-table.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+ </TD>
+ </TR>
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-fixed-country.html b/httemplate/elements/tr-fixed-country.html
new file mode 100644
index 000000000..806d92cd6
--- /dev/null
+++ b/httemplate/elements/tr-fixed-country.html
@@ -0,0 +1,10 @@
+<% include('tr-fixed.html', %opt ) %>
+<%init>
+
+my %opt = @_;
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'formatted_value'} = code2country($value). " ($value)";
+
+</%init>
diff --git a/httemplate/elements/tr-fixed-state.html b/httemplate/elements/tr-fixed-state.html
new file mode 100644
index 000000000..eea30ddc5
--- /dev/null
+++ b/httemplate/elements/tr-fixed-state.html
@@ -0,0 +1,10 @@
+<% include('tr-fixed.html', %opt ) %>
+<%init>
+
+my %opt = @_;
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'formatted_value'} = state_label($value, $opt{'object'}->country);
+
+</%init>
diff --git a/httemplate/elements/tr-fixed.html b/httemplate/elements/tr-fixed.html
new file mode 100644
index 000000000..095e1bce9
--- /dev/null
+++ b/httemplate/elements/tr-fixed.html
@@ -0,0 +1,15 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD BGCOLOR="#dddddd" <% $style %>><% $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'} |h %></TD>
+
+</TR>
+
+<% include('hidden.html', %opt ) %>
+
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-freq.html b/httemplate/elements/tr-freq.html
new file mode 100644
index 000000000..cb58bf6b5
--- /dev/null
+++ b/httemplate/elements/tr-freq.html
@@ -0,0 +1,54 @@
+<% include('tr-td-label.html', @_) %>
+
+ <TD <% $style %>>
+
+ <INPUT TYPE = "text"
+ SIZE = "<% $opt{'size'} || 4 %>"
+ NAME = "<% $opt{'field'} || 'freq' %>"
+ ID = "<% $opt{'id'} %>"
+ VALUE = "<% $curr_value %>"
+ >
+
+ <SELECT NAME = "<% $opt{'field'} || 'freq' %>_units">
+% foreach my $freq ( keys %freq ) {
+ <OPTION VALUE="<% $freq %>"
+ <% $freq eq $units ? 'SELECTED' : '' %>
+ ><% $freq{$freq} %>
+% }
+ </SELECT>
+
+ </TD>
+
+</TR>
+
+<%once>
+
+ tie my %freq, 'Tie::IxHash',
+ #'y' => 'years',
+ 'm' => 'months',
+ 'w' => 'weeks',
+ 'd' => 'days',
+ 'h' => 'hours',
+ ;
+
+</%once>
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+my $units = 'm';
+
+if ( $curr_value =~ /^(\d*)([mwdh])$/i ) {
+ $curr_value = $1;
+ $units = lc($2);
+}
+
+</%init>
+
diff --git a/httemplate/elements/tr-input-beginning_ending.html b/httemplate/elements/tr-input-beginning_ending.html
new file mode 100644
index 000000000..8a1dd62a9
--- /dev/null
+++ b/httemplate/elements/tr-input-beginning_ending.html
@@ -0,0 +1,75 @@
+% unless ( $m->count == $previous_request_count ) {
+ <LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
+ <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
+% }
+
+<TR>
+ <TD ALIGN="right">From date: </TD>
+ <TD><INPUT TYPE="text" NAME="<% $opt{prefix} %>beginning" ID="<% $opt{prefix} %>beginning_text" VALUE="" SIZE=<%$size%> MAXLENGTH=<%$maxlength%>> <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $opt{prefix} %>beginning_button" STYLE="cursor: pointer" TITLE="Select date"><IMG SRC="<%$fsurl%>images/calendar-disabled.png" ID="<% $opt{prefix} %>beginning_disabled" STYLE="display:none"><BR><i>m/d/y<% $time_hint %></i></TD>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "<% $opt{prefix} %>beginning_text",
+ ifFormat: "%m/%d/%Y<% $time_format %>",
+ button: "<% $opt{prefix} %>beginning_button",
+ align: "BR"
+ <% $input_time %>
+ });
+</SCRIPT>
+
+% unless ( $opt{layout} =~ /^h/i ) { #horizontal
+
+</TR>
+<TR>
+
+% }
+
+ <TD ALIGN="right">To date: </TD>
+ <TD><INPUT TYPE="text" NAME="<% $opt{prefix} %>ending" ID="<% $opt{prefix} %>ending_text" VALUE="" SIZE=<%$size%> MAXLENGTH=<%$maxlength%>> <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $opt{prefix} %>ending_button" STYLE="cursor: pointer" TITLE="Select date"><IMG SRC="<%$fsurl%>images/calendar-disabled.png" ID="<% $opt{prefix} %>ending_disabled" STYLE="display:none"><BR><i>m/d/y<% $time_hint %></i></TD>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "<% $opt{prefix} %>ending_text",
+ ifFormat: "%m/%d/%Y<% $time_format %>",
+ button: "<% $opt{prefix} %>ending_button",
+ align: "BR"
+ <% $input_time %>
+ });
+</SCRIPT>
+</TR>
+
+<TR>
+ <TD></TD>
+ <TD COLSPAN=<% $opt{layout} =~ /^h/i ? 3 : 1 %>>
+ <FONT SIZE="-1">(leave one or both dates blank for an open-ended search)</FONT>
+ </TD>
+</TR>
+
+<%once>
+
+my $previous_request_count = '';
+
+</%once>
+<%init>
+
+my %opt = @_;
+
+$opt{prefix} = '' unless defined $opt{prefix};
+$opt{prefix} .= '_' if $opt{prefix};
+
+my( $input_time, $time_format, $time_hint ) = ( '', '', '' );
+my( $size, $maxlength ) = ( 11, 10 );
+if ( $opt{'input_time'} ) {
+ $input_time = ', showsTime: true, timeFormat: "12"'; # http://www.dynarch.com/demos/jscalendar/doc/html/reference.html#node_sec_2.3
+ $time_format = ' %k:%M:%S'; # http://www.dynarch.com/demos/jscalendar/doc/html/reference.html#node_sec_5.3.5
+ $time_hint = ' h:m:s';
+ $size = 21;
+ $maxlength = 27;
+}
+
+</%init>
+<%cleanup>
+
+$previous_request_count = $m->count;
+
+</%cleanup>
diff --git a/httemplate/elements/tr-input-date-field.html b/httemplate/elements/tr-input-date-field.html
new file mode 100644
index 000000000..11581d5bc
--- /dev/null
+++ b/httemplate/elements/tr-input-date-field.html
@@ -0,0 +1,40 @@
+
+<LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
+
+<TR>
+ <TD ALIGN="right"><% $label %></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="<% $name %>" ID="<% $name %>_text" VALUE="<% $value %>">
+ <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $name %>_button" STYLE="cursor: pointer" TITLE="Select date">
+ </TD>
+</TR>
+
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "<% $name %>_text",
+ ifFormat: "<% $format %>",
+ button: "<% $name %>_button",
+ align: "BR"
+ });
+</SCRIPT>
+
+
+<%init>
+my($name, $value, $label, $format, $usedatetime) = @_;
+
+$format = "%m/%d/%Y" unless $format;
+$label = $name unless $label;
+
+if ($usedatetime) {
+ my $dt = DateTime->from_epoch(epoch => $value, time_zone => 'floating');
+ $value = $dt->strftime($format)
+ unless $value eq '';
+}else{
+ $value = time2str($format, $value);
+}
+
+</%init>
+
diff --git a/httemplate/elements/tr-input-lessthan_greaterthan.html b/httemplate/elements/tr-input-lessthan_greaterthan.html
new file mode 100644
index 000000000..16c2ed9fc
--- /dev/null
+++ b/httemplate/elements/tr-input-lessthan_greaterthan.html
@@ -0,0 +1,13 @@
+<TR>
+ <TD ALIGN="right"><% $opt{label} %> less than: </TD>
+ <TD><INPUT TYPE="text" NAME="<% $opt{field} %>_lt" SIZE=7></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right"><% $opt{label} %> greater than: </TD>
+ <TD><INPUT TYPE="text" NAME="<% $opt{field} %>_gt" SIZE=7></TD>
+</TR>
+
+<%init>
+ my %opt = @_;
+</%init>
diff --git a/httemplate/elements/tr-input-money.html b/httemplate/elements/tr-input-money.html
new file mode 100644
index 000000000..88014192d
--- /dev/null
+++ b/httemplate/elements/tr-input-money.html
@@ -0,0 +1,13 @@
+<% include('tr-input-text.html', @_,
+ 'type' => 'text',
+ 'prefix' => $money_char,
+ 'size' => 8,
+ )
+%>
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%once>
+
diff --git a/httemplate/elements/tr-input-percentage.html b/httemplate/elements/tr-input-percentage.html
new file mode 100644
index 000000000..ae553a93c
--- /dev/null
+++ b/httemplate/elements/tr-input-percentage.html
@@ -0,0 +1,8 @@
+<% include('tr-input-text.html', @_,
+ 'type' => 'text',
+ 'postfix' => '%',
+ 'size' => 5, #6? check in IE (not a big deal)
+ 'maxlength' => 7,
+ 'text-align' => 'right',
+ )
+%>
diff --git a/httemplate/elements/tr-input-text.html b/httemplate/elements/tr-input-text.html
new file mode 100644
index 000000000..14f1425df
--- /dev/null
+++ b/httemplate/elements/tr-input-text.html
@@ -0,0 +1,13 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $cell_style %>><% include('input-text.html', @_ ) %></TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-justtitle.html b/httemplate/elements/tr-justtitle.html
new file mode 100644
index 000000000..7839a8ce5
--- /dev/null
+++ b/httemplate/elements/tr-justtitle.html
@@ -0,0 +1,11 @@
+<TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1"><% $opt{value} %></FONT>
+ </TH>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/tr-part_pkg_freq.html b/httemplate/elements/tr-part_pkg_freq.html
new file mode 100644
index 000000000..649f8a2d0
--- /dev/null
+++ b/httemplate/elements/tr-part_pkg_freq.html
@@ -0,0 +1,24 @@
+<% include('tr-select.html', @_,
+ 'field' => 'freq',
+ 'options' => \@freq,
+ 'labels' => \%freq,
+ 'curr_value' => $curr_value,
+ )
+%>
+<%init>
+
+my %opt = @_;
+
+my $curr_value = $opt{'curr_value'} || $opt{'freq'};
+
+tie my %freq, 'Tie::IxHash', %{FS::part_pkg->freqs_href()};
+if ( dbdef->table('part_pkg')->column('freq')->type =~ /(int)/i ) {
+ delete $freq{$_} foreach grep { ! /^\d+$/ } keys %freq;
+}
+
+my @freq = keys %freq;
+@freq = grep { /^\d+$/ } @freq
+ if $opt{'month_increments_only'};
+# if exists($plans{$layer}->{'freq'}) && $plans{$layer}->{'freq'} eq 'm';
+
+</%init>
diff --git a/httemplate/elements/tr-password.html b/httemplate/elements/tr-password.html
new file mode 100644
index 000000000..bbc624d8c
--- /dev/null
+++ b/httemplate/elements/tr-password.html
@@ -0,0 +1,4 @@
+<% include('tr-input-text.html', @_,
+ 'type' => 'password',
+ )
+%>
diff --git a/httemplate/elements/tr-pkg_svc.html b/httemplate/elements/tr-pkg_svc.html
new file mode 100644
index 000000000..a9561a11a
--- /dev/null
+++ b/httemplate/elements/tr-pkg_svc.html
@@ -0,0 +1,93 @@
+<TR>
+ <TD BGCOLOR="#e8e8e8" COLSPAN=99>
+
+<% itable('', 4, 1) %><TR><TD VALIGN="top">
+<% $thead %>
+
+%foreach my $part_svc ( @part_svc ) {
+% my $svcpart = $part_svc->svcpart;
+% my $pkg_svc = $pkg_svc{$svcpart}
+% || new FS::pkg_svc ( {
+% 'pkgpart' => $pkgpart,
+% 'svcpart' => $svcpart,
+% 'quantity' => 0,
+% 'primary_svc' => '',
+% } );
+% if ( $cgi->param('error') ) {
+% my $primary_svc = ( $pkg_svc->primary_svc =~ /^Y/i );
+% my $pkg_svc_primary = scalar($cgi->param('pkg_svc_primary'));
+% $pkg_svc->primary_svc('')
+% if $primary_svc && $pkg_svc_primary != $svcpart;
+% $pkg_svc->primary_svc('Y')
+% if ! $primary_svc && $pkg_svc_primary == $svcpart;
+% }
+%
+% push @fixups, "pkg_svc$svcpart";
+%
+% my $quan = 0;
+% if ( $cgi->param("pkg_svc$svcpart") =~ /^\s*(\d+)\s*$/ ) {
+% $quan = $1;
+% } elsif ( $pkg_svc->quantity ) {
+% $quan = $pkg_svc->quantity;
+% }
+
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="pkg_svc<% $svcpart %>" SIZE=7 MAXLENGTH=6 VALUE="<% $quan %>">
+ </TD>
+
+ <TD ALIGN="center">
+ <INPUT TYPE="radio" NAME="pkg_svc_primary" VALUE="<% $svcpart %>" <% $pkg_svc->primary_svc =~ /^Y/i ? ' CHECKED' : '' %>>
+ </TD>
+
+ <TD>
+ <A HREF="part_svc.cgi?<% $part_svc->svcpart %>"><% $part_svc->svc %></A> <% $part_svc->disabled =~ /^Y/i ? ' (DISABLED' : '' %>
+ </TD>
+ </TR>
+% foreach ( 1 .. $columns-1 ) {
+% if ( $count == int( $_ * scalar(@part_svc) / $columns ) ) {
+%
+
+ </TABLE></TD><TD VALIGN="top"><% $thead %>
+% }
+% }
+% $count++;
+%
+% }
+
+</TR></TABLE></TD></TR></TABLE>
+
+ </TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+my $cgi = $opt{'cgi'};
+
+my $thead = "\n\n". ntable('#cccccc', 2).
+ '<TR><TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Quan.</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-2>Primary</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc">Service</TH></TR>';
+
+my $part_pkg = $opt{'object'};
+my $pkgpart = $part_pkg->pkgpart;
+
+my $where = "WHERE disabled IS NULL OR disabled = ''";
+if ( $pkgpart ) {
+ $where .= " OR 0 < ( SELECT quantity FROM pkg_svc
+ WHERE pkg_svc.svcpart = part_svc.svcpart
+ AND pkgpart = $pkgpart
+ )";
+}
+my @part_svc = qsearch('part_svc', {}, '', $where);
+
+#my $q_part_pkg = $clone_part_pkg || $part_pkg;
+#my %pkg_svc = map { $_->svcpart => $_ } $q_part_pkg->pkg_svc;
+my %pkg_svc = map { $_->svcpart => $_ } $part_pkg->pkg_svc;
+
+my @fixups = ();
+my $count = 0;
+my $columns = 3;
+
+</%init>
diff --git a/httemplate/elements/tr-select-access_group.html b/httemplate/elements/tr-select-access_group.html
new file mode 100644
index 000000000..e443ad26a
--- /dev/null
+++ b/httemplate/elements/tr-select-access_group.html
@@ -0,0 +1,22 @@
+%
+% my( $groupnum, %opt ) = @_;
+%
+% $opt{'access_group'} ||= [ qsearch( 'access_group', {} ) ]; # { disabled=>'' } )
+%
+% #warn "***** tr-select-access_group: \n". Dumper(%opt);
+%
+% if ( scalar(@{ $opt{'access_group'} }) == 0 ) {
+
+
+ <INPUT TYPE="hidden" NAME="groupnum" VALUE="">
+% } else {
+
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Access group' %></TD>
+ <TD>
+ <% include( '/elements/select-access_group.html', $groupnum, %opt ) %>
+ </TD>
+ </TR>
+% }
+
diff --git a/httemplate/elements/tr-select-agent.html b/httemplate/elements/tr-select-agent.html
new file mode 100644
index 000000000..fcfa9f300
--- /dev/null
+++ b/httemplate/elements/tr-select-agent.html
@@ -0,0 +1,33 @@
+% if ( scalar(@agents) == 1 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'agentnum' %>" VALUE="<% $agents[0]->agentnum %>">
+
+%# YUCK. empty row so we don't throw g_row in edit.html off :/
+ <TR>
+ </TR>
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Agent' %></TD>
+ <TD>
+ <% include( '/elements/select-agent.html',
+ 'curr_value' => $agentnum,
+ 'agents' => \@agents,
+ %opt,
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $agentnum = $opt{'curr_value'} || $opt{'value'};
+
+my @agents = $opt{'agents'}
+ ? @{ $opt{'agents'} }
+ : $FS::CurrentUser::CurrentUser->agents;
+
+</%init>
diff --git a/httemplate/elements/tr-select-agent_type.html b/httemplate/elements/tr-select-agent_type.html
new file mode 100644
index 000000000..1b0dfd445
--- /dev/null
+++ b/httemplate/elements/tr-select-agent_type.html
@@ -0,0 +1,39 @@
+% if ( scalar(@agent_types) == 1 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'typenum' %>" VALUE="<% $agent_types[0]->typenum %>">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Agent Type' %></TD>
+ <TD>
+ <% include( '/elements/select-agent_type.html',
+ 'curr_value' => $typenum,
+ 'agent_types' => \@agent_types,
+ %opt,
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $typenum = $opt{'curr_value'} || $opt{'value'};
+
+my @agent_types = ();
+if ( $opt{'agent_types'} ) {
+ #@agents = @{ $opt{'agents'} };
+
+ #here is the agent virtualization
+# my $agentnums_href = $FS::CurrentUser::CurrentUser->agentnums_href;
+# @agent_types = grep $agentnums_href->{$_->agentnum}, @{ $opt{'agent_types'} };
+
+ delete $opt{'agent_types'};
+} else {
+# @agents = $FS::CurrentUser::CurrentUser->agents;
+}
+
+</%init>
diff --git a/httemplate/elements/tr-select-agent_types.html b/httemplate/elements/tr-select-agent_types.html
new file mode 100644
index 000000000..efbf386a7
--- /dev/null
+++ b/httemplate/elements/tr-select-agent_types.html
@@ -0,0 +1,19 @@
+% unless ( $opt{'disabled'} || scalar(@all_agent_types) == 1 ) {
+
+<% include('/elements/tr-justtitle.html', value=>'Agent (reseller) types') %>
+
+% }
+
+<TR>
+ <TD COLSPAN=2>
+ <% include('select-agent_types.html', %opt) %>
+ </TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
+
+</%init>
diff --git a/httemplate/elements/tr-select-cdrbatch.html b/httemplate/elements/tr-select-cdrbatch.html
new file mode 100644
index 000000000..21cd00462
--- /dev/null
+++ b/httemplate/elements/tr-select-cdrbatch.html
@@ -0,0 +1,32 @@
+% if ( ! scalar(@{ $opt{'cdrbatches'} }) ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'cdrbatch' %>" VALUE="<% $selected_cdrbatch %>">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'cdrbatch'} || 'CDR Batch: ' %></TD>
+ <TD>
+ <% include( '/elements/select-cdrbatch.html', 'curr_value' => $selected_cdrbatch, %opt ) %>
+ </TD>
+ </TR>
+
+% }
+<%init>
+
+my( %opt ) = @_;
+my $conf = new FS::Conf;
+my $selected_cdrbatch = $opt{'curr_value'}; # || $opt{'value'} necessary?
+
+unless ( $opt{'cdrbatches'} ) {
+
+ my $sth = dbh->prepare('SELECT cdrbatch FROM cdr')
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my %cdrbatches = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
+ @{ $opt{'cdrbatches'} } = grep $_, keys %cdrbatches;
+
+}
+
+</%init>
+
diff --git a/httemplate/elements/tr-select-cust-fields.html b/httemplate/elements/tr-select-cust-fields.html
new file mode 100644
index 000000000..80562fe3d
--- /dev/null
+++ b/httemplate/elements/tr-select-cust-fields.html
@@ -0,0 +1,15 @@
+%
+% my( $cust_fields, %opt ) = @_;
+%
+% use FS::ConfDefaults;
+% $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ];
+%
+%
+
+
+<TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Customer fields' %></TD>
+ <TD>
+ <% include( '/elements/select-cust-fields.html', $cust_fields, %opt ) %>
+ </TD>
+</TR>
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
new file mode 100644
index 000000000..da16dfe1c
--- /dev/null
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -0,0 +1,178 @@
+<%doc>
+
+Example:
+
+ include('/elements/tr-select-cust_location.html',
+ 'cgi' => $cgi,
+ 'cust_main' => $cust_main,
+ )
+
+</%doc>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p.'misc/location.cgi',
+ 'subs' => [ 'get_location' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function locationnum_changed(what) {
+ var locationnum = what.options[what.selectedIndex].value;
+ if ( locationnum == -1 ) {
+
+% for (@location_fields) {
+ what.form.<%$_%>.disabled = false;
+ what.form.<%$_%>.style.backgroundColor = '#ffffff';
+% }
+
+ what.form.address1.value = '';
+ what.form.address2.value = '';
+ what.form.city.value = '';
+ what.form.zip.value = '';
+
+ changeSelect(what.form.country, <% $countrydefault |js_string %>);
+
+ country_changed( what.form.country,
+ fix_state_factory( <% $statedefault |js_string %>,
+ ''
+ )
+ );
+
+ } else {
+
+ if ( locationnum == 0 ) {
+ what.form.address1.value = <% $cust_main->get($prefix.'address1') |js_string %>;
+ what.form.address2.value = <% $cust_main->get($prefix.'address2') |js_string %>;
+ what.form.city.value = <% $cust_main->get($prefix.'city') |js_string %>;
+ what.form.zip.value = <% $cust_main->get($prefix.'zip') |js_string %>;
+
+ changeSelect(what.form.country, <% $cust_main->get($prefix.'country') | js_string %> );
+
+ country_changed( what.form.country,
+ fix_state_factory( <% $cust_main->get($prefix.'state') | js_string %>,
+ <% $cust_main->get($prefix.'county') | js_string %>
+ )
+ );
+
+ } else {
+ get_location( locationnum, update_location );
+ }
+
+%#sleep/wait until dropdowns are updated?
+% for (@location_fields) {
+ what.form.<%$_%>.disabled = true;
+ what.form.<%$_%>.style.backgroundColor = '#dddddd';
+% }
+
+ }
+ }
+
+ function fix_state_factory (state, county) {
+ function fix_state() {
+ var state_el = document.getElementById('state');
+ changeSelect(state_el, state);
+ state_changed(state_el, fix_county_factory(county) );
+ }
+ return fix_state;
+ }
+
+ function fix_county_factory(county) {
+ function fix_county() {
+ var county_el = document.getElementById('county');
+ if ( county.length > 0 ) {
+ changeSelect(county_el, county );
+ } else {
+ county_el.selectedIndex = 0;
+ }
+ }
+ return fix_county;
+ }
+
+ function changeSelect(what, value) {
+ for ( var i=0; i<what.length; i++) {
+ if ( what.options[i].value == value ) {
+ what.selectedIndex = i;
+ }
+ }
+ }
+
+ function update_location( string ) {
+ var hash = eval('('+string+')');
+ document.getElementById('address1').value = hash['address1'];
+ document.getElementById('address2').value = hash['address2'];
+ document.getElementById('city').value = hash['city'];
+ document.getElementById('zip').value = hash['zip'];
+
+ var country_el = document.getElementById('country');
+
+ changeSelect( country_el, hash['country'] );
+
+ country_changed( country_el,
+ fix_state_factory( hash['state'],
+ hash['county']
+ )
+ );
+ }
+
+</SCRIPT>
+
+<TR>
+ <TH ALIGN="right">Service&nbsp;location</TH>
+ <TD COLSPAN=7>
+ <SELECT NAME="locationnum" onChange="locationnum_changed(this);">
+ <OPTION VALUE="">(default service address)
+% foreach my $loc ( $cust_main->cust_location ) {
+ <OPTION VALUE="<% $loc->locationnum %>"
+ <% $locationnum == $loc->locationnum ? 'SELECTED' : '' %>
+ ><% $loc->line |h %>
+% }
+ <OPTION VALUE="-1"
+ <% $locationnum == -1 ? 'SELECTED' : '' %>
+ >Add new location
+ </SELECT>
+ </TD>
+</TR>
+
+<% include('/elements/location.html',
+ 'object' => $cust_location,
+ #'onchange' ? probably not
+ 'disabled' => ( $locationnum == -1 ? '' : 'DISABLED' ),
+ 'no_asterisks' => 1,
+ )
+%>
+
+<%once>
+
+my @location_fields = qw( address1 address2 city county state zip country );
+
+</%once>
+<%init>
+
+my $conf = new FS::Conf;
+my $countrydefault = $conf->config('countrydefault') || 'US';
+my $statedefault = $conf->config('statedefault')
+ || ($countrydefault eq 'US' ? 'CA' : '');
+
+my %opt = @_;
+my $cgi = $opt{'cgi'};
+my $cust_main = $opt{'cust_main'};
+
+my $prefix = length($cust_main->ship_last) ? 'ship_' : '';
+
+$cgi->param('locationnum') =~ /^(\-?\d*)$/ or die "illegal locationnum";
+my $locationnum = $1;
+my $cust_location;
+if ( $locationnum && $locationnum != -1 ) {
+ $cust_location = qsearchs('cust_location', { 'locationnum' => $locationnum } )
+ or die "unknown locationnum";
+} else {
+ $cust_location = new FS::cust_location;
+ if ( $locationnum == -1 ) {
+ $cust_location->$_( $cgi->param($_) ) foreach @location_fields;
+ } else {
+ $cust_location->$_( $cust_main->get($prefix.$_) ) foreach @location_fields;
+ }
+}
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_main-status.html b/httemplate/elements/tr-select-cust_main-status.html
new file mode 100644
index 000000000..6700d7ed9
--- /dev/null
+++ b/httemplate/elements/tr-select-cust_main-status.html
@@ -0,0 +1,29 @@
+<% include ('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+
+ <% include( '/elements/select-cust_main-status.html',
+ 'curr_value' => $curr_value,
+ %opt
+ )
+ %>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+#my $onchange = $opt{'onchange'}
+# ? 'onChange="'. $opt{'onchange'}. '(this)"'
+# : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+$opt{'statuses'} ||= [ FS::cust_main->statuses() ]; # { disabled=>'' } )
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_pkg-status.html b/httemplate/elements/tr-select-cust_pkg-status.html
new file mode 100644
index 000000000..6cc29d0aa
--- /dev/null
+++ b/httemplate/elements/tr-select-cust_pkg-status.html
@@ -0,0 +1,29 @@
+<% include ('tr-td-label.html', 'label' => 'Status', @_ ) %>
+
+ <TD <% $style %>>
+
+ <% include( '/elements/select-cust_pkg-status.html',
+ 'curr_value' => $curr_value,
+ %opt
+ )
+ %>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+#my $onchange = $opt{'onchange'}
+# ? 'onChange="'. $opt{'onchange'}. '(this)"'
+# : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+$opt{'statuses'} ||= [ FS::cust_pkg->statuses() ]; # { disabled=>'' } )
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
diff --git a/httemplate/elements/tr-select-did.html b/httemplate/elements/tr-select-did.html
new file mode 100644
index 000000000..c78403345
--- /dev/null
+++ b/httemplate/elements/tr-select-did.html
@@ -0,0 +1,25 @@
+<% include('tr-td-label.html', @_ ) %>
+
+% if ( $opt{'curr_value'} ne '' ) {
+
+ <TD BGCOLOR="#dddddd" <% $cell_style %>><% $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'} |h %></TD>
+
+ <% include('hidden.html', %opt ) %>
+
+% } else {
+
+ <TD <% $cell_style %>>
+ <% include('/elements/select-did.html', %opt ) %>
+ </TD>
+
+% }
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-select-domain.html b/httemplate/elements/tr-select-domain.html
new file mode 100644
index 000000000..5b8d23771
--- /dev/null
+++ b/httemplate/elements/tr-select-domain.html
@@ -0,0 +1,12 @@
+% #if ( scalar(@domains) < 2 ) {
+% #} else {
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Domain' %></TD>
+ <TD>
+ <% include( '/elements/select-domain.html', %opt) %>
+ </TD>
+ </TR>
+% #}
+<%init>
+ my %opt = @_;
+</%init>
diff --git a/httemplate/elements/tr-select-from_to.html b/httemplate/elements/tr-select-from_to.html
new file mode 100644
index 000000000..083243d40
--- /dev/null
+++ b/httemplate/elements/tr-select-from_to.html
@@ -0,0 +1,52 @@
+%
+%
+% #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+% my ($curmon,$curyear) = (localtime(time))[4,5];
+%
+% #find first month
+% my $syear = 1899+$curyear;
+% my $smonth = $curmon+1;
+%
+% #want 12 month by default, not 13
+% $smonth++;
+% if ( $smonth > 12 ) { $smonth-=12; $syear++ }
+%
+% #find last month
+% my $eyear = 1900+$curyear;
+% my $emonth = $curmon+1;
+%
+% my %hash = (
+% 'show_month_abbr' => 1,
+% 'start_year' => '1999',
+% 'end_year' => '2012', #haha, well...
+% @_,
+% );
+%
+%
+
+
+<TR>
+ <TD ALIGN="right">From: </TD>
+ <TD>
+ <% include('/elements/select-month_year.html',
+ 'prefix' => 'start',
+ 'selected_mon' => $smonth,
+ 'selected_year' => $syear,
+ %hash,
+ )
+ %>
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">To: </TD>
+ <TD>
+ <% include('/elements/select-month_year.html',
+ 'prefix' => 'end',
+ 'selected_mon' => $emonth,
+ 'selected_year' => $eyear,
+ %hash,
+ )
+ %>
+ </TD>
+</TR>
diff --git a/httemplate/elements/tr-select-invoice_template.html b/httemplate/elements/tr-select-invoice_template.html
new file mode 100644
index 000000000..7ba8d9907
--- /dev/null
+++ b/httemplate/elements/tr-select-invoice_template.html
@@ -0,0 +1,39 @@
+<% include('tr-td-label.html', @_) %>
+
+ <TD <% $style %>>
+
+ <SELECT NAME = "<% $opt{'field'} || 'templatename' %>"
+ ID = "<% $opt{'id'} %>"
+ >
+
+% foreach my $templatename ( '', @templatenames ) {
+
+ <OPTION VALUE="<% $templatename %>"
+ <% $templatename eq $curr_value ? 'SELECTED' : '' %>
+ ><% $templatename || '(Default)' %>
+
+% }
+
+ </SELECT>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+my $conf = new FS::Conf;
+
+my @templatenames = $conf->invoice_templatenames;
+
+</%init>
diff --git a/httemplate/elements/tr-select-otaker.html b/httemplate/elements/tr-select-otaker.html
new file mode 100644
index 000000000..edf62dceb
--- /dev/null
+++ b/httemplate/elements/tr-select-otaker.html
@@ -0,0 +1,10 @@
+<TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Employee: ' %></TD>
+ <TD><% include('select-otaker.html', %opt) %></TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/tr-select-part_pkg.html b/httemplate/elements/tr-select-part_pkg.html
new file mode 100644
index 000000000..db9afd2df
--- /dev/null
+++ b/httemplate/elements/tr-select-part_pkg.html
@@ -0,0 +1,39 @@
+% if ( $opt{'part_pkg'} && scalar(@{ $opt{'part_pkg'} }) == 0 ) {
+% unless ( $opt{'js_only'} ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'pkgpart' %>" VALUE="">
+
+% }
+%
+% } else {
+%
+% unless ( $opt{'js_only'} ) {
+
+ <% include('tr-td-label.html', %opt) %>
+ <TD <% $cell_style %>>
+
+% }
+%
+ <% include( '/elements/select-part_pkg.html', %opt ) %>
+%
+% unless ( $opt{'js_only'} ) {
+
+ </TD>
+ </TR>
+
+% }
+%
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+$opt{'label'} ||= 'Package definition';
+
+#taken care of (better) in select-part_pkg now (is there anything using this
+# that needs to override the disabed=>'' ??)
+#$opt{'part_pkg'} ||= [ qsearch( 'part_pkg', {} ) ]; # { disabled=>'' } )
+
+</%init>
diff --git a/httemplate/elements/tr-select-part_referral.html b/httemplate/elements/tr-select-part_referral.html
new file mode 100644
index 000000000..a589528d7
--- /dev/null
+++ b/httemplate/elements/tr-select-part_referral.html
@@ -0,0 +1,37 @@
+% if ( scalar( @{$opt{'part_referrals'}} ) == 0 ) {
+ <P><FONT SIZE="+1" COLOR="#ff0000">You have not created any advertising sources. You must create at least one advertising source before adding a customer. Go to <A HREF="<% popurl(2) %>browse/part_referral.html">advertising source listing</A> and create one or more advertising sources.</FONT>
+% } elsif ( scalar( @{$opt{'part_referrals'}} ) == 1 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'refnum' %>" VALUE="<% $opt{'part_referrals'}->[0]->refnum %>">
+
+% } else {
+
+ <TR>
+% if ( $opt{'label'} ) {
+ <TD ALIGN="right"><% $opt{'label'} %></TD>
+% } else {
+ <TH ALIGN="right"><%$r%>Advertising source</TH>
+% }
+ <TD COLSPAN="<% $colspan %>">
+ <% include( '/elements/select-part_referral.html',
+ 'curr_value' => $refnum,
+ %opt
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+<%init>
+
+my %opt = @_;
+my $refnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'part_referrals'} ||=
+ [ FS::part_referral->all_part_referral( 1 ) ]; #1: include global
+
+my $colspan = delete($opt{'colspan'}) || 1;
+
+my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+</%init>
diff --git a/httemplate/elements/tr-select-part_svc.html b/httemplate/elements/tr-select-part_svc.html
new file mode 100644
index 000000000..0274ef12a
--- /dev/null
+++ b/httemplate/elements/tr-select-part_svc.html
@@ -0,0 +1,29 @@
+% if ( scalar(@{ $opt{'part_svc'} }) == 0 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'svcpart' %>" VALUE="">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Package definition' %></TD>
+ <TD>
+ <% include( '/elements/select-table.html',
+ 'table' => 'part_svc',
+ 'name_col' => 'svc',
+ 'multiple' => 1,
+ #N/A 'empty_label' => '(none)',
+ %opt,
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my( %opt ) = @_;
+
+$opt{'part_svc'} ||= [ qsearch( 'part_svc', {} ) ]; # { disabled=>'' } )
+
+</%init>
diff --git a/httemplate/elements/tr-select-payby.html b/httemplate/elements/tr-select-payby.html
new file mode 100644
index 000000000..354eb5580
--- /dev/null
+++ b/httemplate/elements/tr-select-payby.html
@@ -0,0 +1,37 @@
+<% include ('tr-td-label.html', 'label' => 'Payment type', @_ ) %>
+
+ <TD <% $style %>>
+
+ <% include( '/elements/select-payby.html',
+ 'curr_value' => $curr_value,
+ %opt
+ )
+ %>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+#my $onchange = $opt{'onchange'}
+# ? 'onChange="'. $opt{'onchange'}. '(this)"'
+# : '';
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $method = 'payby2longname';
+$method = 'cust_payby2longname' if $opt{'payby_type'} eq 'cust';
+#$method = 'event_payby2longname' if $opt{'payby_type'} eq 'event';
+#$method = 'pay_payby2longname' if $opt{'payby_type'} eq 'pay';
+
+unless ( $opt{'paybys'} ) {
+ tie %{ $opt{'paybys'} }, 'Tie::IxHash', FS::payby->$method();
+}
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+</%init>
+
diff --git a/httemplate/elements/tr-select-pkg_class.html b/httemplate/elements/tr-select-pkg_class.html
new file mode 100644
index 000000000..aa2760996
--- /dev/null
+++ b/httemplate/elements/tr-select-pkg_class.html
@@ -0,0 +1,27 @@
+% if ( scalar(@{ $opt{'pkg_class'} }) == 0 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'classnum' %>" VALUE="">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Package class' %></TD>
+ <TD>
+ <% include( '/elements/select-pkg_class.html',
+ 'curr_value' => $classnum,
+ %opt
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'pkg_class'} ||= [ qsearch( 'pkg_class', {} ) ]; # { disabled=>'' } )
+
+</%init>
diff --git a/httemplate/elements/tr-select-rate.html b/httemplate/elements/tr-select-rate.html
new file mode 100644
index 000000000..27f2645af
--- /dev/null
+++ b/httemplate/elements/tr-select-rate.html
@@ -0,0 +1,21 @@
+% unless ( $opt{'js_only'} ) {
+
+ <% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+% }
+
+ <% include( '/elements/select-rate.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+ </TD>
+ </TR>
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
+
diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
new file mode 100755
index 000000000..d85538f0c
--- /dev/null
+++ b/httemplate/elements/tr-select-reason.html
@@ -0,0 +1,189 @@
+<%doc>
+
+Example:
+
+ include( '/elements/tr-select-reason.html',
+
+ #required
+ 'field' => 'reasonnum',
+ 'reason_class' => 'C', # currently 'C', 'R', or 'S'
+ # for cancel, credit, or suspend
+
+ #recommended
+ 'cgi' => $cgi, #easiest way for things to be properly "sticky" on errors
+
+ #optional
+ 'control_button' => 'element_name', #button to be enabled when a reason is
+ #selected
+ 'id' => 'element_id',
+
+ #deprecated ways to keep things "sticky" on errors
+ # (requires duplicate code in each using file to parse cgi params)
+ 'curr_value' => $curr_value,
+ 'curr_value' => {
+ 'typenum' => $typenum,
+ 'reason' => $reason,
+ },
+
+ )
+
+</%doc>
+
+<SCRIPT TYPE="text/javascript">
+ function sh_add<% $func_suffix %>()
+ {
+
+ if (document.getElementById('<% $id %>').selectedIndex == 0){
+ <% $controlledbutton ? $controlledbutton.'.disabled = true;' : ';' %>
+ }else{
+ <% $controlledbutton ? $controlledbutton.'.disabled = false;' : ';' %>
+ }
+
+%if ($curuser->access_right($add_access_right)){
+
+ if (document.getElementById('<% $id %>').selectedIndex ==
+ (document.getElementById('<% $id %>').length - 1)) {
+ document.getElementById('new<% $id %>').disabled = false;
+ document.getElementById('new<% $id %>').style.display = 'inline';
+ document.getElementById('new<% $id %>Label').style.display = 'inline';
+ document.getElementById('new<% $id %>T').disabled = false;
+ document.getElementById('new<% $id %>T').style.display = 'inline';
+ document.getElementById('new<% $id %>TLabel').style.display = 'inline';
+ } else {
+ document.getElementById('new<% $id %>').disabled = true;
+ document.getElementById('new<% $id %>').style.display = 'none';
+ document.getElementById('new<% $id %>Label').style.display = 'none';
+ document.getElementById('new<% $id %>T').disabled = true;
+ document.getElementById('new<% $id %>T').style.display = 'none';
+ document.getElementById('new<% $id %>TLabel').style.display = 'none';
+ }
+
+%}
+
+ }
+</SCRIPT>
+
+<TR>
+ <TD ALIGN="right">Reason</TD>
+ <TD>
+ <SELECT id="<% $id %>" name="<% $name %>" onFocus="sh_add<% $func_suffix %>()" onChange="sh_add<% $func_suffix %>()">
+ <OPTION VALUE="" <% ($init_reason eq '') ? 'SELECTED' : '' %>>Select Reason...</OPTION>
+% foreach my $reason (@reasons) {
+ <OPTION VALUE="<% $reason->reasonnum %>" <% ($init_reason == $reason->reasonnum) ? 'SELECTED' : '' %>><% $reason->reasontype->type %> : <% $reason->reason %></OPTION>
+% }
+% if ($curuser->access_right($add_access_right)) {
+ <OPTION VALUE="-1" <% ($init_reason == -1) ? 'SELECTED' : '' %>>Add new reason</OPTION>
+% }
+%
+ </SELECT>
+ </TD>
+</TR>
+
+% my @types = qsearch( 'reason_type', { 'class' => $class } );
+% if (scalar(@types) < 1) { # we should never reach this
+<TR>
+ <TD ALIGN="right">
+ <P>No reason types. Go add some. </P>
+ </TD>
+</TR>
+% }elsif (scalar(@types) == 1) {
+<TR>
+ <TD ALIGN="right">
+ <P id="new<% $name %>TLabel" style="display:<% $display %>">Reason Type</P>
+ </TD>
+ <TD>
+ <P id="new<% $name %>T" disabled="<% $disabled %>" style="display:<% $display %>"><% $types[0]->type %>
+ <INPUT type="hidden" name="new<% $name %>T" value="<% $types[0]->typenum %>">
+ </TD>
+</TR>
+
+% }else{
+
+<TR>
+ <TD ALIGN="right">
+ <P id="new<% $id %>TLabel" style="display:<% $display %>">Reason Type</P>
+ </TD>
+ <TD>
+ <SELECT id="new<% $id %>T" name="new<% $name %>T" "<% $disabled %>" style="display:<% $display %>">
+% for my $type (@types) {
+ <OPTION VALUE="<% $type->typenum %>" <% ($init_type == $type->typenum) ? 'SELECTED' : '' %>><% $type->type %></OPTION>
+% }
+ </SELECT>
+ </TD>
+</TR>
+% }
+
+<TR>
+ <TD ALIGN="right">
+ <P id="new<% $id %>Label" style="display:<% $display %>">New Reason</P>
+ </TD>
+ <TD><INPUT id="new<% $id %>" name="new<% $name %>" type="text" value="<% $init_newreason |h %>" "<% $disabled %>" style="display:<% $display %>"></TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $name = $opt{'field'};
+my $class = $opt{'reason_class'};
+
+my $init_reason;
+if ( $opt{'cgi'} ) {
+ $init_reason = $opt{'cgi'}->param($name);
+} else {
+ $init_reason = $opt{'curr_value'};
+}
+
+my $controlledbutton = $opt{'control_button'};
+
+( my $func_suffix = $name ) =~ s/\./_/g;
+
+my $id = $opt{'id'} || $func_suffix;
+
+my( $add_access_right, $access_right );
+if ($class eq 'C') {
+ $access_right = 'Cancel customer';
+ $add_access_right = 'Add on-the-fly cancel reason';
+} elsif ($class eq 'S') {
+ $access_right = 'Suspend customer package';
+ $add_access_right = 'Add on-the-fly suspend reason';
+} elsif ($class eq 'R') {
+ $access_right = 'Post credit';
+ $add_access_right = 'Add on-the-fly credit reason';
+} else {
+ die "illegal class: $class";
+}
+
+my( $display, $disabled ) = ( 'none', 'DISABLED' );
+my( $init_type, $init_newreason ) = ( '', '' );
+if ($init_reason == -1 || ref($init_reason) ) {
+
+ $display = 'inline';
+ $disabled = '';
+
+ if ( ref($init_reason) ) {
+ $init_type = $init_reason->{'typenum'};
+ $init_newreason = $init_reason->{'reason'};
+ $init_reason = -1;
+ } elsif ( $opt{'cgi'} ) {
+ $init_type = $opt{'cgi'}->param( "new${name}T" );
+ $init_newreason = $opt{'cgi'}->param( "new$name" );
+ }
+
+}
+
+my $extra_sql =
+ "WHERE class = '$class' and (disabled = '' OR disabled is NULL)";
+
+my @reasons = qsearch({
+ table => 'reason',
+ hashref => {},
+ extra_sql => $extra_sql,
+ addl_from => 'LEFT JOIN reason_type '.
+ ' ON reason_type.typenum = reason.reason_type',
+ order_by => 'ORDER BY reason_type.type ASC, reason.reason ASC',
+});
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+</%init>
diff --git a/httemplate/elements/tr-select-table.html b/httemplate/elements/tr-select-table.html
new file mode 100644
index 000000000..6ac748782
--- /dev/null
+++ b/httemplate/elements/tr-select-table.html
@@ -0,0 +1,20 @@
+% unless ( $opt{'js_only'} ) {
+
+ <% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+% }
+
+ <% include( '/elements/select-table.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+ </TD>
+ </TR>
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-select-taxclass.html b/httemplate/elements/tr-select-taxclass.html
new file mode 100644
index 000000000..981c1a5f2
--- /dev/null
+++ b/httemplate/elements/tr-select-taxclass.html
@@ -0,0 +1,34 @@
+% if ( ! $conf->exists('enable_taxclasses')
+% || scalar(@{ $opt{'taxclasses'} }) == 0
+% ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'taxclass' %>" VALUE="<% $selected_taxclass %>">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Tax class: ' %></TD>
+ <TD>
+ <% include( '/elements/select-taxclass.html', 'curr_value' => $selected_taxclass, %opt ) %>
+ </TD>
+ </TR>
+
+% }
+<%init>
+
+my( %opt ) = @_;
+my $conf = new FS::Conf;
+my $selected_taxclass = $opt{'curr_value'}; # || $opt{'value'} necessary?
+
+unless ( $opt{'taxclasses'} ) {
+
+ #my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
+ my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+ or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ my %taxclasses = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
+ @{ $opt{'taxclasses'} } = grep $_, keys %taxclasses;
+
+}
+
+</%init>
diff --git a/httemplate/elements/tr-select-taxoverride.html b/httemplate/elements/tr-select-taxoverride.html
new file mode 100644
index 000000000..e20d37efd
--- /dev/null
+++ b/httemplate/elements/tr-select-taxoverride.html
@@ -0,0 +1,18 @@
+% if ( $conf->exists('enable_taxproducts') ) {
+ <%include('tr-td-label.html', @_) %>
+ <TD <% $cell_style %>><% include('select-taxoverride.html', @_) %></TD>
+ </TR>
+
+% } else {
+ <INPUT TYPE="hidden" NAME="<% $name %>" VALUE="<% $opt{value} %>">
+% }
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my %opt = @_;
+my $cell_style = $opt{'cell_style'}? 'STYLE="'. $opt{cell_style}. '"' : '';
+my $name = $opt{element_name} || $opt{field} || 'tax_override';
+
+</%init>
diff --git a/httemplate/elements/tr-select-taxproduct.html b/httemplate/elements/tr-select-taxproduct.html
new file mode 100644
index 000000000..759d0c01c
--- /dev/null
+++ b/httemplate/elements/tr-select-taxproduct.html
@@ -0,0 +1,18 @@
+% if ( $conf->exists('enable_taxproducts') ) {
+ <%include('tr-td-label.html', @_) %>
+ <TD <% $cell_style %>><% include('select-taxproduct.html', @_) %></TD>
+ </TR>
+
+% } else {
+ <INPUT TYPE="hidden" NAME="<% $name %>" VALUE="<% $opt{value} %>">
+% }
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my %opt = @_;
+my $cell_style = $opt{cell_style} ? 'STYLE="'. $opt{cell_style}. '"' : '';
+my $name = $opt{element_name} || $opt{field} || 'taxproductnum';
+
+</%init>
diff --git a/httemplate/elements/tr-select.html b/httemplate/elements/tr-select.html
new file mode 100644
index 000000000..07b0a01d5
--- /dev/null
+++ b/httemplate/elements/tr-select.html
@@ -0,0 +1,61 @@
+<% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+
+ <SELECT NAME = "<% $opt{field} %>"
+ ID = "<% $opt{id} %>"
+ previousValue = "<% $curr_value %>"
+ previousText = "<% $labels->{$curr_value} || $curr_value %>"
+ <% $onchange %>
+ >
+
+% if ( $opt{options} ) {
+%
+% foreach my $option ( @{ $opt{options} } ) { #just arrayref for now
+
+ <OPTION VALUE="<% $option %>"
+ <% $opt{curr_value} eq $option ? 'SELECTED' : '' %>
+ >
+ <% $labels->{$option} || $option %>
+ </OPTION>
+
+% }
+%
+% } else { #deprecated weird value hashref used only by reason.html
+%
+% my $aref = $opt{'value'}->{'values'};
+% my $vkey = $opt{'value'}->{'vcolumn'};
+% my $ckey = $opt{'value'}->{'ccolumn'};
+% foreach my $v (@$aref) {
+
+ <OPTION VALUE="<% $v->$vkey %>"
+ <% ($opt{curr_value} eq $v->$vkey) ? 'SELECTED' : '' %>
+ >
+ <% $v->$ckey %>
+ </OPTION>
+
+% }
+%
+% }
+
+ </SELECT>
+
+ </TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $onchange = $opt{'onchange'}
+ ? 'onChange="'. $opt{'onchange'}. '(this)"'
+ : '';
+
+my $labels = $opt{'option_labels'} || $opt{'labels'};
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $curr_value = $opt{'curr_value'};
+
+</%init>
diff --git a/httemplate/elements/tr-selectlayers-select.html b/httemplate/elements/tr-selectlayers-select.html
new file mode 100644
index 000000000..af8133627
--- /dev/null
+++ b/httemplate/elements/tr-selectlayers-select.html
@@ -0,0 +1 @@
+<% include('tr-selectlayers.html', @_, 'select_only'=>1 ) %>
diff --git a/httemplate/elements/tr-selectlayers.html b/httemplate/elements/tr-selectlayers.html
new file mode 100644
index 000000000..865d8226a
--- /dev/null
+++ b/httemplate/elements/tr-selectlayers.html
@@ -0,0 +1,25 @@
+% unless ( $opt{js_only} ) {
+
+ <% include('tr-td-label.html', @_ ) %>
+
+ <TD <% $style %>>
+
+% }
+
+ <% include('selectlayers.html', @_ ) %>
+
+% unless ( $opt{js_only} ) {
+
+ </TD>
+
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-selectmultiple-part_pkg.html b/httemplate/elements/tr-selectmultiple-part_pkg.html
new file mode 100644
index 000000000..455038da9
--- /dev/null
+++ b/httemplate/elements/tr-selectmultiple-part_pkg.html
@@ -0,0 +1,20 @@
+<TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Packages' %></TD>
+ <TD>
+ <% include( '/elements/select-table.html',
+ 'table' => 'part_pkg',
+ 'name_col' => 'pkg',
+ 'value' => '',
+ 'empty_label' => '(none)',
+ 'element_etc' => 'multiple',
+ %opt,
+ )
+ %>
+ </TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/tr-td-label.html b/httemplate/elements/tr-td-label.html
new file mode 100644
index 000000000..77c048405
--- /dev/null
+++ b/httemplate/elements/tr-td-label.html
@@ -0,0 +1,17 @@
+<TR>
+
+ <TD ALIGN="right" VALIGN="top" STYLE="<% $style %>" ID="<% $opt{label_id} || $opt{id}. '_label0' %>">
+
+ <% $opt{label} %>
+
+ </TD>
+
+<%init>
+
+my %opt = @_;
+
+my $style = 'padding-top: 3px';
+$style .= '; '. $opt{'cell_style'}
+ if $opt{'cell_style'};
+
+</%init>
diff --git a/httemplate/elements/tr-title.html b/httemplate/elements/tr-title.html
new file mode 100644
index 000000000..8517737ae
--- /dev/null
+++ b/httemplate/elements/tr-title.html
@@ -0,0 +1,5 @@
+<TR>
+ <TD BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TD>
+</TR>
+
+<% include('tr-justtitle.html', @_) %>
diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css
new file mode 100644
index 000000000..97c7da8bb
--- /dev/null
+++ b/httemplate/elements/xmenu.css
@@ -0,0 +1,196 @@
+
+.webfx-menu, .webfx-menu * {
+ /*
+ Set the box sizing to content box
+ in the future when IE6 supports box-sizing
+ there will be an issue to fix the sizes
+
+ There is probably an issue with IE5 mac now
+ because IE5 uses content-box but the script
+ assumes all versions of IE uses border-box.
+
+ At the time of this writing mozilla did not support
+ box-sizing for absolute positioned element.
+
+ Opera only supports content-box
+ */
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+}
+
+.webfx-menu {
+ position: absolute;
+ z-index: 100;
+ visibility: hidden;
+ border: 1px solid black;
+ padding: 1px;
+ background: white;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, Strength=4)
+ alpha(Opacity=95);
+ -moz-opacity: 0.95;
+ /* a drop shadow would be nice in moz/others too... */
+}
+
+.webfx-menu-empty {
+ display: block;
+ border: 1px solid white;
+ padding: 2px 5px 2px 5px;
+ font-size: 11px;
+ /* font-family: Tahoma, Verdan, Helvetica, Sans-Serif; */
+ color: black;
+}
+
+.webfx-menu a {
+ display: block;
+ /* width: expression(constExpression(ieBox ? "100%": "auto")); /* should be ignored by mz and op */
+ width: expression(constExpression(ie ? "98%": "auto")); /* should be ignored by mz and op */
+ overflow: visible;
+ /* padding: 2px 0px 2px 5px; */
+ padding: 1px 0px 1px 5px;
+ font-size: 14px;
+/* font-family: Verdana, Arial, Helvetica, sans-serif; */
+ font-weight: bold;
+ text-decoration: none;
+ vertical-align: center;
+ color: black;
+ border: 1px solid white;
+}
+
+.webfx-menu a:visited {
+ color: black;
+ border: 1px solid white;
+}
+
+.webfx-menu a:hover {
+ color: black;
+ border: 1px solid #7e0079;
+}
+
+.webfx-menu a:hover {
+ color: black;
+ /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */
+ /* background: #ffe6fe; */
+ /* background: #ffc2fe; */
+ background: #fff2fe;
+ border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/
+}
+
+.webfx-menu a .arrow {
+ float: right;
+ border: 0;
+ width: 3px;
+ margin-right: 3px;
+ margin-top: 4px;
+}
+
+/* separtor */
+.webfx-menu div {
+ height: 0;
+ height: expression(constExpression(ieBox ? "2px" : "0"));
+ border-top: 1px solid #7e0079; /* rgb(120,172,255); */
+ border-bottom: 1px solid rgb(234,242,255);
+ overflow: hidden;
+ margin: 2px 0px 2px 0px;
+ font-size: 0mm;
+}
+
+.webfx-menu-bar {
+ /* i want a vertical bar */
+ display: block;
+
+ /* background: rgb(120,172,255);/*rgb(255,128,0);*/
+ /* background: #a097ed; */
+ background: #000000;
+ /* border: 1px solid #7E0079; */
+ /* border: 1px solid #000000; */
+ /* border: none */
+ color: white;
+
+ padding: 2px;
+
+ /* IE5.0 has the wierdest box model for inline elements */
+ padding: expression(constExpression(ie50 ? "0px" : "2px"));
+}
+
+.webfx-menu-bar a,
+.webfx-menu-bar a:visited {
+ /* i want a vertical bar */
+ display: block;
+
+ /* border: 1px solid black; /*rgb(0,0,0);/*rgb(255,128,0);*/
+ /* border: 1px solid black; /* #ffffff; */
+ /* border-bottom: 1px solid black; */
+ border-bottom: 1px solid white;
+ /* border-bottom: 1px solid rgb(0,66,174);
+ /* border-bottom: 1px solid black;
+ border-bottom: 1px solid black;
+ border-bottom: 1px solid black; */
+
+ padding: 1px 5px 1px 5px;
+
+ /* color: black; */
+ color: white;
+ text-decoration: none;
+
+ /* IE5.0 Does not paint borders and padding on inline elements without a height/width */
+ height: expression(constExpression(ie50 ? "17px" : "auto"));
+}
+
+.webfx-menu-bar a:link {
+ color: white;
+}
+
+.webfx-menu-bar a:hover {
+ /* color: black; */
+ color: white;
+ /* background: rgb(120,172,255); */
+ /* background: #BC79B8; */
+ background: #7e0079;
+ /* border-left: 1px solid rgb(234,242,255);
+ border-right: 1px solid rgb(0,66,174);
+ border-top: 1px solid rgb(234,242,255);
+ border-bottom: 1px solid rgb(0,66,174); */
+}
+
+.webfx-menu-bar a .arrow {
+ float: right;
+ border: 0;
+/* vertical-align: top; */
+ width: 3px;
+ margin-right: 3px;
+ margin-top: 4px;
+}
+
+.webfx-menu-bar a:active, .webfx-menu-bar a:focus {
+ -moz-outline: none;
+ outline: none;
+ /*
+ ie does not support outline but ie55 can hide the outline using
+ a proprietary property on HTMLElement. Did I say that IE sucks at CSS?
+ */
+ ie-dummy: expression(this.hideFocus=true);
+
+/* border-left: 1px solid rgb(0,66,174); */
+/* border-right: 1px solid rgb(234,242,255); */
+/* border-top: 1px solid rgb(0,66,174); */
+/* border-bottom: 1px solid rgb(234,242,255); */
+}
+
+.webfx-menu-title {
+ color: black;
+ /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */
+ background: #7e0079;
+/* border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/
+ /* padding: 3px 1px 3px 6px; */
+ padding: 3px 1px 3px 5px;
+ display: block;
+ font-size: 16px;
+/* font-family: Verdana, Arial, Helvetica, sans-serif; */
+ font-weight: bold;
+ text-decoration: none;
+ color: white;
+/* border: 1px solid white; */
+ border-bottom: 1px solid white;
+ width: expression(constExpression(ie ? "98%": "auto")); /* should be ignored by mz and op */
+}
+
diff --git a/httemplate/elements/xmenu.js b/httemplate/elements/xmenu.js
new file mode 100644
index 000000000..134265f53
--- /dev/null
+++ b/httemplate/elements/xmenu.js
@@ -0,0 +1,668 @@
+//<script>
+/*
+ * This script was created by Erik Arvidsson (erik@eae.net)
+ * for WebFX (http://webfx.eae.net)
+ * Copyright 2001
+ *
+ * For usage see license at http://webfx.eae.net/license.html
+ *
+ * Created: 2001-01-12
+ * Updates: 2001-11-20 Added hover mode support and removed Opera focus hacks
+ * 2001-12-20 Added auto positioning and some properties to support this
+ * 2002-08-13 toString used ' for attributes. Changed to " to allow in args
+ */
+
+// check browsers
+var ua = navigator.userAgent;
+var opera = /opera [56789]|opera\/[56789]/i.test(ua);
+var ie = !opera && /MSIE/.test(ua);
+var ie50 = ie && /MSIE 5\.[01234]/.test(ua);
+var ie6 = ie && /MSIE [6789]/.test(ua);
+var ieBox = ie && (document.compatMode == null || document.compatMode != "CSS1Compat");
+var moz = !opera && /gecko/i.test(ua);
+var nn6 = !opera && /netscape.*6\./i.test(ua);
+var khtml = /KHTML/i.test(ua);
+
+// define the default values
+
+webfxMenuDefaultWidth = 154;
+
+webfxMenuDefaultBorderLeft = 1;
+webfxMenuDefaultBorderRight = 1;
+webfxMenuDefaultBorderTop = 1;
+webfxMenuDefaultBorderBottom = 1;
+
+webfxMenuDefaultPaddingLeft = 1;
+webfxMenuDefaultPaddingRight = 1;
+webfxMenuDefaultPaddingTop = 1;
+webfxMenuDefaultPaddingBottom = 1;
+
+webfxMenuDefaultShadowLeft = 0;
+webfxMenuDefaultShadowRight = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 :0;
+webfxMenuDefaultShadowTop = 0;
+webfxMenuDefaultShadowBottom = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 : 0;
+
+
+webfxMenuItemDefaultHeight = 18;
+webfxMenuItemDefaultText = "Untitled";
+webfxMenuItemDefaultHref = "javascript:void(0)";
+
+webfxMenuSeparatorDefaultHeight = 6;
+
+webfxMenuDefaultEmptyText = "Empty";
+
+webfxMenuDefaultUseAutoPosition = nn6 ? false : true;
+
+
+
+// other global constants
+
+webfxMenuImagePath = "";
+
+webfxMenuUseHover = opera ? true : false;
+webfxMenuHideTime = 500;
+webfxMenuShowTime = 200;
+
+
+
+var webFXMenuHandler = {
+ idCounter : 0,
+ idPrefix : "webfx-menu-object-",
+ all : {},
+ getId : function () { return this.idPrefix + this.idCounter++; },
+ overMenuItem : function (oItem) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+ var jsItem = this.all[oItem.id];
+ if (webfxMenuShowTime <= 0)
+ this._over(jsItem);
+ else if ( jsItem )
+ //this.showTimeout = window.setTimeout(function () { webFXMenuHandler._over(jsItem) ; }, webfxMenuShowTime);
+ // I hate IE5.0 because the piece of shit crashes when using setTimeout with a function object
+ this.showTimeout = window.setTimeout("webFXMenuHandler._over(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuShowTime);
+ },
+ outMenuItem : function (oItem) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+ var jsItem = this.all[oItem.id];
+ if (webfxMenuHideTime <= 0)
+ this._out(jsItem);
+ else if ( jsItem )
+ //this.hideTimeout = window.setTimeout(function () { webFXMenuHandler._out(jsItem) ; }, webfxMenuHideTime);
+ this.hideTimeout = window.setTimeout("webFXMenuHandler._out(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuHideTime);
+ },
+ blurMenu : function (oMenuItem) {
+ window.setTimeout("webFXMenuHandler.all[\"" + oMenuItem.id + "\"].subMenu.hide();", webfxMenuHideTime);
+ },
+ _over : function (jsItem) {
+ if (jsItem.subMenu) {
+ jsItem.parentMenu.hideAllSubs();
+ jsItem.subMenu.show();
+ }
+ else
+ jsItem.parentMenu.hideAllSubs();
+ },
+ _out : function (jsItem) {
+ // find top most menu
+ var root = jsItem;
+ var m;
+ if (root instanceof WebFXMenuButton)
+ m = root.subMenu;
+ else {
+ m = jsItem.parentMenu;
+ while (m.parentMenu != null && !(m.parentMenu instanceof WebFXMenuBar))
+ m = m.parentMenu;
+ }
+ if (m != null)
+ m.hide();
+ },
+ hideMenu : function (menu) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+
+ this.hideTimeout = window.setTimeout("webFXMenuHandler.all['" + menu.id + "'].hide()", webfxMenuHideTime);
+ },
+ showMenu : function (menu, src, dir) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+
+ if (arguments.length < 3)
+ dir = "vertical";
+
+ menu.show(src, dir);
+ }
+};
+
+function WebFXMenu() {
+ this._menuItems = [];
+ this._subMenus = [];
+ this.id = webFXMenuHandler.getId();
+ this.top = 0;
+ this.left = 0;
+ this.shown = false;
+ this.parentMenu = null;
+ webFXMenuHandler.all[this.id] = this;
+}
+
+WebFXMenu.prototype.width = webfxMenuDefaultWidth;
+WebFXMenu.prototype.emptyText = webfxMenuDefaultEmptyText;
+WebFXMenu.prototype.useAutoPosition = webfxMenuDefaultUseAutoPosition;
+
+WebFXMenu.prototype.borderLeft = webfxMenuDefaultBorderLeft;
+WebFXMenu.prototype.borderRight = webfxMenuDefaultBorderRight;
+WebFXMenu.prototype.borderTop = webfxMenuDefaultBorderTop;
+WebFXMenu.prototype.borderBottom = webfxMenuDefaultBorderBottom;
+
+WebFXMenu.prototype.paddingLeft = webfxMenuDefaultPaddingLeft;
+WebFXMenu.prototype.paddingRight = webfxMenuDefaultPaddingRight;
+WebFXMenu.prototype.paddingTop = webfxMenuDefaultPaddingTop;
+WebFXMenu.prototype.paddingBottom = webfxMenuDefaultPaddingBottom;
+
+WebFXMenu.prototype.shadowLeft = webfxMenuDefaultShadowLeft;
+WebFXMenu.prototype.shadowRight = webfxMenuDefaultShadowRight;
+WebFXMenu.prototype.shadowTop = webfxMenuDefaultShadowTop;
+WebFXMenu.prototype.shadowBottom = webfxMenuDefaultShadowBottom;
+
+
+
+WebFXMenu.prototype.add = function (menuItem) {
+ this._menuItems[this._menuItems.length] = menuItem;
+ if (menuItem.subMenu) {
+ this._subMenus[this._subMenus.length] = menuItem.subMenu;
+ menuItem.subMenu.parentMenu = this;
+ }
+
+ menuItem.parentMenu = this;
+};
+
+WebFXMenu.prototype.show = function (relObj, sDir) {
+ if (this.useAutoPosition)
+ this.position(relObj, sDir);
+
+ var divElement = document.getElementById(this.id);
+ if ( divElement ) {
+
+ divElement.style.left = opera ? this.left : this.left + "px";
+ divElement.style.top = opera ? this.top : this.top + "px";
+ divElement.style.visibility = "visible";
+
+ if ( ie ) {
+ var shimElement = document.getElementById(this.id + "Shim");
+ if ( shimElement ) {
+ shimElement.style.width = divElement.offsetWidth;
+ shimElement.style.height = divElement.offsetHeight;
+ shimElement.style.top = divElement.style.top;
+ shimElement.style.left = divElement.style.left;
+ /*shimElement.style.zIndex = divElement.style.zIndex - 1; */
+ shimElement.style.display = "block";
+ shimElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
+ }
+ }
+
+ }
+
+ this.shown = true;
+
+ if (this.parentMenu)
+ this.parentMenu.show();
+};
+
+WebFXMenu.prototype.hide = function () {
+ this.hideAllSubs();
+ var divElement = document.getElementById(this.id);
+ if ( divElement ) {
+ divElement.style.visibility = "hidden";
+ if ( ie ) {
+ var shimElement = document.getElementById(this.id + "Shim");
+ if ( shimElement ) {
+ shimElement.style.display = "none";
+ }
+ }
+ }
+
+ this.shown = false;
+};
+
+WebFXMenu.prototype.hideAllSubs = function () {
+ for (var i = 0; i < this._subMenus.length; i++) {
+ if (this._subMenus[i].shown)
+ this._subMenus[i].hide();
+ }
+};
+
+WebFXMenu.prototype.toString = function () {
+ var top = this.top + this.borderTop + this.paddingTop;
+ var str = "<div id='" + this.id + "' class='webfx-menu' style='" +
+ "width:" + (!ieBox ?
+ this.width - this.borderLeft - this.paddingLeft - this.borderRight - this.paddingRight :
+ this.width) + "px;" +
+ (this.useAutoPosition ?
+ "left:" + this.left + "px;" + "top:" + this.top + "px;" :
+ "") +
+ (ie50 ? "filter: none;" : "") +
+ "'>";
+
+ if (this._menuItems.length == 0) {
+ str += "<span class='webfx-menu-empty'>" + this.emptyText + "</span>";
+ }
+ else {
+ str += '<span class="webfx-menu-title" onmouseover="webFXMenuHandler.overMenuItem(this)"' +
+ (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") +
+ '>' + this.emptyText + '</span>';
+ // str += '<div id="' + this.id + '-title">' + this.emptyText + '</div>';
+ // loop through all menuItems
+ for (var i = 0; i < this._menuItems.length; i++) {
+ var mi = this._menuItems[i];
+ str += mi;
+ if (!this.useAutoPosition) {
+ if (mi.subMenu && !mi.subMenu.useAutoPosition)
+ mi.subMenu.top = top - mi.subMenu.borderTop - mi.subMenu.paddingTop;
+ top += mi.height;
+ }
+ }
+
+ }
+
+ str += "</div>";
+
+ if ( ie ) {
+ str += "<iframe id='" + this.id + "Shim' src='javascript:false;' scrolling='no' frameBorder='0' style='position:absolute; top:0px; left: 0px; display:none;'></iframe>";
+ }
+
+ for (var i = 0; i < this._subMenus.length; i++) {
+ this._subMenus[i].left = this.left + this.width - this._subMenus[i].borderLeft;
+ str += this._subMenus[i];
+ }
+
+ return str;
+};
+// WebFXMenu.prototype.position defined later
+
+function WebFXMenuItem(sText, sHref, sToolTip, oSubMenu) {
+ this.text = sText || webfxMenuItemDefaultText;
+ this.href = (sHref == null || sHref == "") ? webfxMenuItemDefaultHref : sHref;
+ this.subMenu = oSubMenu;
+ if (oSubMenu)
+ oSubMenu.parentMenuItem = this;
+ this.toolTip = sToolTip;
+ this.id = webFXMenuHandler.getId();
+ webFXMenuHandler.all[this.id] = this;
+};
+WebFXMenuItem.prototype.height = webfxMenuItemDefaultHeight;
+WebFXMenuItem.prototype.toString = function () {
+ return "<a" +
+ " id='" + this.id + "'" +
+ " href=\"" + this.href + "\"" +
+ (this.toolTip ? " title=\"" + this.toolTip + "\"" : "") +
+ " onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") +
+ (this.subMenu ? " unselectable='on' tabindex='-1'" : "") +
+ ">" +
+ (this.subMenu ? "<img class='arrow' src=\"" + webfxMenuImagePath + "arrow.right.black.png\">" : "") +
+ this.text +
+ "</a>";
+};
+
+
+function WebFXMenuSeparator() {
+ this.id = webFXMenuHandler.getId();
+ webFXMenuHandler.all[this.id] = this;
+};
+WebFXMenuSeparator.prototype.height = webfxMenuSeparatorDefaultHeight;
+WebFXMenuSeparator.prototype.toString = function () {
+ return "<div" +
+ " id='" + this.id + "'" +
+ (webfxMenuUseHover ?
+ " onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ " onmouseout='webFXMenuHandler.outMenuItem(this)'"
+ :
+ "") +
+ "></div>"
+};
+
+function WebFXMenuBar() {
+ this._parentConstructor = WebFXMenu;
+ this._parentConstructor();
+}
+WebFXMenuBar.prototype = new WebFXMenu;
+WebFXMenuBar.prototype.toString = function () {
+ var str = "<div id='" + this.id + "' class='webfx-menu-bar'>";
+
+ // loop through all menuButtons
+ for (var i = 0; i < this._menuItems.length; i++)
+ str += this._menuItems[i];
+
+ str += "</div>";
+
+ for (var i = 0; i < this._subMenus.length; i++)
+ str += this._subMenus[i];
+
+ return str;
+};
+
+function WebFXMenuButton(sText, sHref, sToolTip, oSubMenu) {
+ this._parentConstructor = WebFXMenuItem;
+ this._parentConstructor(sText, sHref, sToolTip, oSubMenu);
+}
+WebFXMenuButton.prototype = new WebFXMenuItem;
+WebFXMenuButton.prototype.toString = function () {
+ return "<a" +
+ " id='" + this.id + "'" +
+ " href='" + this.href + "'" +
+ (this.toolTip ? " title='" + this.toolTip + "'" : "") +
+ (webfxMenuUseHover ?
+ (" onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ " onmouseout='webFXMenuHandler.outMenuItem(this)'") :
+ (
+ " onfocus='webFXMenuHandler.overMenuItem(this)'" +
+ (this.subMenu ?
+ " onblur='webFXMenuHandler.blurMenu(this)'" :
+ ""
+ )
+ )) +
+ ">" +
+ (this.subMenu ? "<img class='arrow' src='" + webfxMenuImagePath + "arrow.right.png'>" : "") +
+ this.text +
+ "</a>";
+};
+
+
+
+
+
+/* Position functions */
+
+
+function getInnerLeft(el) {
+
+ if (el == null) return 0;
+
+ if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0;
+
+ return parseInt( getLeft(el) + parseInt(getBorderLeft(el)) );
+
+}
+
+
+
+function getLeft(el, debug) {
+
+ if (el == null) return 0;
+
+ //if ( debug )
+ // alert ( el.offsetLeft + ' - ' + getInnerLeft(el.offsetParent) );
+
+ return parseInt( el.offsetLeft + parseInt(getInnerLeft(el.offsetParent)) );
+
+}
+
+
+
+function getInnerTop(el) {
+
+ if (el == null) return 0;
+
+ if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0;
+
+ return parseInt( getTop(el) + parseInt(getBorderTop(el)) );
+
+}
+
+
+
+function getTop(el) {
+
+ if (el == null) return 0;
+
+ return parseInt( el.offsetTop + parseInt(getInnerTop(el.offsetParent)) );
+
+}
+
+
+
+function getBorderLeft(el) {
+
+ return ie ?
+
+ el.clientLeft :
+
+ ( khtml
+ ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ );
+
+}
+
+
+
+function getBorderTop(el) {
+
+ return ie ?
+
+ el.clientTop :
+
+ ( khtml
+ ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-top-width"))
+ );
+
+}
+
+
+
+function opera_getLeft(el) {
+
+ if (el == null) return 0;
+
+ return el.offsetLeft + opera_getLeft(el.offsetParent);
+
+}
+
+
+
+function opera_getTop(el) {
+
+ if (el == null) return 0;
+
+ return el.offsetTop + opera_getTop(el.offsetParent);
+
+}
+
+
+
+function getOuterRect(el, debug) {
+
+ return {
+
+ left: (opera ? opera_getLeft(el) : getLeft(el, debug)),
+
+ top: (opera ? opera_getTop(el) : getTop(el)),
+
+ width: el.offsetWidth,
+
+ height: el.offsetHeight
+
+ };
+
+}
+
+
+
+// mozilla bug! scrollbars not included in innerWidth/height
+
+function getDocumentRect(el) {
+
+ return {
+
+ left: 0,
+
+ top: 0,
+
+ width: (ie ?
+
+ (ieBox ? document.body.clientWidth : document.documentElement.clientWidth) :
+
+ window.innerWidth
+
+ ),
+
+ height: (ie ?
+
+ (ieBox ? document.body.clientHeight : document.documentElement.clientHeight) :
+
+ window.innerHeight
+
+ )
+
+ };
+
+}
+
+
+
+function getScrollPos(el) {
+
+ return {
+
+ left: (ie ?
+
+ (ieBox ? document.body.scrollLeft : document.documentElement.scrollLeft) :
+
+ window.pageXOffset
+
+ ),
+
+ top: (ie ?
+
+ (ieBox ? document.body.scrollTop : document.documentElement.scrollTop) :
+
+ window.pageYOffset
+
+ )
+
+ };
+
+}
+
+
+/* end position functions */
+
+WebFXMenu.prototype.position = function (relEl, sDir) {
+ var dir = sDir;
+ // find parent item rectangle, piRect
+ var piRect;
+ if (!relEl) {
+ var pi = this.parentMenuItem;
+ if (!this.parentMenuItem)
+ return;
+
+ relEl = document.getElementById(pi.id);
+ if (dir == null)
+ dir = pi instanceof WebFXMenuButton ? "vertical" : "horizontal";
+ //alert('created RelEl from parent: ' + pi.id);
+ piRect = getOuterRect(relEl, 1);
+ }
+ else if (relEl.left != null && relEl.top != null && relEl.width != null && relEl.height != null) { // got a rect
+ //alert('passed a Rect as RelEl: ' + typeof(relEl));
+
+ piRect = relEl;
+ }
+ else {
+ //alert('passed an element as RelEl: ' + typeof(relEl));
+ piRect = getOuterRect(relEl);
+ }
+
+ var menuEl = document.getElementById(this.id);
+ var menuRect = getOuterRect(menuEl);
+ var docRect = getDocumentRect();
+ var scrollPos = getScrollPos();
+ var pMenu = this.parentMenu;
+
+ if (dir == "vertical") {
+ if (piRect.left + menuRect.width - scrollPos.left <= docRect.width) {
+ //alert('piRect.left: ' + piRect.left);
+ this.left = piRect.left;
+ if ( ! ie )
+ this.left = this.left + 138;
+ } else if (docRect.width >= menuRect.width) {
+ //konq (not safari though) winds up here by accident and positions the menus all weird
+ //alert('docRect.width + scrollPos.left - menuRect.width');
+
+ this.left = docRect.width + scrollPos.left - menuRect.width;
+ } else {
+ //alert('scrollPos.left: ' + scrollPos.left);
+ this.left = scrollPos.left;
+ }
+
+ if (piRect.top + piRect.height + menuRect.height <= docRect.height + scrollPos.top)
+
+ this.top = piRect.top + piRect.height;
+
+ else if (piRect.top - menuRect.height >= scrollPos.top)
+
+ this.top = piRect.top - menuRect.height;
+
+ else if (docRect.height >= menuRect.height)
+
+ this.top = docRect.height + scrollPos.top - menuRect.height;
+
+ else
+
+ this.top = scrollPos.top;
+ }
+ else {
+ if (piRect.top + menuRect.height - this.borderTop - this.paddingTop <= docRect.height + scrollPos.top)
+
+ this.top = piRect.top - this.borderTop - this.paddingTop;
+
+ else if (piRect.top + piRect.height - menuRect.height + this.borderTop + this.paddingTop >= 0)
+
+ this.top = piRect.top + piRect.height - menuRect.height + this.borderBottom + this.paddingBottom + this.shadowBottom;
+
+ else if (docRect.height >= menuRect.height)
+
+ this.top = docRect.height + scrollPos.top - menuRect.height;
+
+ else
+
+ this.top = scrollPos.top;
+
+
+
+ var pMenuPaddingLeft = pMenu ? pMenu.paddingLeft : 0;
+
+ var pMenuBorderLeft = pMenu ? pMenu.borderLeft : 0;
+
+ var pMenuPaddingRight = pMenu ? pMenu.paddingRight : 0;
+
+ var pMenuBorderRight = pMenu ? pMenu.borderRight : 0;
+
+
+
+ if (piRect.left + piRect.width + menuRect.width + pMenuPaddingRight +
+
+ pMenuBorderRight - this.borderLeft + this.shadowRight <= docRect.width + scrollPos.left)
+
+ this.left = piRect.left + piRect.width + pMenuPaddingRight + pMenuBorderRight - this.borderLeft;
+
+ else if (piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight >= 0)
+
+ this.left = piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight;
+
+ else if (docRect.width >= menuRect.width)
+
+ this.left = docRect.width + scrollPos.left - menuRect.width;
+
+ else
+
+ this.left = scrollPos.left;
+ }
+};
diff --git a/httemplate/elements/xmenu.top.css b/httemplate/elements/xmenu.top.css
new file mode 100644
index 000000000..75917031b
--- /dev/null
+++ b/httemplate/elements/xmenu.top.css
@@ -0,0 +1,211 @@
+
+.webfx-menu, .webfx-menu * {
+ /*
+ Set the box sizing to content box
+ in the future when IE6 supports box-sizing
+ there will be an issue to fix the sizes
+
+ There is probably an issue with IE5 mac now
+ because IE5 uses content-box but the script
+ assumes all versions of IE uses border-box.
+
+ At the time of this writing mozilla did not support
+ box-sizing for absolute positioned element.
+
+ Opera only supports content-box
+ */
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+}
+
+.webfx-menu {
+ position: absolute;
+ z-index: 100;
+ visibility: hidden;
+ border: 1px solid black;
+ padding: 1px;
+ background: white;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, Strength=4)
+ alpha(Opacity=95);
+ -moz-opacity: 0.95;
+ /* a drop shadow would be nice in moz/others too... */
+}
+
+.webfx-menu-empty {
+ display: block;
+ border: 1px solid white;
+ padding: 2px 5px 2px 5px;
+ font-size: 11px;
+ /* font-family: Tahoma, Verdan, Helvetica, Sans-Serif; */
+ color: black;
+}
+
+.webfx-menu a {
+ display: block;
+ /* width: expression(constExpression(ieBox ? "100%": "auto")); /* should be ignored by mz and op */
+ width: expression(constExpression(ie ? "98%": "auto")); /* should be ignored by mz and op */
+ overflow: visible;
+ /* padding: 2px 0px 2px 5px; */
+ padding: 1px 0px 1px 5px;
+ font-size: 14px;
+/* font-family: Verdana, Arial, Helvetica, sans-serif; */
+ font-weight: bold;
+ text-decoration: none;
+ vertical-align: center;
+ color: black;
+ border: 1px solid white;
+}
+
+.webfx-menu a:visited {
+ color: black;
+ border: 1px solid white;
+}
+
+.webfx-menu a:hover {
+ color: black;
+ border: 1px solid #7e0079;
+}
+
+.webfx-menu a:hover {
+ color: black;
+ /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */
+ /* background: #ffe6fe; */
+ /* background: #ffc2fe; */
+ background: #fff2fe;
+ border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/
+}
+
+.webfx-menu a .arrow {
+ float: right;
+ border: 0;
+ width: 3px;
+ margin-right: 3px;
+ margin-top: 4px;
+}
+
+/* separtor */
+.webfx-menu div {
+ height: 0;
+ height: expression(constExpression(ieBox ? "2px" : "0"));
+ border-top: 1px solid #7e0079; /* rgb(120,172,255); */
+ border-bottom: 1px solid rgb(234,242,255);
+ overflow: hidden;
+ margin: 2px 0px 2px 0px;
+ font-size: 0mm;
+}
+
+.webfx-menu-bar {
+ /* background: rgb(120,172,255);/*rgb(255,128,0);*/
+ /* background: #a097ed; */
+ background: #000000;
+ /* border: 1px solid #7E0079; */
+ /* border: 1px solid #000000; */
+ /* border: none */
+ color: white;
+
+ padding: 2px;
+
+ /* IE5.0 has the wierdest box model for inline elements */
+ padding: expression(constExpression(ie50 ? "0px" : "2px"));
+}
+
+.webfx-menu-bar a,
+.webfx-menu-bar a:visited {
+ /* i want a vertical bar */
+ /* display: block; */
+
+ /* border: 1px solid black; /*rgb(0,0,0);/*rgb(255,128,0);*/
+ /* border: 1px solid black; /* #ffffff; */
+ /* border-bottom: 1px solid black; */
+ /* border-bottom: 1px solid white; */
+ /* border-bottom: 1px solid rgb(0,66,174);
+ /* border-bottom: 1px solid black;
+ border-bottom: 1px solid black;
+ border-bottom: 1px solid black; */
+
+ padding: 1px 5px 1px 5px;
+
+ /* color: black; */
+ color: white;
+ text-decoration: none;
+
+ /* IE5.0 Does not paint borders and padding on inline elements without a height/width */
+ height: expression(constExpression(ie50 ? "17px" : "auto"));
+
+ background-color:#333333;
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+
+ margin-right: 4px
+
+}
+
+.webfx-menu-bar a:link {
+ color: white;
+}
+
+.webfx-menu-bar a:hover {
+ /* color: black; */
+ color: white;
+ /* background: rgb(120,172,255); */
+ /* background: #BC79B8; */
+ background: #7e0079;
+ /* border-left: 1px solid rgb(234,242,255);
+ border-right: 1px solid rgb(0,66,174);
+ border-top: 1px solid rgb(234,242,255);
+ border-bottom: 1px solid rgb(0,66,174); */
+
+ border:1px solid;
+ border-top-color:#cccccc;
+ border-left-color:#cccccc;
+ border-right-color:#aaaaaa;
+ border-bottom-color:#aaaaaa;
+
+}
+
+.webfx-menu-bar a .arrow {
+ /* float: right; */
+ border: 0;
+/* vertical-align: top; */
+/* width: 3px; */
+/* margin-right: 3px; */
+ margin-bottom: 2px;
+
+}
+
+.webfx-menu-bar a:active, .webfx-menu-bar a:focus {
+ -moz-outline: none;
+ outline: none;
+ /*
+ ie does not support outline but ie55 can hide the outline using
+ a proprietary property on HTMLElement. Did I say that IE sucks at CSS?
+ */
+ ie-dummy: expression(this.hideFocus=true);
+
+/* border-left: 1px solid rgb(0,66,174); */
+/* border-right: 1px solid rgb(234,242,255); */
+/* border-top: 1px solid rgb(0,66,174); */
+/* border-bottom: 1px solid rgb(234,242,255); */
+}
+
+.webfx-menu-title {
+ color: black;
+ /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */
+ background: #7e0079;
+/* border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/
+ /* padding: 3px 1px 3px 6px; */
+ padding: 3px 1px 3px 5px;
+ display: block;
+ font-size: 16px;
+/* font-family: Verdana, Arial, Helvetica, sans-serif; */
+ font-weight: bold;
+ text-decoration: none;
+ color: white;
+/* border: 1px solid white; */
+ border-bottom: 1px solid white;
+ width: expression(constExpression(ie ? "98%": "auto")); /* should be ignored by mz and op */
+}
+
diff --git a/httemplate/elements/xmenu.top.js b/httemplate/elements/xmenu.top.js
new file mode 100644
index 000000000..8d81035a2
--- /dev/null
+++ b/httemplate/elements/xmenu.top.js
@@ -0,0 +1,671 @@
+//<script>
+/*
+ * This script was created by Erik Arvidsson (erik@eae.net)
+ * for WebFX (http://webfx.eae.net)
+ * Copyright 2001
+ *
+ * For usage see license at http://webfx.eae.net/license.html
+ *
+ * Created: 2001-01-12
+ * Updates: 2001-11-20 Added hover mode support and removed Opera focus hacks
+ * 2001-12-20 Added auto positioning and some properties to support this
+ * 2002-08-13 toString used ' for attributes. Changed to " to allow in args
+ */
+
+// check browsers
+var ua = navigator.userAgent;
+var opera = /opera [56789]|opera\/[56789]/i.test(ua);
+var ie = !opera && /MSIE/.test(ua);
+var ie50 = ie && /MSIE 5\.[01234]/.test(ua);
+var ie6 = ie && /MSIE [6789]/.test(ua);
+var ieBox = ie && (document.compatMode == null || document.compatMode != "CSS1Compat");
+var moz = !opera && /gecko/i.test(ua);
+var nn6 = !opera && /netscape.*6\./i.test(ua);
+var khtml = /KHTML/i.test(ua);
+
+// define the default values
+
+webfxMenuDefaultWidth = 154;
+
+webfxMenuDefaultBorderLeft = 1;
+webfxMenuDefaultBorderRight = 1;
+webfxMenuDefaultBorderTop = 1;
+webfxMenuDefaultBorderBottom = 1;
+
+webfxMenuDefaultPaddingLeft = 1;
+webfxMenuDefaultPaddingRight = 1;
+webfxMenuDefaultPaddingTop = 1;
+webfxMenuDefaultPaddingBottom = 1;
+
+webfxMenuDefaultShadowLeft = 0;
+webfxMenuDefaultShadowRight = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 :0;
+webfxMenuDefaultShadowTop = 0;
+webfxMenuDefaultShadowBottom = ie && !ie50 && /win32/i.test(navigator.platform) ? 4 : 0;
+
+
+webfxMenuItemDefaultHeight = 18;
+webfxMenuItemDefaultText = "Untitled";
+webfxMenuItemDefaultHref = "javascript:void(0)";
+
+webfxMenuSeparatorDefaultHeight = 6;
+
+webfxMenuDefaultEmptyText = "Empty";
+
+webfxMenuDefaultUseAutoPosition = nn6 ? false : true;
+
+
+
+// other global constants
+
+webfxMenuImagePath = "";
+
+webfxMenuUseHover = opera ? true : false;
+webfxMenuHideTime = 500;
+webfxMenuShowTime = 200;
+
+
+
+var webFXMenuHandler = {
+ idCounter : 0,
+ idPrefix : "webfx-menu-object-",
+ all : {},
+ getId : function () { return this.idPrefix + this.idCounter++; },
+ overMenuItem : function (oItem) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+ var jsItem = this.all[oItem.id];
+ if (webfxMenuShowTime <= 0)
+ this._over(jsItem);
+ else if ( jsItem )
+ //this.showTimeout = window.setTimeout(function () { webFXMenuHandler._over(jsItem) ; }, webfxMenuShowTime);
+ // I hate IE5.0 because the piece of shit crashes when using setTimeout with a function object
+ this.showTimeout = window.setTimeout("webFXMenuHandler._over(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuShowTime);
+ },
+ outMenuItem : function (oItem) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+ var jsItem = this.all[oItem.id];
+ if (webfxMenuHideTime <= 0)
+ this._out(jsItem);
+ else if ( jsItem )
+ //this.hideTimeout = window.setTimeout(function () { webFXMenuHandler._out(jsItem) ; }, webfxMenuHideTime);
+ this.hideTimeout = window.setTimeout("webFXMenuHandler._out(webFXMenuHandler.all['" + jsItem.id + "'])", webfxMenuHideTime);
+ },
+ blurMenu : function (oMenuItem) {
+ window.setTimeout("webFXMenuHandler.all[\"" + oMenuItem.id + "\"].subMenu.hide();", webfxMenuHideTime);
+ },
+ _over : function (jsItem) {
+ if (jsItem.subMenu) {
+ jsItem.parentMenu.hideAllSubs();
+ jsItem.subMenu.show();
+ }
+ else
+ jsItem.parentMenu.hideAllSubs();
+ },
+ _out : function (jsItem) {
+ // find top most menu
+ var root = jsItem;
+ var m;
+ if (root instanceof WebFXMenuButton)
+ m = root.subMenu;
+ else {
+ m = jsItem.parentMenu;
+ while (m.parentMenu != null && !(m.parentMenu instanceof WebFXMenuBar))
+ m = m.parentMenu;
+ }
+ if (m != null)
+ m.hide();
+ },
+ hideMenu : function (menu) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+
+ this.hideTimeout = window.setTimeout("webFXMenuHandler.all['" + menu.id + "'].hide()", webfxMenuHideTime);
+ },
+ showMenu : function (menu, src, dir) {
+ if (this.showTimeout != null)
+ window.clearTimeout(this.showTimeout);
+ if (this.hideTimeout != null)
+ window.clearTimeout(this.hideTimeout);
+
+ if (arguments.length < 3)
+ dir = "vertical";
+
+ menu.show(src, dir);
+ }
+};
+
+function WebFXMenu() {
+ this._menuItems = [];
+ this._subMenus = [];
+ this.id = webFXMenuHandler.getId();
+ this.top = 0;
+ this.left = 0;
+ this.shown = false;
+ this.parentMenu = null;
+ webFXMenuHandler.all[this.id] = this;
+}
+
+WebFXMenu.prototype.width = webfxMenuDefaultWidth;
+WebFXMenu.prototype.emptyText = webfxMenuDefaultEmptyText;
+WebFXMenu.prototype.useAutoPosition = webfxMenuDefaultUseAutoPosition;
+
+WebFXMenu.prototype.borderLeft = webfxMenuDefaultBorderLeft;
+WebFXMenu.prototype.borderRight = webfxMenuDefaultBorderRight;
+WebFXMenu.prototype.borderTop = webfxMenuDefaultBorderTop;
+WebFXMenu.prototype.borderBottom = webfxMenuDefaultBorderBottom;
+
+WebFXMenu.prototype.paddingLeft = webfxMenuDefaultPaddingLeft;
+WebFXMenu.prototype.paddingRight = webfxMenuDefaultPaddingRight;
+WebFXMenu.prototype.paddingTop = webfxMenuDefaultPaddingTop;
+WebFXMenu.prototype.paddingBottom = webfxMenuDefaultPaddingBottom;
+
+WebFXMenu.prototype.shadowLeft = webfxMenuDefaultShadowLeft;
+WebFXMenu.prototype.shadowRight = webfxMenuDefaultShadowRight;
+WebFXMenu.prototype.shadowTop = webfxMenuDefaultShadowTop;
+WebFXMenu.prototype.shadowBottom = webfxMenuDefaultShadowBottom;
+
+
+
+WebFXMenu.prototype.add = function (menuItem) {
+ this._menuItems[this._menuItems.length] = menuItem;
+ if (menuItem.subMenu) {
+ this._subMenus[this._subMenus.length] = menuItem.subMenu;
+ menuItem.subMenu.parentMenu = this;
+ }
+
+ menuItem.parentMenu = this;
+};
+
+WebFXMenu.prototype.show = function (relObj, sDir) {
+ if (this.useAutoPosition)
+ this.position(relObj, sDir);
+
+ var divElement = document.getElementById(this.id);
+ if ( divElement ) {
+
+ divElement.style.left = opera ? this.left : this.left + "px";
+ divElement.style.top = opera ? this.top : this.top + "px";
+ divElement.style.visibility = "visible";
+
+ if ( ie ) {
+ var shimElement = document.getElementById(this.id + "Shim");
+ if ( shimElement ) {
+ shimElement.style.width = divElement.offsetWidth;
+ shimElement.style.height = divElement.offsetHeight;
+ shimElement.style.top = divElement.style.top;
+ shimElement.style.left = divElement.style.left;
+ /*shimElement.style.zIndex = divElement.style.zIndex - 1; */
+ shimElement.style.display = "block";
+ shimElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
+ }
+ }
+
+ }
+
+ this.shown = true;
+
+ if (this.parentMenu)
+ this.parentMenu.show();
+};
+
+WebFXMenu.prototype.hide = function () {
+ this.hideAllSubs();
+ var divElement = document.getElementById(this.id);
+ if ( divElement ) {
+ divElement.style.visibility = "hidden";
+ if ( ie ) {
+ var shimElement = document.getElementById(this.id + "Shim");
+ if ( shimElement ) {
+ shimElement.style.display = "none";
+ }
+ }
+ }
+
+ this.shown = false;
+};
+
+WebFXMenu.prototype.hideAllSubs = function () {
+ for (var i = 0; i < this._subMenus.length; i++) {
+ if (this._subMenus[i].shown)
+ this._subMenus[i].hide();
+ }
+};
+
+WebFXMenu.prototype.toString = function () {
+ var top = this.top + this.borderTop + this.paddingTop;
+ var str = "<div id='" + this.id + "' class='webfx-menu' style='" +
+ "width:" + (!ieBox ?
+ this.width - this.borderLeft - this.paddingLeft - this.borderRight - this.paddingRight :
+ this.width) + "px;" +
+ (this.useAutoPosition ?
+ "left:" + this.left + "px;" + "top:" + this.top + "px;" :
+ "") +
+ (ie50 ? "filter: none;" : "") +
+ "'>";
+
+ if (this._menuItems.length == 0) {
+ str += "<span class='webfx-menu-empty'>" + this.emptyText + "</span>";
+ }
+ else {
+ str += '<span class="webfx-menu-title" onmouseover="webFXMenuHandler.overMenuItem(this)"' +
+ (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") +
+ '>' + this.emptyText + '</span>';
+ // str += '<div id="' + this.id + '-title">' + this.emptyText + '</div>';
+ // loop through all menuItems
+ for (var i = 0; i < this._menuItems.length; i++) {
+ var mi = this._menuItems[i];
+ str += mi;
+ if (!this.useAutoPosition) {
+ if (mi.subMenu && !mi.subMenu.useAutoPosition)
+ mi.subMenu.top = top - mi.subMenu.borderTop - mi.subMenu.paddingTop;
+ top += mi.height;
+ }
+ }
+
+ }
+
+ str += "</div>";
+
+ if ( ie ) {
+ str += "<iframe id='" + this.id + "Shim' src='javascript:false;' scrolling='no' frameBorder='0' style='position:absolute; top:0px; left: 0px; display:none;'></iframe>";
+ }
+
+ for (var i = 0; i < this._subMenus.length; i++) {
+ this._subMenus[i].left = this.left + this.width - this._subMenus[i].borderLeft;
+ str += this._subMenus[i];
+ }
+
+ return str;
+};
+// WebFXMenu.prototype.position defined later
+
+function WebFXMenuItem(sText, sHref, sToolTip, oSubMenu) {
+ this.text = sText || webfxMenuItemDefaultText;
+ this.href = (sHref == null || sHref == "") ? webfxMenuItemDefaultHref : sHref;
+ this.subMenu = oSubMenu;
+ if (oSubMenu)
+ oSubMenu.parentMenuItem = this;
+ this.toolTip = sToolTip;
+ this.id = webFXMenuHandler.getId();
+ webFXMenuHandler.all[this.id] = this;
+};
+WebFXMenuItem.prototype.height = webfxMenuItemDefaultHeight;
+WebFXMenuItem.prototype.toString = function () {
+ return "<a" +
+ " id='" + this.id + "'" +
+ " href=\"" + this.href + "\"" +
+ (this.toolTip ? " title=\"" + this.toolTip + "\"" : "") +
+ " onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ (webfxMenuUseHover ? " onmouseout='webFXMenuHandler.outMenuItem(this)'" : "") +
+ (this.subMenu ? " unselectable='on' tabindex='-1'" : "") +
+ ">" +
+ (this.subMenu ? "<img class='arrow' src=\"" + webfxMenuImagePath + "arrow.right.black.png\">" : "") +
+ this.text +
+ "</a>";
+};
+
+
+function WebFXMenuSeparator() {
+ this.id = webFXMenuHandler.getId();
+ webFXMenuHandler.all[this.id] = this;
+};
+WebFXMenuSeparator.prototype.height = webfxMenuSeparatorDefaultHeight;
+WebFXMenuSeparator.prototype.toString = function () {
+ return "<div" +
+ " id='" + this.id + "'" +
+ (webfxMenuUseHover ?
+ " onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ " onmouseout='webFXMenuHandler.outMenuItem(this)'"
+ :
+ "") +
+ "></div>"
+};
+
+function WebFXMenuBar() {
+ this._parentConstructor = WebFXMenu;
+ this._parentConstructor();
+}
+WebFXMenuBar.prototype = new WebFXMenu;
+WebFXMenuBar.prototype.toString = function () {
+ var str = "<div id='" + this.id + "' class='webfx-menu-bar'>";
+
+ // loop through all menuButtons
+ for (var i = 0; i < this._menuItems.length; i++)
+ str += this._menuItems[i];
+
+ str += "</div>";
+
+ for (var i = 0; i < this._subMenus.length; i++)
+ str += this._subMenus[i];
+
+ return str;
+};
+
+function WebFXMenuButton(sText, sHref, sToolTip, oSubMenu) {
+ this._parentConstructor = WebFXMenuItem;
+ this._parentConstructor(sText, sHref, sToolTip, oSubMenu);
+}
+WebFXMenuButton.prototype = new WebFXMenuItem;
+WebFXMenuButton.prototype.toString = function () {
+ return "<a" +
+ " id='" + this.id + "'" +
+ " href='" + this.href + "'" +
+ (this.toolTip ? " title='" + this.toolTip + "'" : "") +
+ (webfxMenuUseHover ?
+ (" onmouseover='webFXMenuHandler.overMenuItem(this)'" +
+ " onmouseout='webFXMenuHandler.outMenuItem(this)'") :
+ (
+ " onfocus='webFXMenuHandler.overMenuItem(this)'" +
+ (this.subMenu ?
+ " onblur='webFXMenuHandler.blurMenu(this)'" :
+ ""
+ )
+ )) +
+ ">" +
+ this.text +
+ (this.subMenu ? "<img class='arrow' src='" + webfxMenuImagePath + "arrow.down.png'>" : "") +
+ "</a>";
+};
+
+
+
+
+
+/* Position functions */
+
+
+function getInnerLeft(el, debug) {
+
+ if (el == null) return 0;
+
+ if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0;
+
+ //if ( debug )
+ // alert ( 'getInnerLeft: ' + getLeft(el) + ' - ' + getBorderLeft(el) );
+
+ return parseInt( getLeft(el) + parseInt(getBorderLeft(el)) );
+
+}
+
+
+
+function getLeft(el, debug) {
+
+ if (el == null) return 0;
+
+ //if ( debug )
+ // alert ( el + ': ' + el.offsetLeft + ' - ' + getInnerLeft(el.offsetParent) );
+
+ return parseInt( el.offsetLeft + parseInt(getInnerLeft(el.offsetParent)) );
+
+}
+
+
+
+function getInnerTop(el) {
+
+ if (el == null) return 0;
+
+ if (ieBox && el == document.body || !ieBox && el == document.documentElement) return 0;
+
+ return parseInt( getTop(el) + parseInt(getBorderTop(el)) );
+
+}
+
+
+
+function getTop(el) {
+
+ if (el == null) return 0;
+
+ return parseInt( el.offsetTop + parseInt(getInnerTop(el.offsetParent)) );
+
+}
+
+
+
+function getBorderLeft(el) {
+
+ return ie ?
+
+ el.clientLeft :
+
+ ( khtml
+ ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ );
+
+}
+
+
+
+function getBorderTop(el) {
+
+ return ie ?
+
+ el.clientTop :
+
+ ( khtml
+ ? parseInt(document.defaultView.getComputedStyle(el, null).getPropertyValue("border-left-width"))
+ : parseInt(window.getComputedStyle(el, null).getPropertyValue("border-top-width"))
+ );
+
+}
+
+
+
+function opera_getLeft(el) {
+
+ if (el == null) return 0;
+
+ return el.offsetLeft + opera_getLeft(el.offsetParent);
+
+}
+
+
+
+function opera_getTop(el) {
+
+ if (el == null) return 0;
+
+ return el.offsetTop + opera_getTop(el.offsetParent);
+
+}
+
+
+
+function getOuterRect(el, debug) {
+
+ return {
+
+ left: (opera ? opera_getLeft(el) : getLeft(el, debug)),
+
+ top: (opera ? opera_getTop(el) : getTop(el)),
+
+ width: el.offsetWidth,
+
+ height: el.offsetHeight
+
+ };
+
+}
+
+
+
+// mozilla bug! scrollbars not included in innerWidth/height
+
+function getDocumentRect(el) {
+
+ return {
+
+ left: 0,
+
+ top: 0,
+
+ width: (ie ?
+
+ (ieBox ? document.body.clientWidth : document.documentElement.clientWidth) :
+
+ window.innerWidth
+
+ ),
+
+ height: (ie ?
+
+ (ieBox ? document.body.clientHeight : document.documentElement.clientHeight) :
+
+ window.innerHeight
+
+ )
+
+ };
+
+}
+
+
+
+function getScrollPos(el) {
+
+ return {
+
+ left: (ie ?
+
+ (ieBox ? document.body.scrollLeft : document.documentElement.scrollLeft) :
+
+ window.pageXOffset
+
+ ),
+
+ top: (ie ?
+
+ (ieBox ? document.body.scrollTop : document.documentElement.scrollTop) :
+
+ window.pageYOffset
+
+ )
+
+ };
+
+}
+
+
+/* end position functions */
+
+WebFXMenu.prototype.position = function (relEl, sDir) {
+ var dir = sDir;
+ // find parent item rectangle, piRect
+ var piRect;
+ if (!relEl) {
+ var pi = this.parentMenuItem;
+ if (!this.parentMenuItem)
+ return;
+
+ relEl = document.getElementById(pi.id);
+ if (dir == null)
+ dir = pi instanceof WebFXMenuButton ? "vertical" : "horizontal";
+ //alert('created RelEl from parent: ' + pi.id);
+ piRect = getOuterRect(relEl, 1);
+ }
+ else if (relEl.left != null && relEl.top != null && relEl.width != null && relEl.height != null) { // got a rect
+ //alert('passed a Rect as RelEl: ' + typeof(relEl));
+
+ piRect = relEl;
+ }
+ else {
+ //alert('passed an element as RelEl: ' + typeof(relEl));
+ piRect = getOuterRect(relEl);
+ }
+
+ var menuEl = document.getElementById(this.id);
+ var menuRect = getOuterRect(menuEl);
+ var docRect = getDocumentRect();
+ var scrollPos = getScrollPos();
+ var pMenu = this.parentMenu;
+
+ if (dir == "vertical") {
+ if (piRect.left + menuRect.width - scrollPos.left <= docRect.width) {
+ //alert('piRect.left: ' + piRect.left);
+ this.left = piRect.left;
+// if ( ! ie )
+// this.left = this.left + 138;
+ } else if (docRect.width >= menuRect.width) {
+ //konq (not safari though) winds up here by accident and positions the menus all weird
+ //alert('docRect.width + scrollPos.left - menuRect.width');
+
+ this.left = docRect.width + scrollPos.left - menuRect.width;
+ } else {
+ //alert('scrollPos.left: ' + scrollPos.left);
+ this.left = scrollPos.left;
+ }
+
+ if (piRect.top + piRect.height + menuRect.height <= docRect.height + scrollPos.top)
+
+ this.top = piRect.top + piRect.height;
+
+ else if (piRect.top - menuRect.height >= scrollPos.top)
+
+ this.top = piRect.top - menuRect.height;
+
+ else if (docRect.height >= menuRect.height)
+
+ this.top = docRect.height + scrollPos.top - menuRect.height;
+
+ else
+
+ this.top = scrollPos.top;
+ }
+ else {
+ if (piRect.top + menuRect.height - this.borderTop - this.paddingTop <= docRect.height + scrollPos.top)
+
+ this.top = piRect.top - this.borderTop - this.paddingTop;
+
+ else if (piRect.top + piRect.height - menuRect.height + this.borderTop + this.paddingTop >= 0)
+
+ this.top = piRect.top + piRect.height - menuRect.height + this.borderBottom + this.paddingBottom + this.shadowBottom;
+
+ else if (docRect.height >= menuRect.height)
+
+ this.top = docRect.height + scrollPos.top - menuRect.height;
+
+ else
+
+ this.top = scrollPos.top;
+
+
+
+ var pMenuPaddingLeft = pMenu ? pMenu.paddingLeft : 0;
+
+ var pMenuBorderLeft = pMenu ? pMenu.borderLeft : 0;
+
+ var pMenuPaddingRight = pMenu ? pMenu.paddingRight : 0;
+
+ var pMenuBorderRight = pMenu ? pMenu.borderRight : 0;
+
+
+
+ if (piRect.left + piRect.width + menuRect.width + pMenuPaddingRight +
+
+ pMenuBorderRight - this.borderLeft + this.shadowRight <= docRect.width + scrollPos.left)
+
+ this.left = piRect.left + piRect.width + pMenuPaddingRight + pMenuBorderRight - this.borderLeft;
+
+ else if (piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight >= 0)
+
+ this.left = piRect.left - menuRect.width - pMenuPaddingLeft - pMenuBorderLeft + this.borderRight + this.shadowRight;
+
+ else if (docRect.width >= menuRect.width)
+
+ this.left = docRect.width + scrollPos.left - menuRect.width;
+
+ else
+
+ this.left = scrollPos.left;
+ }
+};
diff --git a/httemplate/elements/xmlhttp.html b/httemplate/elements/xmlhttp.html
new file mode 100644
index 000000000..d0c799095
--- /dev/null
+++ b/httemplate/elements/xmlhttp.html
@@ -0,0 +1,125 @@
+<%doc>
+
+Example:
+
+ include( '/elements/xmlhttp.html',
+ # required
+ 'url' => $p.'misc/something.html',
+ 'subs' => [ 'subroutine' ],
+
+ # optional
+ 'method' => 'GET', #defaults to GET, could specify POST
+ 'key' => 'unique', #unique key
+
+ );
+
+</%doc>
+<SCRIPT TYPE="text/javascript">
+
+ function rs_init_object() {
+ var A;
+ try {
+ A=new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ A=new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (oc) {
+ A=null;
+ }
+ }
+ if(!A && typeof XMLHttpRequest != "undefined")
+ A = new XMLHttpRequest();
+ if (!A)
+ alert("Can't create XMLHttpRequest object");
+ return A;
+
+ }
+% foreach my $func ( @{$opt{'subs'}} ) {
+%
+% my $furl = $url;
+% $furl =~ s/\"/\\\\\"/; #javascript escape
+%
+%
+
+
+ function <%$key%><%$func%>() {
+ // count args; build URL
+ var url = "<%$furl%>";
+ var a = <%$key%><%$func%>.arguments;
+
+ var args;
+ var len;
+ var content = 'sub=<% uri_escape($func) %>';
+ if ( a && typeof a == 'object' && a[0].constructor == Array ) {
+ args = a[0];
+ len = args.length
+ } else {
+ args = a;
+ len = args.length - 1;
+ }
+ for (var i = 0; i < len; i++)
+ content = content + "&arg=" + escape(args[i]);
+ content = content.replace( /[+]/g, '%2B'); // fix unescaped plus signs
+
+ if ( '<%$method%>' == 'GET' ) {
+ url = url + content;
+ }
+
+ //alert('<%$method%> ' + url);
+
+ var xmlhttp = rs_init_object();
+ xmlhttp.open("<%$method%>", url, true);
+
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState != 4)
+ return;
+
+ if (xmlhttp.status != 200) {
+ alert(xmlhttp.status + " status connecting to " + url);
+ } else {
+ var data = xmlhttp.responseText;
+ //alert('received response: ' + data);
+ a[a.length-1](data);
+ if ( data.indexOf("<b>System error</b>") > -1 ) {
+ var w;
+ if ( w = window.open("about:blank") ) {
+ w.document.write(data);
+ } else {
+ // popup blocking? should use an overlib popup instead
+ alert("Error popup disabled; try disabling popup blocking to see");
+ }
+ }
+ }
+ }
+
+ if ( '<%$method%>' == 'POST' ) {
+
+ xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ xmlhttp.send(content);
+
+ } else {
+
+ xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
+ xmlhttp.send(null);
+
+ }
+
+ //rs_debug("x_$func_name url = " + url);
+ //rs_debug("x_$func_name waiting..");
+ }
+% }
+
+
+</SCRIPT>
+<%init>
+my ( %opt ) = @_;
+
+my $url = $opt{'url'};
+my $method = exists($opt{'method'}) ? $opt{'method'} : 'GET';
+#my @subs = @{ $opt{'subs'};
+my $key = exists($opt{'key'}) ? $opt{'key'} : '';
+
+$url .= ( ($url =~ /\?/) ? '&' : '?' )
+ if $method eq 'GET';
+
+</%init>
diff --git a/httemplate/graph/cust_bill_pkg.cgi b/httemplate/graph/cust_bill_pkg.cgi
new file mode 100644
index 000000000..d7cae8055
--- /dev/null
+++ b/httemplate/graph/cust_bill_pkg.cgi
@@ -0,0 +1,109 @@
+<% include('elements/monthly.html',
+ 'title' => $title. 'Sales Report (Gross)',
+ 'graph_type' => 'Mountain',
+ 'items' => \@items,
+ 'params' => \@params,
+ 'labels' => \@labels,
+ 'graph_labels' => \@labels,
+ 'colors' => \@colors,
+ 'links' => \@links,
+ 'remove_empty' => 1,
+ 'bottom_total' => 1,
+ 'bottom_link' => "$link;",
+ 'agentnum' => $agentnum,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+#XXX or virtual
+my( $agentnum, $sel_agent ) = ('', '');
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+ $sel_agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ die "agentnum $agentnum not found!" unless $sel_agent;
+}
+my $title = $sel_agent ? $sel_agent->agent.' ' : '';
+
+#false lazinessish w/search/cust_pkg.cgi
+my $classnum = 0;
+my @pkg_class = ();
+if ( $cgi->param('classnum') =~ /^(\d*)$/ ) {
+ $classnum = $1;
+ if ( $classnum ) {
+ @pkg_class = ( qsearchs('pkg_class', { 'classnum' => $classnum } ) );
+ die "classnum $classnum not found!" unless $pkg_class[0];
+ $title .= $pkg_class[0]->classname.' ';
+ } elsif ( $classnum eq '' ) {
+ $title .= 'Empty class ';
+ @pkg_class = ( '(empty class)' );
+ } elsif ( $classnum eq '0' ) {
+ @pkg_class = qsearch('pkg_class', {} ); # { 'disabled' => '' } );
+ push @pkg_class, '(empty class)';
+ }
+}
+#eslaf
+
+my $hue = 0;
+#my $hue_increment = 170;
+#my $hue_increment = 145;
+my $hue_increment = 125;
+
+my @items = ();
+my @params = ();
+my @labels = ();
+my @colors = ();
+my @links = ();
+
+my $link = "${p}search/cust_bill_pkg.cgi?nottax=1;include_comp_cust=1";
+
+foreach my $agent ( $sel_agent || qsearch('agent', { 'disabled' => '' } ) ) {
+
+ my $col_scheme = Color::Scheme->new
+ ->from_hue($hue) #->from_hex($agent->color)
+ ->scheme('analogic')
+ ;
+ my @recur_colors = ();
+ my @onetime_colors = ();
+
+ ### fixup the color handling for package classes...
+ my $n = 0;
+
+ foreach my $pkg_class ( @pkg_class ) {
+
+ push @items, 'cust_bill_pkg';
+
+
+ push @labels,
+ ( $sel_agent ? '' : $agent->agent.' ' ).
+ ( $classnum eq '0'
+ ? ( ref($pkg_class) ? $pkg_class->classname : $pkg_class )
+ : ''
+ );
+
+ my $row_classnum = ref($pkg_class) ? $pkg_class->classnum : 0;
+ my $row_agentnum = $agent->agentnum;
+ push @params, [ 'classnum' => $row_classnum,
+ 'agentnum' => $row_agentnum,
+ ];
+
+ push @links, "$link;agentnum=$row_agentnum;classnum=$row_classnum;";
+
+ @recur_colors = ($col_scheme->colors)[0,4,8,1,5,9]
+ unless @recur_colors;
+ @onetime_colors = ($col_scheme->colors)[2,6,10,3,7,11]
+ unless @onetime_colors;
+ push @colors, shift @recur_colors;
+
+ }
+
+ $hue += $hue_increment;
+
+}
+
+#use Data::Dumper;
+#warn Dumper(\@items);
+
+</%init>
diff --git a/httemplate/graph/cust_pkg.cgi b/httemplate/graph/cust_pkg.cgi
new file mode 100644
index 000000000..21ce07d21
--- /dev/null
+++ b/httemplate/graph/cust_pkg.cgi
@@ -0,0 +1,63 @@
+<% include('elements/monthly.html',
+ 'title' => $agentname. 'Package Churn',
+ 'items' => \@items,
+ 'labels' => \%label,
+ 'graph_labels' => \%graph_label,
+ 'colors' => \%color,
+ 'links' => \%link,
+ 'agentnum' => $agentnum,
+ 'sprintf' => '%u',
+ 'disable_money' => 1,
+ )
+%>
+<%init>
+
+#XXX use a different ACL for package churn?
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+#false laziness w/money_time.cgi, cust_bill_pkg.cgi
+
+#XXX or virtual
+my( $agentnum, $agent ) = ('', '');
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+ $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ die "agentnum $agentnum not found!" unless $agent;
+}
+
+my $agentname = $agent ? $agent->agent.' ' : '';
+
+my @items = qw( setup_pkg susp_pkg cancel_pkg );
+
+my %label = (
+ 'setup_pkg' => 'New orders',
+ 'susp_pkg' => 'Suspensions',
+# 'unsusp' => 'Unsuspensions',
+ 'cancel_pkg' => 'Cancellations',
+);
+my %graph_label = %label;
+
+my %color = (
+ 'setup_pkg' => '00cc00', #green
+ 'susp_pkg' => 'ff9900', #yellow
+ #'unsusp' => '', #light green?
+ 'cancel_pkg' => 'cc0000', #red ? 'ff0000'
+);
+
+my %link = (
+ 'setup_pkg' => { 'link' => "${p}search/cust_pkg.cgi?agentnum=$agentnum;",
+ 'fromparam' => 'setup_begin',
+ 'toparam' => 'setup_end',
+ },
+ 'susp_pkg' => { 'link' => "${p}search/cust_pkg.cgi?agentnum=$agentnum;",
+ 'fromparam' => 'susp_begin',
+ 'toparam' => 'susp_end',
+ },
+ 'cancel_pkg' => { 'link' => "${p}search/cust_pkg.cgi?agentnum=$agentnum;",
+ 'fromparam' => 'cancel_begin',
+ 'toparam' => 'cancel_end',
+ },
+);
+
+</%init>
diff --git a/httemplate/graph/elements/monthly.html b/httemplate/graph/elements/monthly.html
new file mode 100644
index 000000000..7039bfe56
--- /dev/null
+++ b/httemplate/graph/elements/monthly.html
@@ -0,0 +1,351 @@
+<%doc>
+
+Example:
+
+ include('elements/monthly.html',
+ #required
+ 'title' => 'Page title',
+ 'items' => \@items,
+ 'labels' => \@labels, # or \%labels (keys are items)
+
+ #required?
+ 'colors' => \@colors, # or \%colors,
+
+ #recommended
+ 'graph_labels' => \@graph_labels, # or \%graph_labels,
+
+ #optional
+ 'params' => \@params, # opt,
+ 'links' => \@links, # or \%link, #opt
+ 'link_fromparam' => 'param_from', #defaults to 'begin'
+ 'link_toparam' => 'param_to', #defaults to 'end'
+
+ #optional, pulled from CGI params if not specified
+ 'start_month' => $smonth,
+ 'start_year' => $syear,
+ 'end_month' => $emonth,
+ 'end_year' => $eyear,
+
+ #optional
+ 'agentnum' => $agentnum,
+ 'nototal' => 1,
+ 'graph_type' => 'LinesPoints',
+ 'remove_empty' => 1,
+ 'bottom_total' => 1,
+ 'sprintf' => '%u', #sprintf format, overrides default %.2f
+ 'disable_money' => 1,
+ );
+
+</%doc>
+% if ( $cgi->param('_type') =~ /^(csv)$/ ) {
+%
+% #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+% http_header('Content-Type' => 'text/plain' );
+%
+% my $csv = new Text::CSV_XS { 'always_quote' => 1,
+% 'eol' => "\n", #"\015\012", #"\012"
+% };
+%
+% $csv->combine(map { my $m=$_; $m =~ s/^(\d+)\//$mon[$1-1] /; $m; }
+% ('', @{$data->{label}}, $opt{'nototal'} ? () : 'Total')
+% );
+%
+<% $csv->string %>
+%
+% my @bottom_total = ();
+% foreach ( @{ $data->{'items'} } ) {
+%
+% my $col = 0;
+% my $total = 0;
+% $csv->combine(
+% shift( @{ $data->{'item_labels'} } ),
+% map { $total += $_; $bottom_total[$col++] += $_; sprintf($sprintf, $_); }
+% ( @{ shift( @{$data->{data}} ) } ),
+% ( $opt{'nototal'} ? () : sprintf($sprintf, $total) ),
+% );
+% unless ( $opt{'nototal'} ) {
+% $bottom_total[$col++] += $total;
+% }
+%
+<% $csv->string %>
+%
+% }
+%
+% if ( $opt{'bottom_total'} ) {
+% $csv->combine(
+% 'Total',
+% map { sprintf($sprintf, $_) } @bottom_total,
+% );
+%
+<% $csv->string %>
+%
+% }
+%
+% } elsif ( $cgi->param('_type') =~ /(\.xls)$/ ) {
+%
+% #http_header('Content-Type' => 'application/excel' ); #eww
+% http_header('Content-Type' => 'application/vnd.ms-excel' );
+% #http_header('Content-Type' => 'application/msexcel' ); #alas
+%
+% my $output = '';
+% my $XLS = new IO::Scalar \$output;
+% my $workbook = Spreadsheet::WriteExcel->new($XLS)
+% or die "Error opening .xls file: $!";
+%
+% my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
+%
+% my($r,$c) = (0,0);
+%
+% foreach ('', @{$data->{label}}, ($opt{'nototal'} ? () : 'Total') ) {
+% my $header = $_;
+% $header =~ s/^(\d+)\//$mon[$1-1] /;
+% $worksheet->write($r, $c++, $header)
+% }
+%
+% my @bottom_total = ();
+% foreach ( @{ $data->{'items'} } ) {
+% $r++;
+% $c = 0;
+% my $total = 0;
+% $worksheet->write( $r, $c++, shift( @{ $data->{'item_labels'} } ) );
+% foreach ( @{ shift( @{$data->{data}} ) } ) {
+% $total += $_;
+% $bottom_total[$c] += $_;
+% $worksheet->write($r, $c++, sprintf($sprintf, $_) );
+% }
+% unless ( $opt{'nototal'} ) {
+% $bottom_total[$c] += $total;
+% $worksheet->write($r, $c++, sprintf($sprintf, $total) );
+% }
+% }
+%
+% $c = 0;
+% if ( $opt{'bottom_total'} ) {
+% $r++;
+% $worksheet->write($r, $c++, 'Total');
+% $worksheet->write($r, $c++, sprintf($sprintf, $_)) foreach @bottom_total;
+% }
+%
+% $workbook->close();# or die "Error creating .xls file: $!";
+%
+% http_header('Content-Length' => length($output) );
+%
+<% $output %>
+% } elsif ( $cgi->param('_type') =~ /^(png)$/ ) {
+%
+% #my $chart = Chart::LinesPoints->new(1024,480);
+% #my $chart = Chart::LinesPoints->new(768,480);
+%
+% my $graph_type = 'LinesPoints';
+% if ( $opt{'graph_type'} =~ /^(LinesPoints|Mountain)$/ ) {
+% $graph_type = $1;
+% }
+% my $class = "Chart::$graph_type";
+%
+% my $chart = $class->new(976,384);
+%
+% my $d = 0;
+% $chart->set(
+% #'min_val' => 0,
+% 'legend' => 'bottom',
+% 'colors' => { (
+% map { my $color = $_;
+% 'dataset'.$d++ =>
+% [ map hex($_), unpack 'a2a2a2', $color ]
+% }
+% #@{ $opt{'colors'} }
+% @{ $data->{'colors'} }
+% ),
+% #'grey_background' => [ 211, 211, 211 ],
+% 'grey_background' => 'white',
+% 'background' => [ 0xe8, 0xe8, 0xe8 ], #grey
+% },
+% #'grey_background' => 'false',
+% 'legend_labels' => $data->{'item_labels'},
+% 'brush_size' => 4,
+% #'pt_size' => 12,
+% );
+%
+% #my @data = map { $data->{$_} } ( 'label', @items );
+% my @data = @{ $data->{data} };
+% unshift @data, $data->{'label'};
+%
+% http_header('Content-Type' => 'image/png' );
+%
+% $chart->_set_colors();
+%
+<% $chart->scalar_png(\@data) %>
+%
+% } else {
+%
+<% include('/elements/header.html', $opt{'title'} ) %>
+% $cgi->param('_type', 'png');
+
+<IMG SRC="<% $cgi->self_url %>" WIDTH="976" HEIGHT="384">
+<P ALIGN="right">
+
+% unless ( $opt{'disable_download'} ) {
+% $cgi->param('_type', "monthly.xls" );
+ Download full results<BR>
+ as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
+% $cgi->param('_type', 'csv');
+ as <A HREF="<% $cgi->self_url %>">CSV file</A></P>
+% $cgi->param('_type', "html" );
+% }
+%
+</P>
+<% include('/elements/table.html', 'e8e8e8') %>
+
+<TR>
+
+ <TD></TD>
+
+% foreach my $column ( @{$data->{label}} ) {
+% #$column =~ s/^(\d+)\//$mon[$1-1]<BR>/e;
+% $column =~ s/^(\d+)\//$mon[$1-1]<BR>/;
+ <TH><% $column %></TH>
+% }
+
+% unless ( $opt{'nototal'} ) {
+ <TH>Total</TH>
+% }
+
+</TR>
+
+% my @bottom_total = ();
+% foreach my $row ( @{ $data->{'items'} } ) {
+%
+% #my $color = shift( @{ $opt{'colors'} } );
+% my $color = shift( @{ $data->{'colors'} } );
+% my $link = shift( @{ $data->{'links'} } );
+% my ( $begin, $end ) = ( $fromparam, $toparam );
+% if ( ref($link) ) {
+% my $ref = $link;
+% $link = $ref->{link};
+% $begin = $ref->{fromparam};
+% $end = $ref->{toparam};
+% }
+% $link = $link ? qq(<A HREF="$link) : '';
+% my $label = shift( @{ $data->{'item_labels'} } );
+
+ <TR>
+
+ <TH>
+ <FONT COLOR="#<% $color %>"><% $label %></FONT>
+ </TH>
+
+% #my $link = exists($opt{'links'}{$row})
+% # ? qq(<A HREF="$opt{'links'}{$row})
+% # : '';
+% my @speriod = @{$data->{speriod}};
+% my @eperiod = @{$data->{eperiod}};
+% my $total = 0;
+%
+% my $col = 0;
+% foreach my $column ( @{ shift( @{$data->{data}} ) } ) {
+
+ <TD ALIGN="right" BGCOLOR="#ffffff">
+ <% $link ? $link. "$begin=". shift(@speriod). ";$end=". shift(@eperiod). '">' : '' %><FONT COLOR="#<% $color %>"><% $money_char %><% sprintf($sprintf,, $column) %></FONT><% $link ? '</A>' : '' %>
+ </TD>
+%
+% $total += $column;
+% $bottom_total[$col++] += $column;
+%
+% }
+
+% unless ( $opt{'nototal'} ) {
+ <TD ALIGN="right" BGCOLOR="#f5f6be">
+ <% $link ? $link. "$begin=". ${$data->{speriod}}[0]. ";$end=". ${$data->{eperiod}}[-1]. '">' : '' %><FONT COLOR="#<% $color %>"><% $money_char %><% sprintf($sprintf, $total) %></FONT><% $link ? '</A>' : '' %>
+ </TD>
+% $bottom_total[$col++] += $total;
+% }
+
+ </TR>
+
+% }
+
+% if ( $opt{'bottom_total'} ) {
+% my @speriod = ( @{$data->{speriod}}, ${$data->{speriod}}[0] );
+% my @eperiod = ( @{$data->{eperiod}}, ${$data->{eperiod}}[-1] );
+
+ <TR>
+ <TH>Total</TH>
+
+% foreach my $total ( @bottom_total ) {
+
+ <TD ALIGN="right" BGCOLOR="#f5f6be">
+ <% $opt{'bottom_link'}
+ ? '<A HREF="'. $opt{'bottom_link'}.
+ "$fromparam=". shift(@speriod).
+ ";$toparam=". shift(@eperiod). '">'
+ : ''
+ %>$<% sprintf($sprintf, $total) %><% $opt{'bottom_link'} ? '</A>' : '' %>
+
+ </TD>
+
+% }
+
+ </TR>
+
+% }
+
+</TABLE>
+
+<% include('/elements/footer.html') %>
+% }
+<%once>
+
+</%once>
+<%init>
+
+my(%opt) = @_;
+
+my $sprintf = $opt{'sprintf'} || '%.2f';
+my $fromparam = $opt{'link_fromparam'} || 'begin';
+my $toparam = $opt{'link_toparam'} || 'end';
+
+my $conf = new FS::Conf;
+my $money_char = $opt{'disable_money'} ? '' : $conf->config('money_char');
+
+my @items = @{ $opt{'items'} };
+
+foreach my $other (qw( labels graph_labels colors links )) {
+#foreach my $other (qw( labels graph_labels colors )) {
+ if ( ref($opt{$other}) eq 'HASH' ) {
+ $opt{$other} = [ map $opt{$other}{$_}, @items ];
+ }
+}
+
+my @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+
+#find first month
+$opt{'start_month'} ||= $cgi->param('start_month'); # || $curmon+1;
+$opt{'start_year'} ||= $cgi->param('start_year'); # || 1899+$curyear;
+
+#find last month
+$opt{'end_month'} ||= $cgi->param('end_month'); # || $curmon+1;
+$opt{'end_year'} ||= $cgi->param('end_year'); # || 1900+$curyear;
+
+my $report = new FS::Report::Table::Monthly (
+
+ #'items' => $opt{'items'},
+ 'items' => \@items,
+ 'params' => $opt{'params'},
+ 'item_labels' => ( $cgi->param('_type') =~ /^(png)$/
+ ? $opt{'graph_labels'}
+ : $opt{'labels'}
+ ),
+ 'colors' => $opt{'colors'},
+ 'links' => $opt{'links'},
+
+ 'start_month' => $opt{'start_month'},
+ 'start_year' => $opt{'start_year'},
+ 'end_month' => $opt{'end_month'},
+ 'end_year' => $opt{'end_year'},
+
+ 'agentnum' => $opt{'agentnum'},
+ 'remove_empty' => $opt{'remove_empty'},
+);
+my $data = $report->data;
+
+</%init>
diff --git a/httemplate/graph/money_time.cgi b/httemplate/graph/money_time.cgi
new file mode 100644
index 000000000..4e4157ea1
--- /dev/null
+++ b/httemplate/graph/money_time.cgi
@@ -0,0 +1,98 @@
+<% include('elements/monthly.html',
+ 'title' => $agentname.
+ 'Sales, Credits and Receipts Summary',
+ 'items' => \@items,
+ 'labels' => \%label,
+ 'graph_labels' => \%graph_label,
+ 'colors' => \%color,
+ 'links' => \%link,
+ 'agentnum' => $agentnum,
+ 'nototal' => scalar($cgi->param('12mo')),
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+#XXX or virtual
+my( $agentnum, $agent ) = ('', '');
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+ $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+ die "agentnum $agentnum not found!" unless $agent;
+}
+
+my $agentname = $agent ? $agent->agent.' ' : '';
+
+my @items = qw( invoiced netsales
+ credits netcredits
+ payments receipts
+ refunds netrefunds
+ cashflow netcashflow
+ );
+if ( $cgi->param('12mo') == 1 ) {
+ @items = map $_.'_12mo', @items;
+}
+
+my %label = (
+ 'invoiced' => 'Gross Sales',
+ 'netsales' => 'Net Sales',
+ 'credits' => 'Gross Credits',
+ 'netcredits' => 'Net Credits',
+ 'payments' => 'Gross Receipts',
+ 'receipts' => 'Net Receipts',
+ 'refunds' => 'Gross Refunds',
+ 'netrefunds' => 'Net Refunds',
+ 'cashflow' => 'Gross Cashflow',
+ 'netcashflow' => 'Net Cashflow',
+);
+
+my %graph_suffix = (
+ 'invoiced' => ' (invoiced)',
+ 'netsales' => ' (invoiced - applied credits)',
+ 'credits' => ' (credited)',
+ 'netcredits' => ' (applied credits)',
+ 'payments' => ' (payments)',
+ 'receipts' => ' (applied payments)',
+ 'refunds' => ' (refunds)',
+ 'netrefunds' => ' (applied refunds)',
+ 'cashflow' => ' (payments - refunds)',
+ 'netcashflow' => ' (applied payments - applied refunds)',
+);
+my %graph_label = map { $_ => $label{$_}.$graph_suffix{$_} } keys %label;
+
+$label{$_.'_12mo'} = $label{$_}. " (prev 12 months)"
+ foreach keys %label;
+
+$graph_label{$_.'_12mo'} = $graph_label{$_}. " (prev 12 months)"
+ foreach keys %graph_label;
+
+my %color = (
+ 'invoiced' => '9999ff', #light blue
+ 'netsales' => '0000cc', #blue
+ 'credits' => 'ff9999', #light red
+ 'netcredits' => 'cc0000', #red
+ 'payments' => '99cc99', #light green
+ 'receipts' => '00cc00', #green
+ 'refunds' => 'ffcc99', #light orange
+ 'netrefunds' => 'ff9900', #orange
+ 'cashflow' => '99cc33', #light olive
+ 'netcashflow' => '339900', #olive
+);
+$color{$_.'_12mo'} = $color{$_}
+ foreach keys %color;
+
+my %link = (
+ 'invoiced' => "${p}search/cust_bill.html?agentnum=$agentnum;",
+ 'netsales' => "${p}search/cust_bill.html?agentnum=$agentnum;net=1;",
+ 'credits' => "${p}search/cust_credit.html?agentnum=$agentnum;",
+ 'netcredits' => "${p}search/cust_credit_bill.html?agentnum=$agentnum;",
+ 'payments' => "${p}search/cust_pay.cgi?magic=_date;agentnum=$agentnum;",
+ 'receipts' => "${p}search/cust_bill_pay.html?agentnum=$agentnum;",
+ 'refunds' => "${p}search/cust_refund.html?magic=_date;agentnum=$agentnum;",
+ 'netrefunds' => "${p}search/cust_credit_refund.html?agentnum=$agentnum;",
+);
+# XXX link 12mo?
+
+</%init>
diff --git a/httemplate/graph/report_cust_bill_pkg.html b/httemplate/graph/report_cust_bill_pkg.html
new file mode 100644
index 000000000..5193bf4a3
--- /dev/null
+++ b/httemplate/graph/report_cust_bill_pkg.html
@@ -0,0 +1,39 @@
+<% include('/elements/header.html', 'Sales Report' ) %>
+
+<FORM ACTION="cust_bill_pkg.cgi" METHOD="GET">
+
+<TABLE>
+
+<% include('/elements/tr-select-from_to.html' ) %>
+
+<% include('/elements/tr-select-agent.html',
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0,
+ )
+%>
+
+<% include('/elements/tr-select-pkg_class.html',
+ 'pre_options' => [ '0' => 'all' ],
+ 'empty_label' => '(empty class)',
+ )
+%>
+
+<!--
+<TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="separate_0freq" VALUE="1"></TD>
+ <TD>Separate one-time vs. recurring sales</TD>
+</TR>
+-->
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Display">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/graph/report_cust_pkg.html b/httemplate/graph/report_cust_pkg.html
new file mode 100644
index 000000000..22ccd5def
--- /dev/null
+++ b/httemplate/graph/report_cust_pkg.html
@@ -0,0 +1,28 @@
+<% include('/elements/header.html', 'Package Churn Summary' ) %>
+
+<FORM ACTION="cust_pkg.cgi" METHOD="GET">
+
+<TABLE>
+
+<% include('/elements/tr-select-from_to.html' ) %>
+
+<% include('/elements/tr-select-agent.html',
+ 'curr_value' => scalar($cgi->param('agentnum')),
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0,
+ )
+%>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Display">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+#XXX use a different ACL for package churn?
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/graph/report_money_time.html b/httemplate/graph/report_money_time.html
new file mode 100644
index 000000000..b85bb6552
--- /dev/null
+++ b/httemplate/graph/report_money_time.html
@@ -0,0 +1,43 @@
+<% include('/elements/header.html', 'Sales, Credits and Receipts Summary' ) %>
+
+<FORM ACTION="money_time.cgi" METHOD="GET">
+
+<!--
+<INPUT TYPE="checkbox" NAME="ar">
+ Accounts receivable (invoices - applied credits)<BR>
+<INPUT TYPE="checkbox" NAME="charged">
+ Just Invoices<BR>
+<INPUT TYPE="checkbox" NAME="defer">
+ Accounts receivable, with deferred revenue (invoices - applied credits, with charges for annual/semi-annual/quarterly/etc. services deferred over applicable time period) (there has got to be a shorter description for this)<BR>
+<INPUT TYPE="checkbox" NAME="cash">
+ Cashflow (payments - refunds)<BR>
+<BR>
+-->
+
+<TABLE>
+
+<% include('/elements/tr-select-from_to.html' ) %>
+
+<% include('/elements/tr-select-agent.html',
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0,
+ )
+%>
+
+<TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="12mo" VALUE="1"></TD>
+ <TD>Show 12 month totals instead of monthly values</TD>
+</TR>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Display">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/images/32clear.gif b/httemplate/images/32clear.gif
new file mode 100644
index 000000000..5fdcea204
--- /dev/null
+++ b/httemplate/images/32clear.gif
Binary files differ
diff --git a/httemplate/images/ach.png b/httemplate/images/ach.png
new file mode 100644
index 000000000..fdcd5e6ed
--- /dev/null
+++ b/httemplate/images/ach.png
Binary files differ
diff --git a/httemplate/images/arrow.down.png b/httemplate/images/arrow.down.png
new file mode 100644
index 000000000..34cb0286a
--- /dev/null
+++ b/httemplate/images/arrow.down.png
Binary files differ
diff --git a/httemplate/images/arrow.right.black.png b/httemplate/images/arrow.right.black.png
new file mode 100644
index 000000000..933c25894
--- /dev/null
+++ b/httemplate/images/arrow.right.black.png
Binary files differ
diff --git a/httemplate/images/arrow.right.png b/httemplate/images/arrow.right.png
new file mode 100644
index 000000000..60bcb76ab
--- /dev/null
+++ b/httemplate/images/arrow.right.png
Binary files differ
diff --git a/httemplate/images/background-cheat.png b/httemplate/images/background-cheat.png
new file mode 100644
index 000000000..ad332f675
--- /dev/null
+++ b/httemplate/images/background-cheat.png
Binary files differ
diff --git a/httemplate/images/black-gradient.png b/httemplate/images/black-gradient.png
new file mode 100644
index 000000000..225732d16
--- /dev/null
+++ b/httemplate/images/black-gradient.png
Binary files differ
diff --git a/httemplate/images/black-gray-corner.png b/httemplate/images/black-gray-corner.png
new file mode 100644
index 000000000..17954cdd7
--- /dev/null
+++ b/httemplate/images/black-gray-corner.png
Binary files differ
diff --git a/httemplate/images/black-gray-gradient.png b/httemplate/images/black-gray-gradient.png
new file mode 100644
index 000000000..f5c318fe7
--- /dev/null
+++ b/httemplate/images/black-gray-gradient.png
Binary files differ
diff --git a/httemplate/images/black-gray-side.png b/httemplate/images/black-gray-side.png
new file mode 100644
index 000000000..f7a98a43d
--- /dev/null
+++ b/httemplate/images/black-gray-side.png
Binary files differ
diff --git a/httemplate/images/black-gray-top.png b/httemplate/images/black-gray-top.png
new file mode 100644
index 000000000..ed0707573
--- /dev/null
+++ b/httemplate/images/black-gray-top.png
Binary files differ
diff --git a/httemplate/images/calendar-disabled.png b/httemplate/images/calendar-disabled.png
new file mode 100644
index 000000000..81816bcd6
--- /dev/null
+++ b/httemplate/images/calendar-disabled.png
Binary files differ
diff --git a/httemplate/images/calendar.png b/httemplate/images/calendar.png
new file mode 100644
index 000000000..163266174
--- /dev/null
+++ b/httemplate/images/calendar.png
Binary files differ
diff --git a/httemplate/images/cross.png b/httemplate/images/cross.png
new file mode 100644
index 000000000..1514d51a3
--- /dev/null
+++ b/httemplate/images/cross.png
Binary files differ
diff --git a/httemplate/images/cvv2.png b/httemplate/images/cvv2.png
new file mode 100644
index 000000000..48c58d561
--- /dev/null
+++ b/httemplate/images/cvv2.png
Binary files differ
diff --git a/httemplate/images/cvv2_amex.png b/httemplate/images/cvv2_amex.png
new file mode 100644
index 000000000..82d1f4715
--- /dev/null
+++ b/httemplate/images/cvv2_amex.png
Binary files differ
diff --git a/httemplate/images/error.png b/httemplate/images/error.png
new file mode 100644
index 000000000..628cf2dae
--- /dev/null
+++ b/httemplate/images/error.png
Binary files differ
diff --git a/httemplate/images/menu-left-example.png b/httemplate/images/menu-left-example.png
new file mode 100644
index 000000000..375725cb9
--- /dev/null
+++ b/httemplate/images/menu-left-example.png
Binary files differ
diff --git a/httemplate/images/menu-top-example.png b/httemplate/images/menu-top-example.png
new file mode 100644
index 000000000..bd9bea883
--- /dev/null
+++ b/httemplate/images/menu-top-example.png
Binary files differ
diff --git a/httemplate/images/progressbar-empty.png b/httemplate/images/progressbar-empty.png
new file mode 100644
index 000000000..318219c77
--- /dev/null
+++ b/httemplate/images/progressbar-empty.png
Binary files differ
diff --git a/httemplate/images/progressbar-full.png b/httemplate/images/progressbar-full.png
new file mode 100644
index 000000000..863d8e1ee
--- /dev/null
+++ b/httemplate/images/progressbar-full.png
Binary files differ
diff --git a/httemplate/images/red_telephone_mimooh_01.png b/httemplate/images/red_telephone_mimooh_01.png
new file mode 100644
index 000000000..2212ff0e8
--- /dev/null
+++ b/httemplate/images/red_telephone_mimooh_01.png
Binary files differ
diff --git a/httemplate/images/small-logo.png b/httemplate/images/small-logo.png
new file mode 100644
index 000000000..1e415e6d8
--- /dev/null
+++ b/httemplate/images/small-logo.png
Binary files differ
diff --git a/httemplate/images/tick.png b/httemplate/images/tick.png
new file mode 100644
index 000000000..a9925a06a
--- /dev/null
+++ b/httemplate/images/tick.png
Binary files differ
diff --git a/httemplate/images/wait-orange.gif b/httemplate/images/wait-orange.gif
new file mode 100644
index 000000000..92c7f3476
--- /dev/null
+++ b/httemplate/images/wait-orange.gif
Binary files differ
diff --git a/httemplate/index.html b/httemplate/index.html
new file mode 100644
index 000000000..c813991f9
--- /dev/null
+++ b/httemplate/index.html
@@ -0,0 +1,54 @@
+% my $conf = new FS::Conf;
+
+<% include('/elements/header.html', 'Billing Main' ) %>
+
+<% include('/elements/dashboard-toplist.html') %>
+
+% my $sth = dbh->prepare(
+% #"SELECT DISTINCT custnum FROM h_cust_main JOIN cust_main USING ( custnum )
+% "SELECT custnum FROM h_cust_main JOIN cust_main USING ( custnum )
+% WHERE ( history_action = 'insert' OR history_action = 'replace_new' )
+% AND history_user = ?
+% ORDER BY history_date desc" # LIMIT 10
+% ) or die dbh->errstr;
+%
+% $sth->execute( getotaker() ) or die $sth->errstr;
+%
+% my %saw = ();
+% my @custnums = grep { !$saw{$_}++ } map $_->[0], @{ $sth->fetchall_arrayref };
+%
+% @custnums = splice(@custnums, 0, 10);
+%
+% if ( @custnums ) {
+
+ <% include('/elements/table-grid.html') %>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = $bgcolor2;
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=1>Customers I recently added or modified</TH>
+ </TR>
+
+% foreach my $custnum ( @custnums ) {
+% my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+% next unless $cust_main;
+
+ <TR>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="view/cust_main.cgi?<% $custnum %>"><% $cust_main->display_custnum %>: <% $cust_main->name %></A></TD>
+ </TR>
+
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% }
+
+ </TABLE>
+
+% }
+
+<% include('/elements/footer.html') %>
diff --git a/httemplate/misc/areacodes.cgi b/httemplate/misc/areacodes.cgi
new file mode 100644
index 000000000..69c9573c3
--- /dev/null
+++ b/httemplate/misc/areacodes.cgi
@@ -0,0 +1,24 @@
+%# [ <% join(', ', map { qq("$_") } @areacodes) %> ]
+<% objToJson(\@areacodes) %>
+<%init>
+
+my( $state, $svcpart ) = $cgi->param('arg');
+
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @exports = $part_svc->part_export_did;
+if ( scalar(@exports) > 1 ) {
+ die "more than one DID-providing export attached to svcpart $svcpart";
+} elsif ( ! @exports ) {
+ die "no DID providing export attached to svcpart $svcpart";
+}
+my $export = $exports[0];
+
+my $something = $export->get_dids('state'=>$state);
+
+#warn Dumper($something);
+
+my @areacodes = @{ $something };
+
+</%init>
diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html
new file mode 100644
index 000000000..e10a5f658
--- /dev/null
+++ b/httemplate/misc/batch-cust_pay.html
@@ -0,0 +1,38 @@
+<% include('/elements/header.html', 'Quick payment entry') %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="process/batch-cust_pay.cgi" NAME="OneTrueForm" METHOD="POST" onsubmit="document.OneTrueForm.submit.disabled=true;">
+
+<!-- <B>Batch</B> <INPUT TYPE="text" NAME="paybatch"><BR><BR> -->
+
+<% include( "/elements/customer-table.html",
+ name_singular => 'payment',
+ header => [ '', 'Amount', 'Check #', '' ],
+ fields => [ sub {'$'}, 'paid', 'payinfo', 'error', ],
+ types => [ 'immutable', '', '', 'immutable', ],
+ align => [ 'c', 'r', 'r', 'l' ],
+ sizes => [ 0, 8, 10, 0, ],
+ colors => [ '', '', '', '#ff0000' ],
+ param => { () },
+ footer => [ '$', '_TOTAL', '', '' ],
+ footer_align => [ 'c', 'r', 'r', '' ],
+ )
+%>
+
+<!-- <BR>
+<INPUT TYPE="button" VALUE="TEST addrow" onclick="addRow()"> -->
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Post payment batch">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post payment batch');
+
+</%init>
diff --git a/httemplate/misc/bill.cgi b/httemplate/misc/bill.cgi
new file mode 100755
index 000000000..3c3c48c54
--- /dev/null
+++ b/httemplate/misc/bill.cgi
@@ -0,0 +1,45 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2). "view/cust_main.cgi?$custnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bill customer now');
+
+#untaint custnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d*)$/;
+my $custnum = $1;
+my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum});
+die "Can't find customer!\n" unless $cust_main;
+
+my $conf = new FS::Conf;
+
+my $error = $cust_main->bill(
+# 'time'=>$time
+ );
+
+unless ( $error ) {
+ $error = $cust_main->apply_payments_and_credits
+ || $cust_main->collect(
+ #'invoice-time'=>$time,
+ #'batch_card'=> 'yes',
+ #'batch_card'=> 'no',
+ #'report_badcard'=> 'yes',
+ #'retry_card' => 'yes',
+
+ 'retry' => 'yes',
+
+ #this is used only by cust_main::batch_card
+ #need to pick & create an actual config
+ #value if we're going to turn this on
+ #("realtime-backend" doesn't exist,
+ # "backend-realtime" is for something
+ # entirely different)
+ #'realtime' => $conf->exists('realtime-backend'),
+ );
+}
+
+</%init>
diff --git a/httemplate/misc/bulk_change_pkg.cgi b/httemplate/misc/bulk_change_pkg.cgi
new file mode 100755
index 000000000..93349859d
--- /dev/null
+++ b/httemplate/misc/bulk_change_pkg.cgi
@@ -0,0 +1,59 @@
+<% include('/elements/header-popup.html', "Change Packages") %>
+
+% if ( $cgi->param('error') ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $cgi->param('error') %></FONT>
+ <BR><BR>
+% }
+
+<FORM ACTION="<% $p %>misc/process/bulk_change_pkg.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="query" VALUE="<% $cgi->keywords %>">
+% for my $param (qw(agentnum magic status classnum pkgpart)) {
+<INPUT TYPE="hidden" NAME="<% $param %>" VALUE="<% $cgi->param($param) %>">
+% }
+%
+% foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
+%
+ <INPUT TYPE="hidden" NAME="<% $field %>begin" VALUE="<% $cgi->param("${field}.begin") %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>beginning" VALUE="<% $cgi->param("${field}beginning") %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>end" VALUE="<% $cgi->param("${field}.end") %>">
+ <INPUT TYPE="hidden" NAME="<% $field %>ending" VALUE="<% $cgi->param("${field}.ending") %>">
+% }
+
+<% ntable('#cccccc') %>
+
+ <TR>
+ <TD>New package: </TD>
+ <TD><% include('/elements/select-table.html',
+ 'table' => 'part_pkg',
+ 'name_col' => 'pkg',
+ 'empty_label' => 'Select package',
+ 'label_callback' => sub { $_[0]->pkgpart. ': '.
+ $_[0]->pkg. ' - '.
+ $_[0]->comment;
+ },
+ 'element_name' => 'new_pkgpart',
+ 'curr_value' => ( $cgi->param('error')
+ ? scalar($cgi->param('new_pkgpart'))
+ : ''
+ ),
+ )
+ %>
+ </TD>
+ </TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Change packages">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages');
+
+</%init>
diff --git a/httemplate/misc/cancel-unaudited.cgi b/httemplate/misc/cancel-unaudited.cgi
new file mode 100755
index 000000000..4919c6632
--- /dev/null
+++ b/httemplate/misc/cancel-unaudited.cgi
@@ -0,0 +1,33 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2)) %>
+%}
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unprovision customer service')
+ && $FS::CurrentUser::CurrentUser->access_right('View/link unlinked services');
+
+#untaint svcnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+
+#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
+#die "Unknown svcnum!" unless $svc_acct;
+
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "Unknown svcnum!" unless $cust_svc;
+my $cust_pkg = $cust_svc->cust_pkg;
+if ( $cust_pkg ) {
+ errorpage( 'This account has already been audited. Cancel the '.
+ qq!<A HREF="${p}view/cust_main.cgi?!. $cust_pkg->custnum.
+ '#cust_pkg'. $cust_pkg->pkgnum. '">'.
+ 'package</A> instead.');
+}
+
+my $error = $cust_svc->cancel;
+
+</%init>
diff --git a/httemplate/misc/cancel_cust.html b/httemplate/misc/cancel_cust.html
new file mode 100644
index 000000000..12c37ebe2
--- /dev/null
+++ b/httemplate/misc/cancel_cust.html
@@ -0,0 +1,63 @@
+<% include('/elements/header-popup.html', 'Cancel customer' ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="cust_cancel_popup" ACTION="<% popurl(1) %>cust_main-cancel.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+
+
+ <P ALIGN="center"><B>Permanently delete all services and cancel this customer?</B>
+
+ <% $ban %>
+
+<BR><BR>
+
+<% ntable("#cccccc", 2) %>
+
+<% include('/elements/tr-select-reason.html',
+ 'field' => 'reasonnum',
+ 'reason_class' => 'C',
+ 'cgi' => $cgi,
+ 'control_button' => "document.getElementById('confirm_cancel_cust_button')",
+ )
+%>
+
+</TABLE>
+
+<BR>
+<P ALIGN="CENTER">
+<INPUT TYPE="submit" NAME="submit" ID="confirm_cancel_cust_button" VALUE="Cancel customer" DISABLED> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="BUTTON" VALUE="Don't cancel" onClick="parent.cClick();">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
+my $custnum = $1;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied" unless $curuser->access_right('Cancel customer');
+
+my $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+} );
+die "No customer # $custnum" unless $cust_main;
+
+my $ban = '';
+if ( $cust_main->payby =~ /^(CARD|DCRD|CHEK|DCHK)$/ ) {
+ $ban = '<BR><P ALIGN="center">'.
+ '<INPUT TYPE="checkbox" NAME="ban" VALUE="1"> Ban this customer\'s ';
+ if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) {
+ $ban .= 'credit card';
+ } elsif ( $cust_main->payby =~ /^(CHEK|DCHK)$/ ) {
+ $ban .= 'ACH account';
+ }
+}
+
+</%init>
+
diff --git a/httemplate/misc/cancel_pkg.html b/httemplate/misc/cancel_pkg.html
new file mode 100755
index 000000000..e0e5fd1f8
--- /dev/null
+++ b/httemplate/misc/cancel_pkg.html
@@ -0,0 +1,109 @@
+%# if ( $link eq 'popup' ) {
+ <% include('/elements/header-popup.html', $title ) %>
+%# } else {
+%# <% include("/elements/header.html", $title, '') %>
+%# }
+
+<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="sc_popup" ACTION="<% popurl(1) %>process/cancel_pkg.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="method" VALUE="<% $method %>">
+
+
+<BR><BR>
+<% ucfirst($method) . " $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% ntable("#cccccc", 2) %>
+
+% if ($method eq 'expire' || $method eq 'adjourn') {
+<TR>
+ <TD><% $submit =~ /^(\w*)\s/ %> package on </TD>
+ <TD><INPUT TYPE="text" NAME="date" ID="expire_date" VALUE="<% $date |h %>">
+ <IMG SRC="<% $p %>images/calendar.png" ID="expire_button" STYLE="cursor:pointer" TITLE="Select date">
+ <BR><I>m/d/y</I>
+ </TD>
+</TR>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "expire_date",
+ ifFormat: "%m/%d/%Y",
+ button: "expire_button",
+ align: "BR"
+ });
+</SCRIPT>
+%}
+%
+
+<% include('/elements/tr-select-reason.html',
+ 'field' => 'reasonnum',
+ 'reason_class' => $class,
+ 'curr_value' => $reasonnum,
+ 'control_button' => "document.getElementById('confirm_cancel_pkg_button')",
+ )
+%>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" ID="confirm_cancel_pkg_button" VALUE="<% $submit %>" DISABLED>
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $date = time2str("%m/%d/%Y", time);
+
+my($pkgnum, $reasonnum);
+if ( $cgi->param('error') ) {
+ $pkgnum = $cgi->param('pkgnum');
+ $reasonnum = $cgi->param('reasonnum');
+ $date = $cgi->param('date');
+} elsif ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
+ $pkgnum = $1;
+ $reasonnum = '';
+} else {
+ die "illegal query ". $cgi->keywords;
+}
+
+$cgi->param('method') =~ /^(\w+)$/ or die 'illegal method';
+my $method = $1;
+
+my($class, $submit, $right);
+if ($method eq 'cancel') {
+ $class = 'C';
+ $submit = 'Cancel Now';
+ $right = 'Cancel customer package immediately';
+} elsif ($method eq 'expire') {
+ $class = 'C';
+ $submit = 'Cancel Later';
+ $right = 'Cancel customer package later';
+} elsif ($method eq 'suspend') {
+ $class = 'S';
+ $submit = 'Suspend Now';
+ $right = 'Suspend customer package';
+} elsif ($method eq 'adjourn') {
+ $class = 'S';
+ $submit = "Suspend Later";
+ $right = 'Suspend customer package later';
+} else {
+ die 'illegal query (unknown method param)';
+}
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right($right);
+
+my $title = ucfirst($method) . ' Package';
+
+my $cust_pkg = qsearchs('cust_pkg', {'pkgnum' => $pkgnum})
+ or die "Unknown pkgnum: $pkgnum";
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+</%init>
diff --git a/httemplate/misc/catchall.cgi b/httemplate/misc/catchall.cgi
new file mode 100755
index 000000000..240f34d0e
--- /dev/null
+++ b/httemplate/misc/catchall.cgi
@@ -0,0 +1,118 @@
+<% include('/elements/header.html', 'Domain Catchall Edit') %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<%$p1%>process/catchall.cgi" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum |h %>">
+Service #<FONT SIZE=+1><B><% $svcnum ? $svcnum : ' (NEW)' |h %></B></FONT>
+<BR><BR>
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum |h %>">
+
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+
+% my $domain = $svc_domain->domain;
+% my $catchall = $svc_domain->catchall;
+
+<INPUT TYPE="hidden" NAME="domain" VALUE="<% $domain |h %>">
+
+Mail to <I>(anything)</I>@<B><% $domain |h %></B> forwards to <SELECT NAME="catchall" SIZE=1>
+% foreach $_ (keys %email) {
+ <OPTION<% $_ eq $catchall ? ' SELECTED' : '' %> VALUE="<% $_ %>"><% $email{$_} %>
+% }
+</SELECT>
+<BR><BR>
+
+<INPUT TYPE="submit" VALUE="Submit">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall');
+
+my $conf = new FS::Conf;
+
+my($svc_domain, $svcnum, $pkgnum, $svcpart, $part_svc);
+if ( $cgi->param('error') ) {
+ $svc_domain = new FS::svc_domain ( {
+ map { $_, scalar($cgi->param($_)) } fields('svc_domain')
+ } );
+ $svcnum = $svc_domain->svcnum;
+ $pkgnum = $cgi->param('pkgnum');
+ $svcpart = $cgi->param('svcpart');
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+} else {
+ my($query) = $cgi->keywords;
+ if ( $query =~ /^(\d+)$/ ) { #editing
+ $svcnum=$1;
+ $svc_domain=qsearchs('svc_domain',{'svcnum'=>$svcnum})
+ or die "Unknown (svc_domain) svcnum!";
+
+ my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+ or die "Unknown (cust_svc) svcnum!";
+
+ $pkgnum=$cust_svc->pkgnum;
+ $svcpart=$cust_svc->svcpart;
+
+ $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+ die "No part_svc entry!" unless $part_svc;
+
+ } else {
+
+ die "Invalid (svc_domain) svcnum!";
+
+ }
+}
+
+my %email;
+if ($pkgnum) {
+
+ #find all possible user svcnums (and emails)
+
+ #starting with that currently attached
+ if ($svc_domain->catchall) {
+ my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$svc_domain->catchall});
+ $email{$svc_domain->catchall} = $svc_acct->email;
+ }
+
+ #and including the rest for this customer
+ my($u_part_svc,@u_acct_svcparts);
+ foreach $u_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_acct'}) ) {
+ push @u_acct_svcparts,$u_part_svc->getfield('svcpart');
+ }
+
+ my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ my($custnum)=$cust_pkg->getfield('custnum');
+ my($i_cust_pkg);
+ foreach $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) {
+ my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum');
+ my($acct_svcpart);
+ foreach $acct_svcpart (@u_acct_svcparts) { #now find the corresponding
+ #record(s) in cust_svc ( for this
+ #pkgnum ! )
+ my($i_cust_svc);
+ foreach $i_cust_svc ( qsearch('cust_svc',{'pkgnum'=>$cust_pkgnum,'svcpart'=>$acct_svcpart}) ) {
+ my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$i_cust_svc->getfield('svcnum')});
+ $email{$svc_acct->getfield('svcnum')}=$svc_acct->email;
+ }
+ }
+ }
+
+} else {
+
+ my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$svc_domain->catchall});
+ $email{$svc_domain->catchall} = $svc_acct->email;
+}
+
+# add an absence of a catchall
+$email{''} = "(none)";
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/misc/cdr-import.html b/httemplate/misc/cdr-import.html
new file mode 100644
index 000000000..7af6c521f
--- /dev/null
+++ b/httemplate/misc/cdr-import.html
@@ -0,0 +1,61 @@
+<% include("/elements/header.html",'Call Detail Record Import') %>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'CDRImportForm',
+ 'action' => 'process/cdr-import.html',
+ 'num_files' => 1,
+ 'fields' => [ 'format', 'cdrbatch', ],
+ 'message' => 'CDR import successful',
+ 'url' => $p."search/cdr.html?cdrbatch=$cdrbatch",
+ )
+%>
+
+Import a file containing Call Detail Records (CDRs).<BR><BR>
+
+<INPUT TYPE="hidden" NAME="cdrbatch" VALUE="<% $cdrbatch %>"%>
+
+<% ntable('#cccccc', 2) %>
+
+ <TR>
+ <TD>CDR Format</TD>
+ <TD>
+ <SELECT NAME="format">
+% foreach my $format ( keys %formats ) {
+ <OPTION VALUE="<% $format %>"><% $formats{$format} %></OPTION>
+% }
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => 'Filename',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Import file"
+ onClick = "document.InventoryItemImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+tie my %formats, 'Tie::IxHash', FS::cdr->import_formats;
+
+my $cdrbatch = time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+</%init>
diff --git a/httemplate/misc/cdr.cgi b/httemplate/misc/cdr.cgi
new file mode 100644
index 000000000..d2ee77364
--- /dev/null
+++ b/httemplate/misc/cdr.cgi
@@ -0,0 +1,48 @@
+%# <% $cgi->redirect(popurl(2). "search/cdr.html") %>
+%# i should be a popup and reload my parent... until then, this will do
+<% include('/elements/header.html','CDR update successful') %>
+<% include('/elements/footer.html') %>
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit rating data');
+
+$cgi->param('action') =~ /^(new|del|(reprocess|delete) selected)$/
+ or die "Illegal action";
+my $action = $1;
+
+my $cdr;
+if ( $action eq 'new' || $action eq 'del' ) {
+ $cgi->param('acctid') =~ /^(\d+)$/ or die "Illegal acctid";
+ my $acctid = $1;
+ $cdr = qsearchs('cdr', { 'acctid' => $1 })
+ or die "unknown acctid $acctid";
+}
+
+if ( $action eq 'new' ) {
+ my %hash = $cdr->hash;
+ $hash{'freesidestatus'} = '';
+ my $new = new FS::cdr \%hash;
+ my $error = $new->replace($cdr);
+ die $error if $error;
+} elsif ( $action eq 'del' ) {
+ my $error = $cdr->delete;
+ die $error if $error;
+} elsif ( $action =~ /^(reprocess|delete) selected$/ ) {
+ foreach my $acctid (
+ map { /^acctid(\d+)$/; $1; } grep /^acctid\d+$/, $cgi->param
+ ) {
+ my $cdr = qsearchs('cdr', { 'acctid' => $acctid });
+ if ( $action eq 'reprocess selected' && $cdr ) { #new
+ my %hash = $cdr->hash;
+ $hash{'freesidestatus'} = '';
+ my $new = new FS::cdr \%hash;
+ my $error = $new->replace($cdr);
+ die $error if $error;
+ } elsif ( $action eq 'delete selected' && $cdr ) { #del
+ my $error = $cdr->delete;
+ die $error if $error;
+ }
+ }
+}
+
+</%init>
diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi
new file mode 100755
index 000000000..c4dfca200
--- /dev/null
+++ b/httemplate/misc/change_pkg.cgi
@@ -0,0 +1,72 @@
+<% include('/elements/header-popup.html', "Change Package") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p %>edit/process/change-cust_pkg.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+<% ntable('#cccccc') %>
+
+ <TR>
+ <TH ALIGN="right">Current package</TH>
+ <TD COLSPAN=7>
+ <% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B> - <% $part_pkg->comment |h %>
+ </TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">New package</TH>
+ <TD COLSPAN=7>
+ <% include('/elements/select-cust-part_pkg.html',
+ 'cust_main' => $cust_main,
+ 'element_name' => 'pkgpart',
+ #'extra_sql' => ' AND pkgpart != '. $cust_pkg->pkgpart,
+ 'curr_value' => scalar($cgi->param('pkgpart')),
+ )
+ %>
+ </TD>
+ </TR>
+
+ <% include('/elements/tr-select-cust_location.html',
+ 'cgi' => $cgi,
+ 'cust_main' => $cust_main,
+ )
+ %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Change package">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Change customer package');
+
+my $pkgnum = scalar($cgi->param('pkgnum'));
+$pkgnum =~ /^(\d+)$/ or die "illegal pkgnum $pkgnum";
+$pkgnum = $1;
+
+my $cust_pkg =
+ qsearchs({
+ 'table' => 'cust_pkg',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'pkgnum' => $pkgnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ }) or die "unknown pkgnum $pkgnum";
+
+my $cust_main = $cust_pkg->cust_main
+ or die "can't get cust_main record for custnum ". $cust_pkg->custnum.
+ " ( pkgnum ". cust_pkg->pkgnum. ")";
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+</%init>
diff --git a/httemplate/misc/copy-rate_detail.html b/httemplate/misc/copy-rate_detail.html
new file mode 100644
index 000000000..3d328ce59
--- /dev/null
+++ b/httemplate/misc/copy-rate_detail.html
@@ -0,0 +1,61 @@
+<% include( '/elements/header.html', 'Copy rates between plans', menubar(
+ 'View all rate plans' => "${p}browse/rate.cgi",
+ ))
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="process/copy-rate_detail.html">
+
+<% ntable('#cccccc') %>
+
+ <% include( '/elements/tr-justtitle.html', 'value' => 'Copy rates' ) %>
+
+ <% include( '/elements/tr-select-rate.html',
+ 'label' => 'From rate plan',
+ 'element_name' => 'src_ratenum',
+ )
+ %>
+
+ <% include( '/elements/tr-select-rate.html',
+ 'label' => 'To rate plan',
+ 'element_name' => 'dst_ratenum',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2>Copy country codes</TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2>
+
+ <% include( '/elements/checkboxes.html',
+ 'names_list' => [ FS::rate_prefix->all_countrycodes ],
+ 'element_name_prefix' => 'countrycode',
+ )
+ %>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center">
+ <INPUT TYPE="submit" VALUE="Copy rates">
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#should have some javascript that enables submit button only when both src & dst
+#rates are chosen
+
+</%init>
diff --git a/httemplate/misc/counties.cgi b/httemplate/misc/counties.cgi
new file mode 100644
index 000000000..c022a27d9
--- /dev/null
+++ b/httemplate/misc/counties.cgi
@@ -0,0 +1,7 @@
+[ <% join(', ', map { qq("$_") } @counties) %> ]
+<%init>
+
+my( $state, $country ) = $cgi->param('arg');
+my @counties = counties($state, $country);
+
+</%init>
diff --git a/httemplate/misc/cust_main-cancel.cgi b/httemplate/misc/cust_main-cancel.cgi
new file mode 100755
index 000000000..009a7d41b
--- /dev/null
+++ b/httemplate/misc/cust_main-cancel.cgi
@@ -0,0 +1,57 @@
+<% header("Customer cancelled") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Cancel customer');
+
+my $custnum;
+my $ban = '';
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $custnum = $1;
+ $ban = $cgi->param('ban');
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ || die "Illegal custnum";
+ $custnum = $1;
+}
+
+#false laziness w/process/cancel_pkg.html
+
+#untaint reasonnum
+my $reasonnum = $cgi->param('reasonnum');
+$reasonnum =~ /^(-?\d+)$/ || die "Illegal reasonnum";
+$reasonnum = $1;
+
+if ($reasonnum == -1) {
+ $reasonnum = {
+ 'typenum' => scalar( $cgi->param('newreasonnumT') ),
+ 'reason' => scalar( $cgi->param('newreasonnum' ) ),
+ };
+}
+
+#eslaf
+
+my $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+} );
+
+warn "cancelling $cust_main";
+my @errors = $cust_main->cancel(
+ 'ban' => $ban,
+ 'reason' => $reasonnum,
+);
+my $error = join(' / ', @errors) if scalar(@errors);
+
+if ( $error ) {
+ $cgi->param('error', $error);
+ print $cgi->redirect(popurl(1). "cancel_cust.html?". $cgi->query_string );
+}
+
+</%init>
diff --git a/httemplate/misc/cust_main-import.cgi b/httemplate/misc/cust_main-import.cgi
new file mode 100644
index 000000000..b822c5dab
--- /dev/null
+++ b/httemplate/misc/cust_main-import.cgi
@@ -0,0 +1,148 @@
+<% include("/elements/header.html",'Batch Customer Import') %>
+
+Import a file containing customer records.
+<BR><BR>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'CustomerImportForm',
+ 'action' => 'process/cust_main-import.cgi',
+ 'num_files' => 1,
+ 'fields' => [ 'agentnum', 'custbatch', 'format' ],
+ 'message' => 'Customer import successful',
+ 'url' => $p."search/cust_main.html?custbatch=$custbatch",
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <% include( '/elements/tr-select-agent.html',
+ #'curr_value' => '', #$agentnum,
+ 'label' => "<B>Agent</B>",
+ 'empty_label' => 'Select agent',
+ )
+ %>
+
+ <INPUT TYPE="hidden" NAME="custbatch" VALUE="<% $custbatch %>"%>
+
+ <TR>
+ <TH ALIGN="right">Format</TH>
+ <TD>
+ <SELECT NAME="format">
+ <!-- <OPTION VALUE="simple">Simple -->
+ <OPTION VALUE="extended" SELECTED>Extended
+ <OPTION VALUE="extended-plus_company">Extended plus company
+ <OPTION VALUE="svc_external">External service
+ <OPTION VALUE="svc_external_svc_phone">External service and phone service
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => 'Filename',
+ )
+ %>
+
+
+% #include('/elements/tr-select-part_referral.html')
+%
+
+
+<!--
+<TR>
+ <TH>First package</TH>
+ <TD>
+ This needs to be agent-virtualized if it gets used!
+ <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
+% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) {
+
+ <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+% }
+
+ </SELECT>
+ </TD>
+</TR>
+-->
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Import file"
+ onClick = "document.CustomerImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+
+<!-- Simple file format is CSV, with the following field order: <i>cust_pkg.setup, dayphone, first, last, address1, address2, city, state, zip, comments</i>
+<BR><BR> -->
+
+Uploaded files can be CSV (comma-separated value) files or Excel spreadsheets. The file should have a .CSV or .XLS extension.
+<BR><BR>
+
+<b>Extended</b> format has the following field order: <i>agent_custid, refnum<%$req%>, last<%$req%>, first<%$req%>, address1<%$req%>, address2, city<%$req%>, state<%$req%>, zip<%$req%>, country, daytime, night, ship_last, ship_first, ship_address1, ship_address2, ship_city, ship_state, ship_zip, ship_country, payinfo, paycvv, paydate, invoicing_list, pkgpart, username, _password</i>
+<BR><BR>
+
+<b>Extended plus company</b> format has the following field order: <i>agent_custid, refnum<%$req%>, last<%$req%>, first<%$req%>, company, address1<%$req%>, address2, city<%$req%>, state<%$req%>, zip<%$req%>, country, daytime, night, ship_last, ship_first, ship_company, ship_address1, ship_address2, ship_city, ship_state, ship_zip, ship_country, payinfo, paycvv, paydate, invoicing_list, pkgpart, username, _password</i>
+<BR><BR>
+
+<b>External service</b> format has the following field order: <i>agent_custid, refnum<%$req%>, last<%$req%>, first<%$req%>, company, address1<%$req%>, address2, city<%$req%>, state<%$req%>, zip<%$req%>, country, daytime, night, ship_last, ship_first, ship_company, ship_address1, ship_address2, ship_city, ship_state, ship_zip, ship_country, payinfo, paycvv, paydate, invoicing_list, pkgpart, next_bill_date, id, title</i>
+<BR><BR>
+
+<b>External service and phone service</b> format has the following field order: <i>agent_custid, refnum<%$req%>, last<%$req%>, first<%$req%>, company, address1<%$req%>, address2, city<%$req%>, state<%$req%>, zip<%$req%>, country, daytime, night, ship_last, ship_first, ship_company, ship_address1, ship_address2, ship_city, ship_state, ship_zip, ship_country, payinfo, paycvv, paydate, invoicing_list, pkgpart, next_bill_date, id, title, countrycode, phonenum, sip_password, pin</i>
+<BR><BR>
+
+<%$req%> Required fields
+<BR><BR>
+
+Field information:
+
+<ul>
+
+ <li><i>agent_custid</i>: This is the reseller's idea of the customer number or identifier. It may be left blank. If specified, it must be unique per-agent.
+
+ <li><i>refnum</i>: Advertising source number - where a customer heard about your service. Configuration -&gt; Miscellaneous -&gt; View/Edit advertising sources. This field has special treatment upon import: If a string is passed instead
+of an integer, the string is searched for and if necessary auto-created in the
+advertising source table.
+
+ <li><i>payinfo</i>: Credit card number, or leave this, <i>paycvv</i> and <i>paydate</i> blank for email/paper invoicing.
+
+ <li><i>paycvv</i>: CVV2 number (three digits on the back of the credit card)
+
+ <li><i>paydate</i>: Credit card expiration date, MM/YYYY or MM/YY (M/YY and M/YYYY are also accepted).
+
+ <li><i>invoicing_list</i>: Email address for invoices, or POST for postal invoices.
+
+ <li><i>pkgpart</i>: Package definition. Configuration -&gt; Provisioning, services and packages -&gt; View/Edit package definitions
+
+ <li><i>username</i> and <i>_password</i> are required if <i>pkgpart</i> is specified. (Extended and Extended plus company formats)
+
+ <li><i>id</i>: External service id, integer
+
+ <li><i>title</i>: External service identifier, text
+
+</ul>
+
+<BR>
+
+<% include('/elements/footer.html') %>
+
+<%once>
+
+my $req = qq!<font color="#ff0000">*</font>!;
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $custbatch = time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+</%init>
diff --git a/httemplate/misc/cust_main-import_charges.cgi b/httemplate/misc/cust_main-import_charges.cgi
new file mode 100644
index 000000000..3801929e8
--- /dev/null
+++ b/httemplate/misc/cust_main-import_charges.cgi
@@ -0,0 +1,22 @@
+<% include('/elements/header.html', 'Batch Customer Charge') %>
+
+<FORM ACTION="process/cust_main-import_charges.cgi" METHOD="post" ENCTYPE="multipart/form-data">
+
+Import a CSV file containing customer charges.<BR><BR>
+Default file format is CSV, with the following field order: <i>custnum, amount, description</i><BR><BR>
+If <i>amount</i> is negative, a credit will be applied instead.<BR><BR>
+<BR><BR>
+
+CSV Filename: <INPUT TYPE="file" NAME="csvfile"><BR><BR>
+<INPUT TYPE="submit" VALUE="Import">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/cust_main_note-import.cgi b/httemplate/misc/cust_main_note-import.cgi
new file mode 100644
index 000000000..b93c5c1cc
--- /dev/null
+++ b/httemplate/misc/cust_main_note-import.cgi
@@ -0,0 +1,207 @@
+<% include("/elements/header.html", 'Batch Customer Note Import') %>
+%
+
+<FORM ACTION="process/cust_main_note-import.cgi" METHOD="POST">
+
+
+<SCRIPT TYPE="text/javascript">
+
+ function clearhint_custnum() {
+
+ if ( this.value == 'Not found' ) {
+ this.value = '';
+ this.style.color = '#000000';
+ }
+
+ }
+
+ function search_custnum() {
+
+ this.style.color = '#000000'
+
+ var custnum_obj = this;
+ var searchrow = this.getAttribute('rownum');
+ var custnum = this.value;
+ var name_obj = document.getElementById('name'+searchrow);
+
+ if ( custnum == 'searching...' || custnum == 'Not found' )
+ return;
+
+ var customer_select = document.getElementById('cust_select'+searchrow);
+
+ if ( custnum == '' ) {
+ customer_select.selectedIndex = 0;
+ return;
+ }
+
+ custnum_obj.value = 'searching...';
+ custnum_obj.disabled = true;
+ custnum_obj.style.backgroundColor = '#dddddd';
+
+
+ //alert('search for custnum ' + custnum + ', row#' + searchrow );
+
+ function search_custnum_update(name) {
+
+ var name = eval('(' + name + ')' );
+
+ custnum_obj.disabled = false;
+ custnum_obj.style.backgroundColor = '#ffffff';
+
+ if ( name.length > 0 ) {
+ //alert('custnum found: ' + name);
+ opt(customer_select,custnum,name,'#000000');
+ customer_select.selectedIndex = customer_select.length - 1;
+ custnum_obj.value = custnum;
+ name_obj.value = name;
+ } else {
+ custnum_obj.value = 'Not found';
+ custnum_obj.style.color = '#ff0000';
+ }
+
+ }
+
+ custnum_search( custnum, search_custnum_update );
+
+ }
+
+ function select_customer() {
+
+ var custnum = this.options[this.selectedIndex].value;
+ var name = this.options[this.selectedIndex].text;
+
+ var searchrow = this.getAttribute('rownum');
+ var custnum_obj = document.getElementById('custnum'+searchrow);
+ var name_obj = document.getElementById('name'+searchrow);
+
+ custnum_obj.value = custnum;
+ custnum_obj.style.color = '#000000';
+
+ name_obj.value = name;
+
+ }
+
+ function opt(what,value,text,color) {
+ var optionName = new Option(text, value, false, false);
+ optionName.style.color = color;
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+ function previewChanged(what) {
+ var submit_obj = document.getElementById('importsubmit');
+ if (what.checked) {
+ submit_obj.value = 'Preview note import';
+ }else{
+ submit_obj.value = 'Import notes';
+ }
+ }
+
+</SCRIPT>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi',
+ 'subs' => [qw( custnum_search )],
+ )
+%>
+
+% my $fh = $cgi->upload('csvfile');
+% my $csv = new Text::CSV_XS;
+% my $skip_fuzzies = $cgi->param('fuzzies') ? 0 : 1;
+%
+% if ( defined($fh) ) {
+ <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+ <TR>
+ <TH>Cust #</TH>
+ <TH>Customer</TH>
+ <TH>Last</TH>
+ <TH>First</TH>
+ <TH>Note to be added</TH>
+ </TR>
+% my $agentnum => scalar($cgi->param('agentnum')),
+% my $line;
+% my $row = 0;
+% while ( defined($line=<$fh>) ) {
+% $line =~ s/(\S*)\s*$/$1/;
+% $line =~ s/^(.*)(#!).*/$1/;
+%
+% $csv->parse($line) or die "can't parse line: " . $csv->error_input();
+% my $custnum = 0;
+% my @values = $csv->fields();
+% my $last = shift @values;
+% if ($last =~ /^\s*(\d+)\s*$/ ) {
+% $custnum = $1;
+% $last = shift @values;
+% }
+% my $first = shift @values;
+% my $note = join ' ', @values;
+% next unless ( $last || $first || $note );
+% my @cust_main = ();
+% warn "searching for: $last, $first" if ($first || $last);
+% if ($custnum) {
+% @cust_main = qsearch('cust_main', { 'custnum' => $custnum });
+% } else {
+% @cust_main = FS::cust_main::smart_search(
+% 'search' => "$last, $first",
+% 'no_fuzzy_on_exact' => $skip_fuzzies,
+% )
+% if ($first || $last);
+% }
+%
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="custnum<% $row %>" ID="custnum<% $row %>" SIZE=8 MAXLENGTH=12 VALUE="<% $cust_main[0] ? $cust_main[0]->custnum : '' %>" rownum="<% $row %>">
+ <SCRIPT TYPE="text/javascript">
+ var custnum_input<% $row %> = document.getElementById("custnum<% $row %>");
+ custnum_input<% $row %>.onfocus = clearhint_custnum;
+ custnum_input<% $row %>.onchange = search_custnum;
+ </SCRIPT>
+ </TD>
+ <TD>
+ <SELECT NAME="cust_select<% $row %>" ID="cust_select<% $row %>" rownum="<% $row %>">
+ <OPTION VALUE="">---</OPTION>
+% my $i=0;
+% foreach (@cust_main) {
+ <OPTION <% $i ? '' : 'SELECTED' %> VALUE="<% $_->custnum %>"><% $_->name %></OPTION>
+% $i++;
+% }
+ </SELECT>
+ <SCRIPT TYPE="text/javascript">
+ var customer_select<% $row %> = document.getElementById("cust_select<% $row %>");
+ customer_select<% $row %>.onchange = select_customer;
+ </SCRIPT>
+ <INPUT TYPE="hidden" NAME="name<% $row %>" ID="name<% $row %>" VALUE="<% $i ? $cust_main[0]->name : '' %>">
+ </TD>
+ <TD>
+ <% $first %>
+ <INPUT TYPE="hidden" NAME="first<% $row %>" VALUE="<% $first %>">
+ </TD>
+ <TD>
+ <% $last %>
+ <INPUT TYPE="hidden" NAME="last<% $row %>" VALUE="<% $last %>">
+ </TD>
+ <TD>
+ <% $note %>
+ <INPUT TYPE="hidden" NAME="note<% $row %>" VALUE="<% $note %>">
+ </TD>
+ </TR>
+% $row++;
+% }
+ </TABLE>
+ <INPUT TYPE="submit" NAME="submit" ID="importsubmit" VALUE="Import notes">
+ <INPUT TYPE="checkbox" NAME="preview" onchange="previewChanged(this);">
+ Preview mode
+% } else {
+ No file supplied
+% }
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/cust_main_note-import.html b/httemplate/misc/cust_main_note-import.html
new file mode 100644
index 000000000..d8fefa732
--- /dev/null
+++ b/httemplate/misc/cust_main_note-import.html
@@ -0,0 +1,39 @@
+<% include("/elements/header.html",'Batch Customer Note Import') %>
+
+<FORM ACTION="cust_main_note-import.cgi" METHOD="post" ENCTYPE="multipart/form-data">
+
+Import a CSV file containing customer notes records.
+<BR><BR>
+
+File format is CSV, with the following field order: <i>[custnum,] last, first, notefield1, notefield2, notefield3...</i>
+<BR>
+The optional custnum field is identified by being numeric.
+Anything after the character sequence #! is ignored.
+<BR><BR>
+
+<% &ntable("#cccccc") %>
+
+<TR>
+ <TH ALIGN="right">CSV filename</TH>
+ <TD><INPUT TYPE="file" NAME="csvfile"></TD>
+</TR>
+<TR>
+ <TH ALIGN="right">Include additional possibilites when exact match is found</TH>
+ <TD><INPUT TYPE="checkbox" NAME="fuzzies"></TD>
+</TR>
+
+</TABLE>
+<BR><BR>
+
+<INPUT TYPE="submit" VALUE="Load and match">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
+
diff --git a/httemplate/misc/cust_pay-import.cgi b/httemplate/misc/cust_pay-import.cgi
new file mode 100644
index 000000000..849a25bea
--- /dev/null
+++ b/httemplate/misc/cust_pay-import.cgi
@@ -0,0 +1,62 @@
+<% include("/elements/header.html",'Batch Payment Import') %>
+
+Import a CSV file containing customer payments.
+<BR><BR>
+
+<FORM ACTION="process/cust_pay-import.cgi" METHOD="post" ENCTYPE="multipart/form-data">
+
+<% &ntable("#cccccc", 2) %>
+
+<% include('/elements/tr-select-agent.html',
+ #'curr_value' => '', #$agentnum,
+ 'label' => "<B>Agent</B>",
+ 'empty_label' => 'Select agent',
+ )
+%>
+
+<TR>
+ <TH ALIGN="right">Format</TH>
+ <TD>
+ <SELECT NAME="format">
+ <OPTION VALUE="simple">Simple
+<!-- <OPTION VALUE="extended" SELECTED>Extended -->
+ </SELECT>
+ </TD>
+</TR>
+
+<TR>
+ <TH ALIGN="right">CSV filename</TH>
+ <TD><INPUT TYPE="file" NAME="csvfile"></TD>
+</TR>
+
+<TR><TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px"><INPUT TYPE="submit" VALUE="Import CSV file"></TD></TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+
+Simple file format is CSV, with the following field order: <i>custnum, agent_custid, amount, checknum</i>
+<BR><BR>
+
+<!-- Extended file format is not yet defined</i>
+<BR><BR> -->
+
+Field information:
+
+<ul>
+
+ <li><i>custnum</i>: This is the freeside customer number. It may be left blank. If specified, agent_custid must be blank.
+
+ <li><i>agent_custid</i>: This is the reseller's idea of the customer number or identifier. It may be left blank. If specified, custnum must be blank.
+
+ <li><i>amount</i>: A positive numeric value with at most two digits after the decimal point.
+
+ <li><i>checknum</i>: A sequences of digits. May be left blank.
+
+</ul>
+
+<BR>
+
+<% include('/elements/footer.html') %>
diff --git a/httemplate/misc/delay_susp_pkg.html b/httemplate/misc/delay_susp_pkg.html
new file mode 100755
index 000000000..1158a35c2
--- /dev/null
+++ b/httemplate/misc/delay_susp_pkg.html
@@ -0,0 +1,70 @@
+%# if ( $link eq 'popup' ) {
+ <% include('/elements/header-popup.html', $title ) %>
+%# } else {
+%# <% include("/elements/header.html", $title, '') %>
+%# }
+
+<% include('/elements/init_calendar.html') %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="ds_popup" ACTION="<% popurl(1) %>process/delay_susp_pkg.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+<BR><BR>
+<% "Delay automatic suspension of $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD>Delay until</TD>
+ <TD><INPUT TYPE="text" NAME="date" ID="dun_date" VALUE="<% $date |h %>">
+ <IMG SRC="<% $p %>images/calendar.png" ID="dun_button" STYLE="cursor:pointer" TITLE="Select date">
+ <BR><I>m/d/y</I>
+ </TD>
+</TR>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "dun_date",
+ ifFormat: "%m/%d/%Y",
+ button: "dun_button",
+ align: "BR"
+ });
+</SCRIPT>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="<% $submit %>">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $date = time2str("%m/%d/%Y", time);
+
+my($pkgnum);
+if ( $cgi->param('error') ) {
+ $pkgnum = $cgi->param('pkgnum');
+ $date = $cgi->param('date');
+} elsif ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
+ $pkgnum = $1;
+} else {
+ die "illegal query ". $cgi->keywords;
+}
+
+my $submit = 'Delay Suspension';
+my $right = 'Delay suspension events';
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right($right);
+
+my $title = 'Delay Suspension of Package';
+
+my $cust_pkg = qsearchs('cust_pkg', {'pkgnum' => $pkgnum})
+ or die "Unknown pkgnum: $pkgnum";
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+</%init>
diff --git a/httemplate/misc/delete-agent_payment_gateway.cgi b/httemplate/misc/delete-agent_payment_gateway.cgi
new file mode 100644
index 000000000..20a202e0e
--- /dev/null
+++ b/httemplate/misc/delete-agent_payment_gateway.cgi
@@ -0,0 +1,15 @@
+% die "you don't have the 'Configuration' access right"
+% unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+%
+% my($query) = $cgi->keywords;
+% $query =~ /^(\d+)$/ || die "Illegal agentgatewaynum";
+% my $agentgatewaynum = $1;
+%
+% my $agent_payment_gateway = qsearchs('agent_payment_gateway', {
+% 'agentgatewaynum' => $agentgatewaynum,
+% });
+%
+% my $error = $agent_payment_gateway->delete;
+% errorpage($error) if $error;
+%
+% print $cgi->redirect($p. "browse/agent.cgi");
diff --git a/httemplate/misc/delete-cust_credit.cgi b/httemplate/misc/delete-cust_credit.cgi
new file mode 100755
index 000000000..03eb47299
--- /dev/null
+++ b/httemplate/misc/delete-cust_credit.cgi
@@ -0,0 +1,21 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete credit');
+
+#untaint crednum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal crednum";
+my $crednum = $1;
+
+my $cust_credit = qsearchs('cust_credit',{'crednum'=>$crednum});
+my $custnum = $cust_credit->custnum;
+
+my $error = $cust_credit->delete;
+
+</%init>
diff --git a/httemplate/misc/delete-cust_pay.cgi b/httemplate/misc/delete-cust_pay.cgi
new file mode 100755
index 000000000..38e7e4ba1
--- /dev/null
+++ b/httemplate/misc/delete-cust_pay.cgi
@@ -0,0 +1,21 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete payment');
+
+#untaint paynum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal paynum";
+my $paynum = $1;
+
+my $cust_pay = qsearchs('cust_pay',{'paynum'=>$paynum});
+my $custnum = $cust_pay->custnum;
+
+my $error = $cust_pay->delete;
+
+</%init>
diff --git a/httemplate/misc/delete-cust_refund.cgi b/httemplate/misc/delete-cust_refund.cgi
new file mode 100755
index 000000000..983a79da5
--- /dev/null
+++ b/httemplate/misc/delete-cust_refund.cgi
@@ -0,0 +1,21 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete refund');
+
+#untaint refundnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal refundnum";
+my $refundnum = $1;
+
+my $cust_refund = qsearchs('cust_refund',{'refundnum'=>$refundnum});
+my $custnum = $cust_refund->custnum;
+
+my $error = $cust_refund->delete;
+
+</%init>
diff --git a/httemplate/misc/delete-customer.cgi b/httemplate/misc/delete-customer.cgi
new file mode 100755
index 000000000..203ed36a5
--- /dev/null
+++ b/httemplate/misc/delete-customer.cgi
@@ -0,0 +1,64 @@
+<% include('/elements/header.html', 'Delete customer') %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/delete-customer.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum |h %>">
+
+%if ( qsearch('cust_pkg', { 'custnum' => $custnum, 'cancel' => '' } ) ) {
+ Move uncancelled packages to customer number
+ <INPUT TYPE="text" NAME="new_custnum" VALUE="<% $new_custnum |h %>"><BR><BR>
+%}
+
+This will <B>completely remove</B> all traces of this customer record. This
+is <B>not</B> what you want if this is a real customer who has simply
+canceled service with you. For that, cancel all of the customer's packages.
+(you can optionally hide cancelled customers with the <A HREF="../config/config-view.cgi#hidecancelledcustomers">hidecancelledcustomers</A> configuration option)
+<BR>
+<BR>Are you <B>absolutely sure</B> you want to delete this customer?
+<BR><INPUT TYPE="submit" VALUE="Yes">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+%#Deleting a customer you have financial records on (i.e. credits) is
+%#typically considered fraudulant bookkeeping. Remember, deleting
+%#customers should ONLY be used for completely bogus records. You should
+%#NOT delete real customers who simply discontinue service.
+%#
+%#For real customers who simply discontinue service, cancel all of the
+%#customer's packages. Customers with all cancelled packages are not
+%#billed. There is no need to take further action to prevent billing on
+%#customers with all cancelled packages.
+%#
+%#Also see the "hidecancelledcustomers" and "hidecancelledpackages"
+%#configuration options, which will allow you to surpress the display of
+%#cancelled customers and packages, respectively.
+
+<%init>
+
+my $conf = new FS::Conf;
+die "Customer deletions not enabled in configuration"
+ unless $conf->exists('deletecustomers');
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete customer');
+
+my($custnum, $new_custnum);
+if ( $cgi->param('error') ) {
+ $custnum = $cgi->param('custnum');
+ $new_custnum = $cgi->param('new_custnum');
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "Illegal query: $query";
+ $custnum = $1;
+ $new_custnum = '';
+}
+my $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+} )
+ or die 'Unknown custnum';
+
+</%init>
diff --git a/httemplate/misc/delete-domain_record.cgi b/httemplate/misc/delete-domain_record.cgi
new file mode 100755
index 000000000..08eedde5f
--- /dev/null
+++ b/httemplate/misc/delete-domain_record.cgi
@@ -0,0 +1,20 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/svc_domain.cgi?". $domain_record->svcnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice');
+
+#untaint recnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal recnum";
+my $recnum = $1;
+
+my $domain_record = qsearchs('domain_record',{'recnum'=>$recnum});
+
+my $error = $domain_record->delete;
+
+</%init>
diff --git a/httemplate/misc/delete-part_export.cgi b/httemplate/misc/delete-part_export.cgi
new file mode 100755
index 000000000..52404e0c4
--- /dev/null
+++ b/httemplate/misc/delete-part_export.cgi
@@ -0,0 +1,20 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "browse/part_export.cgi") %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#untaint exportnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal exportnum";
+my $exportnum = $1;
+
+my $part_export = qsearchs('part_export',{'exportnum'=>$exportnum});
+
+my $error = $part_export->delete;
+
+</%init>
diff --git a/httemplate/misc/disable-payment_gateway.cgi b/httemplate/misc/disable-payment_gateway.cgi
new file mode 100644
index 000000000..13e1f92bc
--- /dev/null
+++ b/httemplate/misc/disable-payment_gateway.cgi
@@ -0,0 +1,25 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+%#<% $cgi->redirect(popurl(2). "browse/payment_gateway.html?showdiabled=$showdisabled") %>
+<% $cgi->redirect(popurl(2). "browse/payment_gateway.html") %>
+%}
+<%init>
+
+die "access deined"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#my $showdisabled = 0;
+#$cgi->param('showdisabled') =~ /^(\d+)$/ and $showdisabled = $1;
+
+#$cgi->param('gatewaynum') =~ /^(\d+)$/ or die 'illegal gatewaynum';
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ or die 'illegal gatewaynum';
+my $gatewaynum = $1;
+
+my $payment_gateway =
+ qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } );
+
+my $error = $payment_gateway->disable;
+
+</%init>
diff --git a/httemplate/misc/download-batch.cgi b/httemplate/misc/download-batch.cgi
new file mode 100644
index 000000000..57905daf9
--- /dev/null
+++ b/httemplate/misc/download-batch.cgi
@@ -0,0 +1,213 @@
+%if ($format eq "BoM") {
+%
+% my($origid,$datacenter,$typecode,$shortname,$longname,$mybank,$myacct) =
+% $conf->config("batchconfig-$format");
+%
+<% sprintf( "A%10s%04u%06u%05u%54s\n",$origid,$pay_batch->batchnum,$jdate,$datacenter,"").
+ sprintf( "XD%03u%06u%-15s%-30s%09u%-12s \n",$typecode,$jdate,$shortname,$longname,$mybank,$myacct )
+ %>
+%
+%}elsif ($format eq "PAP"){
+%
+% my($origid,$datacenter,$typecode,$shortname,$longname,$mybank,$myacct) =
+% $conf->config("batchconfig-$format");
+%
+<% sprintf( "H%10sD%3s%06u%-15s%09u%-12s%04u%19s\n",$origid,$typecode,$cdate,$shortname,$mybank,$myacct,$pay_batch->batchnum,"") %>
+%
+%
+%}elsif ($format eq "csv-td_canada_trust-merchant_pc_batch"){
+%# 1;
+%}elsif ($format eq "csv-chase_canada-E-xactBatch"){
+%
+% my($origid) = $conf->config("batchconfig-$format");
+<% sprintf( '$$E-xactBatchFileV1.0$$%s:%03u$$%s',$sdate,$pay_batch->batchnum, $origid)
+ %>
+%
+%}elsif ($format eq "ach-spiritone"){
+%# 1;
+%}else{
+% die "Unknown format for batch in batchconfig. \n";
+%}
+%
+%
+%for my $cust_pay_batch ( sort { $a->paybatchnum <=> $b->paybatchnum }
+% qsearch('cust_pay_batch',
+% {'batchnum'=>$pay_batch->batchnum} )
+%) {
+%
+% $cust_pay_batch->exp =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+% my( $mon, $y ) = ( $2, $1 );
+% if ( $conf->exists('batch-increment_expiration') ) {
+% my( $curmon, $curyear ) = (localtime(time))[4,5];
+% $curmon++; $curyear-=100;
+% $y++ while $y < $curyear || ( $y == $curyear && $mon < $curmon );
+% }
+% $mon = "0$mon" if $mon =~ /^\d$/;
+% $y = "0$y" if $y =~ /^\d$/;
+% my $exp = "$mon$y";
+%
+% if ( $first_download ) {
+% my $balance = $cust_pay_batch->cust_main->balance;
+% if ( $balance <= 0 ) {
+% my $error = $cust_pay_batch->delete;
+% if ( $error ) {
+% $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+% die $error;
+% }
+% next;
+% } elsif ( $balance < $cust_pay_batch->amount ) {
+% $cust_pay_batch->amount($balance);
+% my $error = $cust_pay_batch->replace;
+% if ( $error ) {
+% $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+% die $error;
+% }
+% #} elsif ( $balance > $cust_pay_batch->amount ) {
+% }
+% }
+%
+% $batchcount++;
+% $batchtotal += $cust_pay_batch->amount;
+%
+% if ($format eq "BoM") {
+%
+% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
+%
+<% sprintf( "D%010.0f%09u%-12s%-29s%-19s\n",$cust_pay_batch->amount*100,$aba,$account,$cust_pay_batch->payname,$cust_pay_batch->paybatchnum) %>
+%
+%
+% } elsif ($format eq "PAP"){
+%
+% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
+%
+<% sprintf( "D%-23s%06u%-19s%09u%-12s%010.0f\n",$cust_pay_batch->payname,$cdate,$cust_pay_batch->paybatchnum,$aba,$account,$cust_pay_batch->amount*100) %>
+%
+%
+% } elsif ($format eq "csv-td_canada_trust-merchant_pc_batch") {
+%
+%
+,,,,<% $cust_pay_batch->payinfo %>,<% $exp %>,<% $cust_pay_batch->amount %>,<% $cust_pay_batch->paybatchnum %>
+%
+%
+% } elsif ($format eq "csv-chase_canada-E-xactBatch"){
+%
+% my $payname=$cust_pay_batch->payname; $payname =~ tr/",/ /; #payinfo too? :P
+<% $cust_pay_batch->paybatchnum %>,<% $cust_pay_batch->custnum %>,<% $cust_pay_batch->invnum %>,"<% $payname %>",00,<% $cust_pay_batch->payinfo %>,<% $cust_pay_batch->amount %>,<% $exp %>,,
+%
+%
+% }elsif ($format eq "ach-spiritone"){
+%
+% my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo );
+% my $payname=$cust_pay_batch->first. " ". $cust_pay_batch->last;
+% $payname =~ tr/",/ /; #payinfo too?
+% my $batchline = qq!"$payname","!.$cust_pay_batch->paybatchnum.
+% qq!","$aba","$account","27","!.$cust_pay_batch->amount.
+% qq!","27","0.00"!;
+% push @batchlines, $batchline;
+<% $batchline %>
+%
+% } else {
+% die "I'm already dead, but you did not know that.\n";
+% }
+%
+%}
+%
+%if ($format eq "BoM") {
+%
+%
+<% sprintf( "YD%08u%014.0f%56s\n",$batchcount,$batchtotal*100,"" ).
+ sprintf( "Z%014u%05u%014u%05u%41s\n",$batchtotal*100,$batchcount,"0","0","" ) %>
+%
+%
+%} elsif ($format eq "PAP"){
+%
+%
+<% sprintf( "T%08u%014.0f%57s\n",$batchcount,$batchtotal*100,"" ) %>
+%
+%
+%} elsif ($format eq "csv-td_canada_trust-merchant_pc_batch"){
+% #1;
+%} elsif ($format eq "csv-chase_canada-E-xactBatch"){
+% #1;
+%} elsif ($format eq "ach-spiritone"){
+% #1;
+%} else {
+% die "I'm already dead (again), but you did not know that.\n";
+%}
+%
+<%init>
+
+my $conf=new FS::Conf;
+
+#http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+http_header('Content-Type' => 'text/plain' );
+
+my $batchnum;
+if ( $cgi->param('batchnum') =~ /^(\d+)$/ ) {
+ $batchnum = $1;
+} else {
+ die "No batch number (bad URL) \n";
+}
+
+my $format;
+if ( $cgi->param('format') =~ /^([\w\- ]+)$/ ) {
+ $format = $1;
+} else {
+ $format = $conf->config('batch-default_format');
+}
+
+my $autopost;
+if ( $format eq 'ach-spiritone' ) {
+ $autopost = 1;
+}else{
+ $autopost = 0;
+}
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+my $dbh = dbh;
+
+my $pay_batch = qsearchs('pay_batch', {'batchnum'=>$batchnum, 'status'=>'O'} );
+my $first_download = 1;
+unless ($pay_batch) {
+ $pay_batch = qsearchs('pay_batch', {'batchnum'=>$batchnum, 'status'=>'I'} )
+ if $FS::CurrentUser::CurrentUser->access_right('Reprocess batches');
+ $first_download = 0;
+}
+die "No pending batch. \n" unless $pay_batch;
+
+my $error = $pay_batch->set_status('I');
+die "error updating batch status: $error\n" if $error;
+
+my $batchtotal=0;
+my $batchcount=0;
+
+my (@date)=localtime($pay_batch->download);
+my $jdate = sprintf("%03d", $date[5] % 100).sprintf("%03d", $date[7] + 1);
+my $cdate = sprintf("%02d", $date[3]).sprintf("%02d", $date[4] + 1).
+ sprintf("%02d", $date[5] % 100);
+my $sdate = sprintf("%02d", $date[5] % 100).'/'.sprintf("%02d", $date[4] + 1).
+ '/'.sprintf("%02d", $date[3]);
+
+my @batchlines = ();
+</%init>
+<%cleanup>
+if ($autopost) {
+ my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
+ my $fh = new File::Temp(
+ TEMPLATE => 'paybatch.'. $batchnum .'.XXXXXXXX',
+ DIR => $dir,
+ ) or die "can't open temp file: $!\n";
+
+ print $fh map{ "$_\n" } @batchlines;
+ seek $fh, 0, 0;
+
+ $error = $pay_batch->import_results( 'filehandle' => $fh,
+ 'format' => $format,
+ );
+ die $error if $error;
+}
+
+$dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+</%cleanup>
diff --git a/httemplate/misc/dump.cgi b/httemplate/misc/dump.cgi
new file mode 100644
index 000000000..3b60b20ef
--- /dev/null
+++ b/httemplate/misc/dump.cgi
@@ -0,0 +1,20 @@
+% die "access denied"
+% unless $FS::CurrentUser::CurrentUser->access_right('Export');
+%
+% if ( driver_name =~ /^Pg$/ ) {
+% my $dbname = (split(':', datasrc))[2];
+% if ( $dbname =~ /[;=]/ ) {
+% my %elements = map { /^(\w+)=(.*)$/; $1=>$2 } split(';', $dbname);
+% $dbname = $elements{'dbname'};
+% }
+% open(DUMP,"pg_dump $dbname |");
+% } else {
+% errorpage("don't (yet) know how to dump ". driver_name. " databases");
+% }
+%
+% http_header('Content-Type' => 'text/plain' );
+%
+% while (<DUMP>) {
+% print $_;
+% }
+% close DUMP;
diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html
new file mode 100644
index 000000000..0d3d622c3
--- /dev/null
+++ b/httemplate/misc/email-customers.html
@@ -0,0 +1,145 @@
+<% include('/elements/header.html', $title) %>
+
+<FORM NAME="OneTrueForm" ACTION="email-customers.html" METHOD="POST">
+% foreach my $key ( keys %search ) {
+% my @values = ref($search{$key}) ? @{$search{$key}} : ( $search{$key} );
+% foreach my $value ( @values ) {
+ <INPUT TYPE="hidden" NAME="<% $key |h %>" VALUE="<% $value |h %>">
+% }
+% }
+
+% if ( $cgi->param('magic') eq 'send' ) {
+
+ <FONT SIZE="+2">Sending notice</FONT>
+
+ <% include('/elements/progress-init.html',
+ 'OneTrueForm',
+ [ keys(%search), qw( from subject html_body text_body ) ],
+ 'process/email-customers.html',
+ { 'message' => "Notice sent" }, #would be nice to show #, but..
+ )
+ %>
+
+% } elsif ( $cgi->param('magic') eq 'preview' ) {
+
+ <FONT SIZE="+2">Preview notice</FONT>
+
+% }
+
+% if ( $cgi->param('magic') ) {
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <% include('/elements/tr-fixed.html',
+ 'field' => 'from',
+ 'label' => 'From:',
+ 'value' => scalar( $cgi->param('from') ),
+ )
+ %>
+
+ <% include('/elements/tr-fixed.html',
+ 'field' => 'subject',
+ 'label' => 'Subject:',
+ 'value' => scalar( $cgi->param('subject') ),
+ )
+ %>
+
+ <INPUT TYPE="hidden" NAME="html_body" VALUE="<% $cgi->param('html_body') |h %>">
+ <TR>
+ <TD ALIGN="right" VALIGN="top">Message (HTML display): </TD>
+ <TD BGCOLOR="#e8e8e8" ALIGN="left"><% $cgi->param('html_body') %></TD>
+ </TR>
+
+% my $text_body = HTML::FormatText->new(leftmargin=>0)->format(
+% HTML::TreeBuilder->new_from_content(
+% $cgi->param('html_body')
+% )
+% );
+ <INPUT TYPE="hidden" NAME="text_body" VALUE="<% $text_body |h %>">
+ <TR>
+ <TD ALIGN="right" VALIGN="top">Message (Text display): </TD>
+ <TD BGCOLOR="#e8e8e8" ALIGN="left"><PRE><% $text_body %></PRE></TD>
+ </TR>
+
+ </TABLE>
+
+% if ( $cgi->param('magic') eq 'preview' ) {
+
+ <SCRIPT>
+ function areyousure(href) {
+ return confirm("Send this notice to <% $num_cust %> customers?");
+ }
+ </SCRIPT>
+
+ <BR>
+ <INPUT TYPE="hidden" NAME="magic" VALUE="send">
+ <INPUT TYPE="submit" VALUE="Send notice" onClick="return areyousure()">
+
+% }
+
+% } else {
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0 WIDTH="100%">
+
+ <% include('/elements/tr-input-text.html',
+ 'field' => 'from',
+ 'label' => 'From:',
+ )
+ %>
+
+ <% include('/elements/tr-input-text.html',
+ 'field' => 'subject',
+ 'label' => 'Subject:',
+ )
+ %>
+
+ <TR>
+ <TD ALIGN="right" VALIGN="top">Message: </TD>
+ <TD><% include('/elements/htmlarea.html', 'field'=>'html_body') %></TD>
+ </TR>
+
+ </TABLE>
+
+%#Substitution vars:
+
+ <BR><BR>
+ <INPUT TYPE="hidden" NAME="magic" VALUE="preview">
+ <INPUT TYPE="submit" VALUE="Preview notice">
+
+% }
+
+</FORM>
+
+% if ( $cgi->param('magic') eq 'send' ) {
+ <SCRIPT TYPE="text/javascript">
+ process();
+ </SCRIPT>
+% }
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices');
+
+my %search = $cgi->Vars;
+delete $search{$_} for qw( magic from subject html_body text_body );
+$search{$_} = [ split(/\0/, $search{$_}) ]
+ foreach grep $search{$_} =~ /\0/, keys %search;
+
+my $title = 'Bulk send customer notices';
+
+my $num_cust;
+if ( $cgi->param('magic') eq 'preview' ) {
+ my $sql_query = FS::cust_main->search_sql(\%search);
+ my $count_query = delete($sql_query->{'count_query'});
+ my $count_sth = dbh->prepare($count_query)
+ or die "Error preparing $count_query: ". dbh->errstr;
+ $count_sth->execute
+ or die "Error executing $count_query: ". $count_sth->errstr;
+ my $count_arrayref = $count_sth->fetchrow_arrayref;
+ $num_cust = $count_arrayref->[0];
+}
+
+</%init>
diff --git a/httemplate/misc/email-invoice.cgi b/httemplate/misc/email-invoice.cgi
new file mode 100755
index 000000000..269722f67
--- /dev/null
+++ b/httemplate/misc/email-invoice.cgi
@@ -0,0 +1,19 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $template = $2;
+my $invnum = $3;
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+die "Can't find invoice!\n" unless $cust_bill;
+
+$cust_bill->email($template);
+
+my $custnum = $cust_bill->getfield('custnum');
+
+</%init>
diff --git a/httemplate/misc/email_events.cgi b/httemplate/misc/email_events.cgi
new file mode 100644
index 000000000..e7a0e77f8
--- /dev/null
+++ b/httemplate/misc/email_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_event::process_reemail', $cgi;
+
+</%init>
diff --git a/httemplate/misc/email_invoice_events.cgi b/httemplate/misc/email_invoice_events.cgi
new file mode 100644
index 000000000..d65fe172b
--- /dev/null
+++ b/httemplate/misc/email_invoice_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reemail', $cgi;
+
+</%init>
diff --git a/httemplate/misc/email_invoices.cgi b/httemplate/misc/email_invoices.cgi
new file mode 100644
index 000000000..78ca0f67d
--- /dev/null
+++ b/httemplate/misc/email_invoices.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reemail', $cgi;
+
+</%init>
diff --git a/httemplate/misc/enable_or_disable_tax.html b/httemplate/misc/enable_or_disable_tax.html
new file mode 100755
index 000000000..0efd07d19
--- /dev/null
+++ b/httemplate/misc/enable_or_disable_tax.html
@@ -0,0 +1,37 @@
+<% include('/elements/header-popup.html', ucfirst($action). ' Tax Rates') %>
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% popurl(1) %>process/enable_or_disable_tax.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="action" VALUE="<% $action %>">
+<INPUT TYPE="hidden" NAME="data_vendor" VALUE="<% $cgi->param('data_vendor') %>">
+<INPUT TYPE="hidden" NAME="geocode" VALUE="<% $cgi->param('geocode') %>">
+<INPUT TYPE="hidden" NAME="taxclassnum" VALUE="<% $cgi->param('taxclassnum') %>">
+<INPUT TYPE="hidden" NAME="tax_type" VALUE="<% $cgi->param('tax_type') %>">
+<INPUT TYPE="hidden" NAME="tax_cat" VALUE="<% $cgi->param('tax_cat') %>">
+<INPUT TYPE="hidden" NAME="showdisabled" VALUE="<% $cgi->param('showdisabled') |h %>">
+
+This will <B><% $action %></B> <% $count %> tax
+<% $count == 1 ? 'rate' : 'rates' %>. Are you <B>certain</B> you want to do
+this?
+<BR><BR><INPUT TYPE="submit" VALUE="Yes">
+</FORM>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $action = '';
+if ( $cgi->param('action') =~ /^(\w+)$/ ) {
+ $action = $1;
+}
+
+my ($query, $count_query) = FS::tax_rate::browse_queries(scalar($cgi->Vars));
+
+my $count_sth = dbh->prepare($count_query)
+ or die "Error preparing $count_query: ". dbh->errstr;
+$count_sth->execute
+ or die "Error executing $count_query: ". $count_sth->errstr;
+my $count = $count_sth->fetchrow_arrayref->[0];
+
+</%init>
diff --git a/httemplate/misc/exchanges.cgi b/httemplate/misc/exchanges.cgi
new file mode 100644
index 000000000..f5860cff2
--- /dev/null
+++ b/httemplate/misc/exchanges.cgi
@@ -0,0 +1,24 @@
+%# [ <% join(', ', map { qq("$_") } @exchanges) %> ]
+<% objToJson(\@exchanges) %>
+<%init>
+
+my( $areacode, $svcpart ) = $cgi->param('arg');
+
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @exports = $part_svc->part_export_did;
+if ( scalar(@exports) > 1 ) {
+ die "more than one DID-providing export attached to svcpart $svcpart";
+} elsif ( ! @exports ) {
+ die "no DID providing export attached to svcpart $svcpart";
+}
+my $export = $exports[0];
+
+my $something = $export->get_dids('areacode'=>$areacode);
+
+#warn Dumper($something);
+
+my @exchanges = @{ $something };
+
+</%init>
diff --git a/httemplate/misc/fax-invoice.cgi b/httemplate/misc/fax-invoice.cgi
new file mode 100755
index 000000000..2591fceb8
--- /dev/null
+++ b/httemplate/misc/fax-invoice.cgi
@@ -0,0 +1,19 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $template = $2;
+my $invnum = $3;
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+die "Can't find invoice!\n" unless $cust_bill;
+
+$cust_bill->fax_invoice($template);
+
+my $custnum = $cust_bill->getfield('custnum');
+
+</%init>
diff --git a/httemplate/misc/fax_events.cgi b/httemplate/misc/fax_events.cgi
new file mode 100644
index 000000000..39cba0707
--- /dev/null
+++ b/httemplate/misc/fax_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_event::process_refax', $cgi;
+
+</%init>
diff --git a/httemplate/misc/fax_invoice_events.cgi b/httemplate/misc/fax_invoice_events.cgi
new file mode 100644
index 000000000..05420eeca
--- /dev/null
+++ b/httemplate/misc/fax_invoice_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_refax', $cgi;
+
+</%init>
diff --git a/httemplate/misc/fax_invoices.cgi b/httemplate/misc/fax_invoices.cgi
new file mode 100644
index 000000000..a843523db
--- /dev/null
+++ b/httemplate/misc/fax_invoices.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_refax', $cgi;
+
+</%init>
diff --git a/httemplate/misc/file-upload.html b/httemplate/misc/file-upload.html
new file mode 100644
index 000000000..469274c69
--- /dev/null
+++ b/httemplate/misc/file-upload.html
@@ -0,0 +1,53 @@
+<% include('/elements/header-minimal.html', 'File Upload') %>
+% if ($error) {
+Error: <% $error %>
+% }else{
+File Upload Successful <% join(',', @filenames) %>;
+% }
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import'); #?
+
+my @filenames = ();
+my $error = ''; # could be extended to the access control
+
+$cgi->param('upload_fields') =~ /^([,\w]+)$/
+ or $error = "invalid upload_fields";
+my $fields = $1;
+
+my $dir = $FS::UID::cache_dir. "/cache.". $FS::UID::datasrc;
+
+foreach my $field (split /,/, $fields) {
+ next if $error;
+
+ my $fh = $cgi->upload($field)
+ or $error = "No valid file was provided.";
+
+ my $suffix = '';
+ if ( $cgi->param($field) =~ /(\.\w+)$/i ) {
+ $suffix = lc($1);
+ }
+
+ my $sh = new File::Temp( TEMPLATE => 'upload.XXXXXXXX',
+ SUFFIX => $suffix,
+ DIR => $dir,
+ UNLINK => 0,
+ )
+ or $error ||= "can't open temporary file to store upload: $!\n";
+
+ unless ($error) {
+ while(<$fh>) {
+ print $sh $_;
+ }
+ $sh->filename =~ m!.*/([.\w]+)$!;
+ push @filenames, "$field:$1";
+ close $sh
+ }
+
+}
+
+$error = "No files" unless scalar(@filenames);
+
+</%init>
diff --git a/httemplate/misc/ftp_invoices.cgi b/httemplate/misc/ftp_invoices.cgi
new file mode 100644
index 000000000..9a072b99f
--- /dev/null
+++ b/httemplate/misc/ftp_invoices.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reftp', $cgi;
+
+</%init>
diff --git a/httemplate/misc/inventory_item-import.html b/httemplate/misc/inventory_item-import.html
new file mode 100644
index 000000000..65a123e2a
--- /dev/null
+++ b/httemplate/misc/inventory_item-import.html
@@ -0,0 +1,67 @@
+<% include("/elements/header.html", PL($inventory_class->classname)) %>
+
+Import a file containing <% PL($inventory_class->classname) %>, one per line.
+<BR><BR>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'InventoryItemImportForm',
+ 'action' => 'process/inventory_item-import.html',
+ 'num_files' => 1,
+ #'fields' => [ 'format', 'itembatch', 'classnum', ],
+ 'fields' => [ 'format', 'classnum', ],
+ 'message' => 'Inventory import successful',
+ #XXX redirect via $itembatch? or just back to class browse?
+ 'url' => $p."search/inventory_item.html?classnum=$classnum;avail=1",
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <INPUT TYPE="hidden" NAME="format" VALUE="default">
+
+ <INPUT TYPE="hidden" NAME="classnum" VALUE="<% $classnum %>">
+
+%# <INPUT TYPE="hidden" NAME="itembatch" VALUE="<% $itembatch %>">
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => 'Filename',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Import file"
+ onClick = "document.InventoryItemImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+
+Upload file can be a text file or Excel spreadsheet. If an Excel spreadsheet,
+ should have an .XLS extension.
+<BR><BR>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+$cgi->param =~ /^(\d+)$/ or errorpage("illegal classnum");
+my $classnum = $1;
+my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } );
+
+#my $conf = new FS::Conf;
+#my $itembatch =
+# time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+</%init>
diff --git a/httemplate/misc/link.cgi b/httemplate/misc/link.cgi
new file mode 100755
index 000000000..748eaa15f
--- /dev/null
+++ b/httemplate/misc/link.cgi
@@ -0,0 +1,84 @@
+<% include("/elements/header.html","Link to existing $svc") %>
+
+<FORM ACTION="<% popurl(1) %>process/link.cgi" METHOD=POST>
+% if ( $link_field ) {
+
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="">
+ <INPUT TYPE="hidden" NAME="link_field" VALUE="<% $link_field %>">
+ <% $link_field %> of existing service: <INPUT TYPE="text" NAME="link_value">
+ <BR>
+% if ( $link_field2 ) {
+
+ <INPUT TYPE="hidden" NAME="link_field2" VALUE="<% $link_field2->{field} %>">
+ <% $link_field2->{'label'} %> of existing service:
+% if ( $link_field2->{'type'} eq 'select' ) {
+% if ( $link_field2->{'select_table'} ) {
+
+ <SELECT NAME="link_value2">
+ <OPTION> </OPTION>
+% foreach my $r ( qsearch( $link_field2->{'select_table'}, {})) {
+% my $key = $link_field2->{'select_key'};
+% my $label = $link_field2->{'select_label'};
+
+ <OPTION VALUE="<% $r->$key() %>"><% $r->$label() %></OPTION>
+% }
+
+ </SELECT>
+% } else {
+
+ Don't know how to process secondary link field for <% $svcdb %>
+ (type=>select but no select_table)
+% }
+% } else {
+
+ Don't know how to process secondary link field for <% $svcdb %>
+ (unknown type <% $link_field2->{'type'} %>)
+% }
+
+ <BR>
+% }
+% } else {
+
+ Service # of existing service: <INPUT TYPE="text" NAME="svcnum" VALUE="">
+% }
+
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
+<BR><INPUT TYPE="submit" VALUE="Link">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View/link unlinked services');
+
+my %link_field = (
+ 'svc_acct' => 'username',
+ 'svc_domain' => 'domain',
+);
+
+my %link_field2 = (
+ 'svc_acct' => { label => 'Domain',
+ field => 'domsvc',
+ type => 'select',
+ select_table => 'svc_domain',
+ select_key => 'svcnum',
+ select_label => 'domain'
+ },
+);
+
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+my $pkgnum = $1;
+$cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+my $svcpart = $1;
+
+my $part_svc = qsearchs('part_svc',{'svcpart'=>$svcpart});
+my $svc = $part_svc->getfield('svc');
+my $svcdb = $part_svc->getfield('svcdb');
+my $link_field = $link_field{$svcdb};
+my $link_field2 = $link_field2{$svcdb};
+
+</%init>
diff --git a/httemplate/misc/location.cgi b/httemplate/misc/location.cgi
new file mode 100644
index 000000000..419c59f2e
--- /dev/null
+++ b/httemplate/misc/location.cgi
@@ -0,0 +1,19 @@
+<% objToJson(\%hash) %>
+<%init>
+
+my $locationnum = $cgi->param('arg');
+
+my $cust_location = qsearchs({
+ 'select' => 'cust_location.*',
+ 'table' => 'cust_location',
+ 'hashref' => { 'locationnum' => $locationnum },
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+
+my %hash = ();
+%hash = map { $_ => $cust_location->$_() }
+ qw( address1 address2 city county state zip country )
+ if $cust_location;
+
+</%init>
diff --git a/httemplate/misc/meta-import.cgi b/httemplate/misc/meta-import.cgi
new file mode 100644
index 000000000..5b3470c06
--- /dev/null
+++ b/httemplate/misc/meta-import.cgi
@@ -0,0 +1,79 @@
+<% include('/elements/header.html', 'Import') %>
+
+<FORM ACTION="process/meta-import.cgi" METHOD="post" ENCTYPE="multipart/form-data">
+Import data from a DBI data source<BR><BR>
+%
+% #false laziness with edit/cust_main.cgi
+% my @agents = qsearch( 'agent', {} );
+% die "No agents created!" unless @agents;
+% my $agentnum = $agents[0]->agentnum; #default to first
+%
+% if ( scalar(@agents) == 1 ) {
+%
+
+ <INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agentnum %>">
+% } else {
+
+ <BR><BR>Agent <SELECT NAME="agentnum" SIZE="1">
+% foreach my $agent (sort { $a->agent cmp $b->agent } @agents) {
+
+ <OPTION VALUE="<% $agent->agentnum %>" <% " SELECTED"x($agent->agentnum==$agentnum) %>><% $agent->agent %></OPTION>
+% }
+
+ </SELECT><BR><BR>
+% }
+%
+% my @referrals = qsearch('part_referral',{});
+% die "No advertising sources created!" unless @referrals;
+% my $refnum = $referrals[0]->refnum; #default to first
+%
+% if ( scalar(@referrals) == 1 ) {
+%
+
+ <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
+% } else {
+
+ <BR><BR>Advertising source <SELECT NAME="refnum" SIZE="1">
+% foreach my $referral ( sort { $a->referral <=> $b->referral } @referrals) {
+
+ <OPTION VALUE="<% $referral->refnum %>" <% " SELECTED"x($referral->refnum==$refnum) %>><% $referral->refnum %>: <% $referral->referral %></OPTION>
+% }
+
+ </SELECT><BR><BR>
+% }
+
+
+ First package: <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
+% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) {
+
+ <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+% }
+
+</SELECT><BR><BR>
+
+ <table>
+ <tr>
+ <td align="right">DBI data source: </td>
+ <td><INPUT TYPE="text" NAME="data_source"></td>
+ </tr>
+ <tr>
+ <td align="right">DBI username: </td>
+ <td><INPUT TYPE="text" NAME="username"></td>
+ </tr>
+ <tr>
+ <td align="right">DBI password: </td>
+ <td><INPUT TYPE="text" NAME="password"></td>
+ </tr>
+ </table>
+ <INPUT TYPE="submit" VALUE="Import">
+
+ </FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+#there's no ACL for this... haven't used in ages
+die 'meta-import not enabled; remove this if you want to use it';
+
+</%init>
diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html
new file mode 100644
index 000000000..2c8335154
--- /dev/null
+++ b/httemplate/misc/order_pkg.html
@@ -0,0 +1,75 @@
+<% include('/elements/header-popup.html', 'Order new package' ) %>
+
+<SCRIPT TYPE="text/javascript">
+
+ function enable_order_pkg () {
+ if ( document.OrderPkgForm.pkgpart.selectedIndex > 0 ) {
+ document.OrderPkgForm.submit.disabled = false;
+ } else {
+ document.OrderPkgForm.submit.disabled = true;
+ }
+ }
+
+</SCRIPT>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="OrderPkgForm" ACTION="<% $p %>edit/process/quick-cust_pkg.cgi" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $cust_main->custnum %>">
+
+<% ntable("#cccccc", 2) %>
+<TR>
+ <TH ALIGN="right">Package</TH>
+ <TD COLSPAN=7>
+ <% include('/elements/select-cust-part_pkg.html',
+ 'curr_value' => $pkgpart,
+ 'cust_main' => $cust_main,
+ 'onchange' => 'enable_order_pkg',
+ )
+ %>
+ </TD>
+</TR>
+
+% if ( $conf->exists('pkg_referral') ) {
+ <% include('/elements/tr-select-part_referral.html',
+ 'curr_value' => scalar( $cgi->param('refnum') ), #get rid of empty_label first# || $cust_main->refnum,
+ 'disable_empty' => 1,
+ 'multiple' => $conf->exists('pkg_referral-multiple'),
+ 'colspan' => 7,
+ )
+ %>
+% }
+
+<% include('/elements/tr-select-cust_location.html',
+ 'cgi' => $cgi,
+ 'cust_main' => $cust_main,
+ )
+%>
+
+</TABLE>
+
+<BR>
+<INPUT NAME="submit" TYPE="submit" VALUE="Order Package" <% $pkgpart ? '' : 'DISABLED' %>>
+
+</FORM>
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Order customer package');
+
+my $conf = new FS::Conf;
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die "no custnum";
+my $custnum = $1;
+my $cust_main = qsearchs({
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+
+my $pkgpart = scalar($cgi->param('pkgpart'));
+
+</%init>
diff --git a/httemplate/misc/payment.cgi b/httemplate/misc/payment.cgi
new file mode 100644
index 000000000..004700488
--- /dev/null
+++ b/httemplate/misc/payment.cgi
@@ -0,0 +1,285 @@
+<% include( '/elements/header.html', "Process $type{$payby} payment" ) %>
+<% include( '/elements/small_custview.html', $cust_main, '', '', popurl(2) . "view/cust_main.cgi" ) %>
+<FORM NAME="OneTrueForm" ACTION="process/payment.cgi" METHOD="POST" onSubmit="document.OneTrueForm.process.disabled=true">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+<INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
+<INPUT TYPE="hidden" NAME="payunique" VALUE="<% $payunique %>">
+<INPUT TYPE="hidden" NAME="balance" VALUE="<% $balance %>">
+
+<% include('/elements/init_overlib.html') %>
+
+% #include( '/elements/table.html', '#cccccc' )
+
+<% ntable('#cccccc') %>
+ <TR>
+ <TD ALIGN="right">Payment amount</TD>
+ <TD>
+ <TABLE><TR><TD BGCOLOR="#ffffff">
+ $<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<% $balance > 0 ? sprintf("%.2f", $balance) : '' %>">
+ </TD></TR></TABLE>
+ </TD>
+ </TR>
+
+% if ( $payby eq 'CARD' ) {
+%
+% my( $payinfo, $paycvv, $month, $year ) = ( '', '', '', '' );
+% my $payname = $cust_main->first. ' '. $cust_main->getfield('last');
+% my $address1 = $cust_main->address1;
+% my $address2 = $cust_main->address2;
+% my $city = $cust_main->city;
+% my $state = $cust_main->state;
+% my $zip = $cust_main->zip;
+% if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) {
+% $payinfo = $cust_main->paymask;
+% $paycvv = $cust_main->paycvv;
+% ( $month, $year ) = $cust_main->paydate_monthyear;
+% $payname = $cust_main->payname if $cust_main->payname;
+% }
+
+ <TR>
+ <TD ALIGN="right">Card&nbsp;number</TD>
+ <TD>
+ <TABLE>
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="payinfo" SIZE=20 MAXLENGTH=19 VALUE="<%$payinfo%>"> </TD>
+ <TD>Exp.</TD>
+ <TD>
+ <SELECT NAME="month">
+% for ( ( map "0$_", 1 .. 9 ), 10 .. 12 ) {
+
+ <OPTION<% $_ == $month ? ' SELECTED' : '' %>><% $_ %>
+% }
+
+ </SELECT>
+ </TD>
+ <TD> / </TD>
+ <TD>
+ <SELECT NAME="year">
+% my @a = localtime; for ( $a[5]+1900 .. $a[5]+1915 ) {
+
+ <OPTION<% $_ == $year ? ' SELECTED' : '' %>><% $_ %>
+% }
+
+ </SELECT>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">CVV2</TD>
+ <TD><INPUT TYPE="text" NAME="paycvv" VALUE="<% $paycvv %>" SIZE=4 MAXLENGTH=4>
+ (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)
+ </TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TD>
+ <TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%$payname%>"></TD>
+ </TR><TR>
+ <TD ALIGN="right">Card&nbsp;billing&nbsp;address</TD>
+ <TD>
+ <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address1" VALUE="<%$address1%>">
+ </TD>
+ </TR><TR>
+ <TD ALIGN="right">Address&nbsp;line&nbsp;2</TD>
+ <TD>
+ <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address2" VALUE="<%$address2%>">
+ </TD>
+ </TR><TR>
+ <TD ALIGN="right">City</TD>
+ <TD>
+ <TABLE>
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="city" SIZE="12" MAXLENGTH=80 VALUE="<%$city%>">
+ </TD>
+ <TD>State</TD>
+ <TD>
+ <SELECT NAME="state">
+% for ( @states ) {
+
+ <OPTION<% $_ eq $state ? ' SELECTED' : '' %>><% $_ %>
+% }
+
+ </SELECT>
+ </TD>
+ <TD>Zip</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="zip" SIZE=11 MAXLENGTH=10 VALUE="<%$zip%>">
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+
+% } elsif ( $payby eq 'CHEK' ) {
+%
+% my( $payinfo1, $payinfo2, $payname, $ss, $paytype, $paystate,
+% $stateid, $stateid_state )
+% = ( '', '', '', '', '', '', '', '' );
+% if ( $cust_main->payby =~ /^(CHEK|DCHK)$/ ) {
+% $cust_main->paymask =~ /^([\dx]+)\@([\dx]+)$/i
+% or die "unparsable payinfo ". $cust_main->payinfo;
+% ($payinfo1, $payinfo2) = ($1, $2);
+% $payname = $cust_main->payname;
+% $ss = $cust_main->ss;
+% $paytype = $cust_main->getfield('paytype');
+% $paystate = $cust_main->getfield('paystate');
+% $stateid = $cust_main->getfield('stateid');
+% $stateid_state = $cust_main->getfield('stateid_state');
+% }
+
+ <INPUT TYPE="hidden" NAME="month" VALUE="12">
+ <INPUT TYPE="hidden" NAME="year" VALUE="2037">
+ <TR>
+ <TD ALIGN="right">Account&nbsp;number</TD>
+ <TD><INPUT TYPE="text" SIZE=10 NAME="payinfo1" VALUE="<%$payinfo1%>"></TD>
+ <TD ALIGN="right">Type</TD>
+ <TD><SELECT NAME="paytype"><% join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes) %></SELECT></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">ABA/Routing&nbsp;number</TD>
+ <TD>
+ <INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="payinfo2" VALUE="<%$payinfo2%>">
+ (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)
+ </TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Bank&nbsp;name</TD>
+ <TD><INPUT TYPE="text" NAME="payname" VALUE="<%$payname%>"></TD>
+ </TR>
+
+% if ( $conf->exists('show_bankstate') ) {
+ <TR>
+ <TD ALIGN="right">Bank&nbsp;state</TD>
+ <TD><% include('/elements/select-state.html',
+ 'disable_empty' => 0,
+ 'empty_label' => '(choose)',
+ 'state' => $paystate,
+ 'country' => $cust_main->country,
+ 'prefix' => 'pay',
+ )
+ %>
+ </TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="paystate" VALUE="<% $paystate %>">
+% }
+
+% if ( $conf->exists('show_ss') ) {
+ <TR>
+ <TD ALIGN="right">
+ Account&nbsp;holder<BR>
+ Social&nbsp;security&nbsp;or&nbsp;tax&nbsp;ID&nbsp;#
+ </TD>
+ <TD><INPUT TYPE="text" NAME="ss" VALUE="<% $ss %>"></TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="ss" VALUE="<% $ss %>"></TD>
+% }
+
+% if ( $conf->exists('show_stateid') ) {
+ <TR>
+ <TD ALIGN="right">
+ Account&nbsp;holder<BR>
+ Driver&rsquo;s&nbsp;license&nbsp;or&nbsp;state&nbsp;ID&nbsp;#
+ </TD>
+ <TD><INPUT TYPE="text" NAME="stateid" VALUE="<% $stateid %>"></TD>
+ <TD ALIGN="right">State</TD>
+ <TD><% include('/elements/select-state.html',
+ 'disable_empty' => 0,
+ 'empty_label' => '(choose)',
+ 'state' => $stateid_state,
+ 'country' => $cust_main->country,
+ 'prefix' => 'stateid_',
+ )
+ %>
+ </TD>
+ </TR>
+% } else {
+ <INPUT TYPE="hidden" NAME="stateid" VALUE="<% $stateid %>">
+ <INPUT TYPE="hidden" NAME="stateid_state" VALUE="<% $stateid_state %>">
+% }
+
+% } #end CARD/CHEK-specific section
+
+
+<TR>
+ <TD COLSPAN=2>
+ <INPUT TYPE="checkbox" CHECKED NAME="save" VALUE="1">
+ Remember this information
+ </TD>
+</TR>
+
+% if ( $conf->exists("batch-enable")
+% || grep $payby eq $_, $conf->config('batch-enable_payby')
+% ) {
+%
+% if ( grep $payby eq $_, $conf->config('realtime-disable_payby') ) {
+
+ <INPUT TYPE="hidden" NAME="batch" VALUE="1">
+
+% } else {
+
+ <TR>
+ <TD COLSPAN=2>
+ <INPUT TYPE="checkbox" NAME="batch" VALUE="1">
+ Add to current batch
+ </TD>
+ </TR>
+
+% }
+% }
+
+<TR>
+ <TD COLSPAN=2>
+ <INPUT TYPE="checkbox"<% ( ( $payby eq 'CARD' && $cust_main->payby ne 'DCRD' ) || ( $payby eq 'CHEK' && $cust_main->payby eq 'CHEK' ) ) ? ' CHECKED' : '' %> NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }">
+ Charge future payments to this <% $type{$payby} %> automatically
+ </TD>
+</TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="process" VALUE="Process payment">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Process payment');
+
+my %type = ( 'CARD' => 'credit card',
+ 'CHEK' => 'electronic check (ACH)',
+ );
+
+$cgi->param('payby') =~ /^(CARD|CHEK)$/
+ or die "unknown payby ". $cgi->param('payby');
+my $payby = $1;
+
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die "illegal custnum ". $cgi->param('custnum');
+my $custnum = $1;
+
+my $cust_main = qsearchs( 'cust_main', { 'custnum'=>$custnum } );
+die "unknown custnum $custnum" unless $cust_main;
+
+my $balance = $cust_main->balance;
+
+my $payinfo = '';
+
+#false laziness w/selfservice make_payment.html shortcut for one-country
+my $conf = new FS::Conf;
+my %states = map { $_->state => 1 }
+ qsearch('cust_main_county', {
+ 'country' => $conf->config('countrydefault') || 'US'
+ } );
+my @states = sort { $a cmp $b } keys %states;
+
+my $payunique = "webui-payment-". time. "-$$-". rand() * 2**32;
+
+</%init>
+
+
diff --git a/httemplate/misc/phone_avail-import.html b/httemplate/misc/phone_avail-import.html
new file mode 100644
index 000000000..1f4d8caae
--- /dev/null
+++ b/httemplate/misc/phone_avail-import.html
@@ -0,0 +1,88 @@
+<% include('/elements/header.html', 'Phone number (DID) import') %>
+
+Import a file containing phone numbers (DIDs).
+<BR><BR>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'PhonenumImportForm',
+ 'action' => 'process/phone_avail-import.html',
+ 'num_files' => 1,
+ 'fields' => [ 'format', 'availbatch', 'exportnum', 'countrycode' ],
+ 'message' => 'DID import successful',
+ 'url' => $p."search/phone_avail.html?availbatch=$availbatch",
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <INPUT TYPE="hidden" NAME="format" VALUE="default">
+
+ <INPUT TYPE="hidden" NAME="availbatch" VALUE="<% $availbatch %>">
+
+ <% include( '/elements/tr-select-table.html',
+ 'table' => 'part_export',
+ 'name_col' => 'machine',
+ 'label' => 'Export',
+ 'empty_label' => 'Select export',
+ 'hashref' => { 'exporttype' => 'internal_diddb', },
+ #'label_callback' =>
+ )
+ %>
+
+ <TR>
+ <TH ALIGN="right">Country code</TH>
+ <TD>
+ <INPUT TYPE = "text"
+ NAME = "countrycode"
+ VALUE = "<% $conf->config('default_phone_countrycode') || 1 %>"
+ >
+ </TD>
+ </TR>
+
+ <% include( '/elements/file-upload.html',
+ 'field' => 'file',
+ 'label' => 'Filename',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "Import file"
+ onClick = "document.PhonenumImportForm.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+
+Uploaded files can be CSV (comma-separated value) files or Excel spreadsheets. The file should have a .CSV or .XLS extension.
+<BR><BR>
+
+<b>Default</b> format has the following field order: <i>state, number<i></i>
+<BR><BR>
+
+Field information:
+<ul>
+ <li><i>state</i>: Two-letter state code, i.e. "CA"
+ <li><i>number</i>: Phone number
+</ul>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $conf = new FS::Conf;
+
+my $availbatch =
+ time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+</%init>
diff --git a/httemplate/misc/phonenums.cgi b/httemplate/misc/phonenums.cgi
new file mode 100644
index 000000000..2ed0f617d
--- /dev/null
+++ b/httemplate/misc/phonenums.cgi
@@ -0,0 +1,29 @@
+%# [ <% join(', ', map { qq("$_") } @exchanges) %> ]
+<% objToJson(\@exchanges) %>
+<%init>
+
+my( $exchangestring, $svcpart ) = $cgi->param('arg');
+
+$exchangestring =~ /\((\d{3})-(\d{3})-XXXX\)\s*$/i
+ or die "unparsable exchange: $exchangestring";
+my( $areacode, $exchange ) = ( $1, $2 );
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @exports = $part_svc->part_export_did;
+if ( scalar(@exports) > 1 ) {
+ die "more than one DID-providing export attached to svcpart $svcpart";
+} elsif ( ! @exports ) {
+ die "no DID providing export attached to svcpart $svcpart";
+}
+my $export = $exports[0];
+
+my $something = $export->get_dids('areacode'=>$areacode,
+ 'exchange'=>$exchange,
+ );
+
+#warn Dumper($something);
+
+my @exchanges = @{ $something };
+
+</%init>
diff --git a/httemplate/misc/print-invoice.cgi b/httemplate/misc/print-invoice.cgi
new file mode 100755
index 000000000..aeef68795
--- /dev/null
+++ b/httemplate/misc/print-invoice.cgi
@@ -0,0 +1,19 @@
+<% $cgi->redirect("${p}view/cust_main.cgi?$custnum") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $template = $2;
+my $invnum = $3;
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+die "Can't find invoice!\n" unless $cust_bill;
+
+$cust_bill->print($template);
+
+my $custnum = $cust_bill->getfield('custnum');
+
+</%init>
diff --git a/httemplate/misc/print_events.cgi b/httemplate/misc/print_events.cgi
new file mode 100644
index 000000000..8d83d3de1
--- /dev/null
+++ b/httemplate/misc/print_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_event::process_reprint', $cgi;
+
+</%init>
diff --git a/httemplate/misc/print_invoice_events.cgi b/httemplate/misc/print_invoice_events.cgi
new file mode 100644
index 000000000..c974d5f4e
--- /dev/null
+++ b/httemplate/misc/print_invoice_events.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reprint', $cgi;
+
+</%init>
diff --git a/httemplate/misc/print_invoices.cgi b/httemplate/misc/print_invoices.cgi
new file mode 100644
index 000000000..f859f6db8
--- /dev/null
+++ b/httemplate/misc/print_invoices.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reprint', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/batch-cust_pay.cgi b/httemplate/misc/process/batch-cust_pay.cgi
new file mode 100644
index 000000000..058a2251a
--- /dev/null
+++ b/httemplate/misc/process/batch-cust_pay.cgi
@@ -0,0 +1,47 @@
+% die "access denied"
+% unless $FS::CurrentUser::CurrentUser->access_right('Post payment batch');
+%
+% my $param = $cgi->Vars;
+%
+% #my $paybatch = $param->{'paybatch'};
+% my $paybatch = time2str('webbatch-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+%
+% my @cust_pay = ();
+% #my $row = 0;
+% #while ( exists($param->{"custnum$row"}) ) {
+% for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) {
+% push @cust_pay, new FS::cust_pay {
+% 'custnum' => $param->{"custnum$row"},
+% 'paid' => $param->{"paid$row"},
+% 'payby' => 'BILL',
+% 'payinfo' => $param->{"payinfo$row"},
+% 'paybatch' => $paybatch,
+% }
+% if $param->{"custnum$row"}
+% || $param->{"paid$row"}
+% || $param->{"payinfo$row"};
+% #$row++;
+% }
+%
+% my @errors = FS::cust_pay->batch_insert(@cust_pay);
+% my $num_errors = scalar(grep $_, @errors);
+%
+% if ( $num_errors ) {
+%
+% $cgi->param('error', "$num_errors error". ($num_errors>1 ? 's' : '').
+% ' - Batch not processed, correct and resubmit'
+% );
+%
+% my $erow=0;
+% $cgi->param('error'. $erow++, shift @errors) while @errors;
+%
+%
+<% $cgi->redirect($p.'batch-cust_pay.html?'. $cgi->query_string)
+
+ %>
+% } else {
+%
+%
+<% $cgi->redirect(popurl(3). "search/cust_pay.cgi?magic=paybatch;paybatch=$paybatch") %>
+% }
+
diff --git a/httemplate/misc/process/bulk_change_pkg.cgi b/httemplate/misc/process/bulk_change_pkg.cgi
new file mode 100755
index 000000000..d2ab4bf49
--- /dev/null
+++ b/httemplate/misc/process/bulk_change_pkg.cgi
@@ -0,0 +1,56 @@
+% if ($error) {
+<% $cgi->redirect(popurl(2)."/bulk_change_pkg.cgi?".$cgi->query_string ) %>
+% }
+<% include('/elements/header-popup.html', "Packages Changed") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages');
+
+my %search_hash = ();
+
+$search_hash{'query'} = $cgi->param('query');
+
+for my $param (qw(agentnum magic status classnum pkgpart)) {
+ $search_hash{$param} = $cgi->param($param)
+ if $cgi->param($param);
+}
+
+###
+# parse dates
+###
+
+#false laziness w/report_cust_pkg.html
+my %disable = (
+ 'all' => {},
+ 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, },
+ 'active' => { 'susp'=>1, 'cancel'=>1 },
+ 'suspended' => { 'cancel' => 1 },
+ 'cancelled' => {},
+ '' => {},
+);
+
+foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
+
+ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
+
+ next if $beginning == 0 && $ending == 4294967295
+ or $disable{$cgi->param('status')}->{$field};
+
+ $search_hash{$field} = [ $beginning, $ending ];
+
+}
+
+my $sql_query = FS::cust_pkg->search_sql(\%search_hash);
+$sql_query->{'select'} = 'cust_pkg.pkgnum';
+
+my $error = FS::cust_pkg::bulk_change( [ $cgi->param('new_pkgpart') ],
+ [ map { $_->pkgnum } qsearch($sql_query) ],
+ );
+
+$cgi->param("error", substr($error, 0, 512)); # arbitrary length believed
+ # suited for all supported
+ # browsers
+
+
+</%init>
diff --git a/httemplate/misc/process/cancel_pkg.html b/httemplate/misc/process/cancel_pkg.html
new file mode 100755
index 000000000..669af9c87
--- /dev/null
+++ b/httemplate/misc/process/cancel_pkg.html
@@ -0,0 +1,72 @@
+<% header("Package $past{$method}") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+</HTML>
+<%once>
+
+my %past = ( 'cancel' => 'cancelled',
+ 'expire' => 'expired',
+ 'suspend' => 'suspended',
+ 'adjourn' => 'adjourned',
+ );
+
+#i'm sure this is false laziness with somewhere, at least w/misc/cancel_pkg.html
+my %right = ( 'cancel' => 'Cancel customer package immediately',
+ 'expire' => 'Cancel customer package later',
+ 'suspend' => 'Suspend customer package',
+ 'adjourn' => 'Suspend customer package later',
+ );
+
+</%once>
+<%init>
+
+#untaint method
+my $method = $cgi->param('method');
+$method =~ /^(cancel|expire|suspend|adjourn)$/ or die "Illegal method";
+$method = $1;
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right($right{$method});
+
+#untaint pkgnum
+my $pkgnum = $cgi->param('pkgnum');
+$pkgnum =~ /^(\d+)$/ or die "Illegal pkgnum";
+$pkgnum = $1;
+
+#untaint reasonnum
+my $reasonnum = $cgi->param('reasonnum');
+$reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum";
+$reasonnum = $1;
+
+my $date = time;
+if ($method eq 'expire' || $method eq 'adjourn'){
+ #untaint date
+ $date = $cgi->param('date');
+ str2time($cgi->param('date')) =~ /^(\d+)$/ or die "Illegal date";
+ $date = $1;
+ $method = ($method eq 'expire') ? 'cancel' : 'suspend';
+}
+
+my $cust_pkg = qsearchs( 'cust_pkg', {'pkgnum'=>$pkgnum} );
+
+#my $otaker = $FS::CurrentUser::CurrentUser->name;
+#$otaker = $FS::CurrentUser::CurrentUser->username
+# if ($otaker eq "User, Legacy");
+
+if ($reasonnum == -1) {
+ $reasonnum = {
+ 'typenum' => scalar( $cgi->param('newreasonnumT') ),
+ 'reason' => scalar( $cgi->param('newreasonnum' ) ),
+ };
+}
+
+my $error = $cust_pkg->$method( 'reason' => $reasonnum, 'date' => $date );
+
+if ($error) {
+ $cgi->param('error', $error);
+ print $cgi->redirect(popurl(2). "cancel_pkg.html?". $cgi->query_string );
+}
+
+</%init>
diff --git a/httemplate/misc/process/catchall.cgi b/httemplate/misc/process/catchall.cgi
new file mode 100755
index 000000000..0dda2eada
--- /dev/null
+++ b/httemplate/misc/process/catchall.cgi
@@ -0,0 +1,35 @@
+%if ($error) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "catchall.cgi?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall');
+
+$FS::svc_domain::whois_hack=1;
+
+$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!";
+my $svcnum =$1;
+
+my $old = qsearchs('svc_domain',{'svcnum'=>$svcnum}) if $svcnum;
+
+my $new = new FS::svc_domain ( {
+ map {
+ ($_, scalar($cgi->param($_)));
+ } ( fields('svc_domain'), qw( pkgnum svcpart ) )
+} );
+
+$new->setfield('action' => 'M');
+
+my $error;
+if ( $svcnum ) {
+ $error = $new->replace($old);
+} else {
+ $error = $new->insert;
+ $svcnum = $new->getfield('svcnum');
+}
+
+</%init>
diff --git a/httemplate/misc/process/cdr-import.html b/httemplate/misc/process/cdr-import.html
new file mode 100644
index 000000000..edc441e35
--- /dev/null
+++ b/httemplate/misc/process/cdr-import.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cdr::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/copy-rate_detail.html b/httemplate/misc/process/copy-rate_detail.html
new file mode 100644
index 000000000..87a674566
--- /dev/null
+++ b/httemplate/misc/process/copy-rate_detail.html
@@ -0,0 +1,61 @@
+%# if ( $error ) {
+%# <% $cgi->redirect(popurl(2).'copy-rate_detail.html?'. $cgi->query_string ) %>
+%# } else {
+<% include('/elements/header.html', 'Rates copied',
+ menubar( 'View all rate plans' => popurl(3).'browse/rate.cgi' ),
+ ) %>
+%# }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('src_ratenum') =~ /^(\d+)$/ or die 'Illegal src_ratenum';
+my $src_ratenum = $1;
+
+$cgi->param('dst_ratenum') =~ /^(\d+)$/ or die 'Illegal src_ratenum';
+my $dst_ratenum = $1;
+
+my @countrycodes = map { /^countrycode(\d+)$/ or die; $1 }
+ grep { /^countrycode(\d+)$/ && $cgi->param($_) }
+ $cgi->param;
+
+foreach my $countrycode ( @countrycodes ) {
+
+ my @src_rate_detail = qsearch({
+ 'table' => 'rate_detail',
+ 'addl_from' => 'JOIN rate_region'.
+ ' ON ( rate_detail.dest_regionnum = rate_region.regionnum )',
+ 'hashref' => { 'ratenum' => $src_ratenum },
+ 'extra_sql' =>
+ "AND 0 < ( SELECT COUNT(*) FROM rate_prefix
+ WHERE rate_prefix.regionnum = rate_region.regionnum
+ AND countrycode = '$countrycode'
+ )
+ ",
+ });
+
+ foreach my $src_rate_detail ( @src_rate_detail ) {
+
+ my %hash = (
+ 'ratenum' => $dst_ratenum,
+ map { $_ => $src_rate_detail->get($_) }
+ qw( orig_regionnum dest_regionnum )
+ );
+
+ my $dst_rate_detail = qsearchs( 'rate_detail', \%hash)
+ || new FS::rate_detail \%hash;
+
+ $dst_rate_detail->$_( $src_rate_detail->get($_) )
+ foreach qw( min_included min_charge sec_granularity classnum );
+
+ my $method = $dst_rate_detail->ratedetailnum ? 'replace' : 'insert';
+
+ my $error = $dst_rate_detail->$method();
+
+ die $error if $error; # "shouldn't" happen
+
+ }
+}
+
+</%init>
diff --git a/httemplate/misc/process/cust_main-import.cgi b/httemplate/misc/process/cust_main-import.cgi
new file mode 100644
index 000000000..2b705a6fc
--- /dev/null
+++ b/httemplate/misc/process/cust_main-import.cgi
@@ -0,0 +1,10 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server =
+ new FS::UI::Web::JSRPC 'FS::cust_main::Import::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/cust_main-import_charges.cgi b/httemplate/misc/process/cust_main-import_charges.cgi
new file mode 100644
index 000000000..3ca68944a
--- /dev/null
+++ b/httemplate/misc/process/cust_main-import_charges.cgi
@@ -0,0 +1,23 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+ <% include('/elements/header.html','Import successful') %>
+ <% include('/elements/footer.html') %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $fh = $cgi->upload('csvfile');
+#warn $cgi;
+#warn $fh;
+
+my $error = defined($fh)
+ ? FS::cust_main::batch_charge( {
+ filehandle => $fh,
+ 'fields' => [qw( custnum amount pkg )],
+ } )
+ : 'No file';
+
+</%init>
diff --git a/httemplate/misc/process/cust_main_note-import.cgi b/httemplate/misc/process/cust_main_note-import.cgi
new file mode 100644
index 000000000..6aa8b1d37
--- /dev/null
+++ b/httemplate/misc/process/cust_main_note-import.cgi
@@ -0,0 +1,82 @@
+<% include("/elements/header.html", "Batch Customer Note Import $op") %>
+
+The following items <% $op eq 'Preview' ? 'would not be' : 'were not' %> imported. (See below for imported items)
+<PRE>
+% foreach my $row (@uninserted) {
+% $csv->combine( (map{ $row->{$_} } qw(last first note) ),
+% $row->{error} ? ('#!', $row->{error}) : (),
+% );
+<% $csv->string %>
+% }
+</PRE>
+
+The following items <% $op eq 'Preview' ? 'would be' : 'were' %> imported. (See above for unimported items)
+
+<PRE>
+% foreach my $row (@inserted) {
+% $csv->combine( (map{ $row->{$_} } qw(custnum last first note) ),
+% ('#!', $row->{name}),
+% );
+<% $csv->string %>
+% }
+</PRE>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $date = time;
+my $otaker = $FS::CurrentUser::CurrentUser->username;
+my $csv = new Text::CSV_XS;
+
+my $param = $cgi->Vars;
+
+my $op = $param->{preview} ? "Preview" : "Results";
+
+my @inserted = ();
+my @uninserted = ();
+for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) {
+ if ( $param->{"custnum$row"} ) {
+# my $cust_main_note = new FS::cust_main_note {
+# 'custnum' => $param->{"custnum$row"},
+# '_date' => $date,
+# 'otaker' => $otaker,
+# 'comments' => $param->{"note$row"},
+# };
+# my $error = '';
+# $error = $cust_main_note->insert unless ($op eq "Preview");
+ my $cust_main = qsearchs('cust_main',
+ { 'custnum' => $param->{"custnum$row"} }
+ );
+ my $error;
+ if ($cust_main) {
+ $cust_main->comments
+ ? $cust_main->comments($cust_main->comments. " ". $param->{"note$row"})
+ : $cust_main->comments($param->{"note$row"});
+ $error = $cust_main->replace;
+ }else{
+ $error = "Can't find customer " . $param->{"custnum$row"};
+ }
+ my $result = { 'custnum' => $param->{"custnum$row"},
+ 'last' => $param->{"last$row"},
+ 'first' => $param->{"first$row"},
+ 'note' => $param->{"note$row"},
+ 'name' => $param->{"name$row"},
+ 'error' => $error,
+ };
+ if ($error) {
+ push @uninserted, $result;
+ }else{
+ push @inserted, $result;
+ }
+ }else{
+ push @uninserted, { 'custnum' => '',
+ 'last' => $param->{"last$row"},
+ 'first' => $param->{"first$row"},
+ 'note' => $param->{"note$row"},
+ 'error' => '',
+ };
+ }
+}
+</%init>
diff --git a/httemplate/misc/process/cust_pay-import.cgi b/httemplate/misc/process/cust_pay-import.cgi
new file mode 100644
index 000000000..d4ff226ec
--- /dev/null
+++ b/httemplate/misc/process/cust_pay-import.cgi
@@ -0,0 +1,21 @@
+<% $cgi->redirect(popurl(3). "search/cust_pay.cgi?magic=paybatch;paybatch=$paybatch") %>
+<%init>
+
+my $fh = $cgi->upload('csvfile');
+
+# webbatch? I suppose
+my $paybatch = time2str('webbatch-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+my $error = defined($fh)
+ ? FS::cust_pay::batch_import( {
+ 'filehandle' => $fh,
+ 'agentnum' => scalar($cgi->param('agentnum')),
+ 'format' => scalar($cgi->param('format')),
+ 'paybatch' => $paybatch,
+ } )
+ : 'No file';
+
+errorpage($error)
+ if ( $error );
+
+</%init>
diff --git a/httemplate/misc/process/delay_susp_pkg.html b/httemplate/misc/process/delay_susp_pkg.html
new file mode 100755
index 000000000..c7cc7de7c
--- /dev/null
+++ b/httemplate/misc/process/delay_susp_pkg.html
@@ -0,0 +1,41 @@
+<% header("Package suspension delayed") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+</HTML>
+<%once>
+
+my $right = 'Delay suspension events';
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right($right);
+
+my ($pkgnum, $date, $cust_pkg, $cust_main, $error);
+
+#untaint pkgnum
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die "Illegal pkgnum";
+$pkgnum = $1;
+
+#untaint date
+str2time($cgi->param('date')) =~ /^(\d+)$/ or die "Illegal date";
+my $date = $1;
+
+$cust_pkg = qsearchs( 'cust_pkg', {'pkgnum'=>$pkgnum} );
+if ($cust_pkg) {
+ $cust_main = $cust_pkg->cust_main;
+ $cust_main->dundate( $date );
+ $error = $cust_main->replace;
+} else {
+ $error = "Invalid pkgnum";
+}
+
+if ($error) {
+ $cgi->param('error', $error);
+ print $cgi->redirect(popurl(2). "cancel_pkg.html?". $cgi->query_string );
+}
+
+</%init>
diff --git a/httemplate/misc/process/delete-customer.cgi b/httemplate/misc/process/delete-customer.cgi
new file mode 100755
index 000000000..d509a5e0e
--- /dev/null
+++ b/httemplate/misc/process/delete-customer.cgi
@@ -0,0 +1,33 @@
+%if ( $error ) {
+% $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "delete-customer.cgi?". $cgi->query_string ) %>
+%} elsif ( $new_custnum ) {
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$new_custnum") %>
+%} else {
+<% $cgi->redirect(popurl(3)) %>
+%}
+<%init>
+
+my $conf = new FS::Conf;
+die "Customer deletions not enabled in configuration"
+ unless $conf->exists('deletecustomers');
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete customer');
+
+$cgi->param('custnum') =~ /^(\d+)$/;
+my $custnum = $1;
+my $new_custnum;
+if ( $cgi->param('new_custnum') ) {
+ $cgi->param('new_custnum') =~ /^(\d+)$/
+ or die "Illegal new customer number: ". $cgi->param('new_custnum');
+ $new_custnum = $1;
+} else {
+ $new_custnum = '';
+}
+my $cust_main = qsearchs( 'cust_main', { 'custnum' => $custnum } )
+ or die "Customer not found: $custnum";
+
+my $error = $cust_main->delete($new_custnum);
+
+</%init>
diff --git a/httemplate/misc/process/email-customers.html b/httemplate/misc/process/email-customers.html
new file mode 100644
index 000000000..d254cfecb
--- /dev/null
+++ b/httemplate/misc/process/email-customers.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_main::process_email_search_sql', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/enable_or_disable_tax.html b/httemplate/misc/process/enable_or_disable_tax.html
new file mode 100755
index 000000000..9b7324b0d
--- /dev/null
+++ b/httemplate/misc/process/enable_or_disable_tax.html
@@ -0,0 +1,41 @@
+%if ($error) {
+<% $cgi->redirect(popurl(2).'enable_or_disable_tax.html?'.$cgi->query_string) %>
+%}else{
+ <% include('/elements/header-popup.html', $title) %>
+
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+
+ </BODY>
+ </HTML>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $action = '';
+if ( $cgi->param('action') =~ /^(\w+)$/ ) {
+ $action = $1;
+}
+
+my ($query, $count_query) = FS::tax_rate::browse_queries(scalar($cgi->Vars));
+my @tax_rate = qsearch( $query );
+
+#transaction?
+my $error;
+$error = "Invalid action" unless ($action =~ /enable|disable/);
+
+foreach my $tax_rate (@tax_rate) {
+ $action eq 'enable' ? $tax_rate->disabled('') : $tax_rate->disabled('Y');
+ # $tax_rate->manual('Y');
+ $error ||= $tax_rate->replace;
+ last if $error;
+}
+$cgi->param('error', $error) if $error;
+
+my $title = scalar(@tax_rate) == 1 ? 'Tax rate ' : 'Tax rates ';
+$title .= lc($action). 'd';
+
+</%init>
diff --git a/httemplate/misc/process/inventory_item-import.html b/httemplate/misc/process/inventory_item-import.html
new file mode 100644
index 000000000..377943fb1
--- /dev/null
+++ b/httemplate/misc/process/inventory_item-import.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server = new FS::UI::Web::JSRPC 'FS::inventory_item::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/link.cgi b/httemplate/misc/process/link.cgi
new file mode 100755
index 000000000..df15dca72
--- /dev/null
+++ b/httemplate/misc/process/link.cgi
@@ -0,0 +1,72 @@
+%unless ($error) {
+% #no errors, so let's view this customer.
+% my $custnum = $new->cust_pkg->custnum;
+<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum#cust_pkg$pkgnum" ) %>
+%} else {
+% errorpage($error);
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View/link unlinked services');
+
+my $DEBUG = 0;
+
+$cgi->param('pkgnum') =~ /^(\d+)$/;
+my $pkgnum = $1;
+$cgi->param('svcpart') =~ /^(\d+)$/;
+my $svcpart = $1;
+$cgi->param('svcnum') =~ /^(\d*)$/;
+my $svcnum = $1;
+
+unless ( $svcnum ) {
+ my $part_svc = qsearchs('part_svc',{'svcpart'=>$svcpart});
+ my $svcdb = $part_svc->getfield('svcdb');
+ $cgi->param('link_field') =~ /^(\w+)$/;
+ my $link_field = $1;
+ my %search = ( $link_field => $cgi->param('link_value') );
+ if ( $cgi->param('link_field2') =~ /^(\w+)$/ ) {
+ $search{$1} = $cgi->param('link_value2');
+ }
+
+ my @svc_x = ( sort { ($a->cust_svc->pkgnum > 0) <=> ($b->cust_svc->pkgnum > 0)
+ or ($b->cust_svc->svcpart == $svcpart)
+ <=> ($a->cust_svc->svcpart == $svcpart)
+ }
+ qsearch( $svcdb, \%search )
+ );
+
+ if ( $DEBUG ) {
+ warn scalar(@svc_x). " candidate accounts found for linking ".
+ "(svcpart $svcpart):\n";
+ foreach my $svc_x ( @svc_x ) {
+ warn " ". $svc_x->email.
+ " (svcnum ". $svc_x->svcnum. ",".
+ " pkgnum ". $svc_x->cust_svc->pkgnum. ",".
+ " svcpart ". $svc_x->cust_svc->svcpart. ")\n";
+ }
+ }
+
+ my $svc_x = $svc_x[0];
+
+ errorpage("$link_field not found!") unless $svc_x;
+
+ $svcnum = $svc_x->svcnum;
+
+}
+
+my $old = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "svcnum not found!" unless $old;
+my $conf = new FS::Conf;
+my($error, $new);
+if ( $old->pkgnum && ! $conf->exists('legacy_link-steal') ) {
+ $error = "svcnum $svcnum already linked to package ". $old->pkgnum;
+} else {
+ $new = new FS::cust_svc { $old->hash };
+ $new->pkgnum($pkgnum);
+ $new->svcpart($svcpart);
+
+ $error = $new->replace($old);
+}
+
+</%init>
diff --git a/httemplate/misc/process/meta-import.cgi b/httemplate/misc/process/meta-import.cgi
new file mode 100644
index 000000000..68ae49c60
--- /dev/null
+++ b/httemplate/misc/process/meta-import.cgi
@@ -0,0 +1,190 @@
+<% include("/elements/header.html",'Map tables') %>
+
+<SCRIPT>
+var gSafeOnload = new Array();
+var gSafeOnsubmit = new Array();
+window.onload = SafeOnload;
+function SafeAddOnLoad(f) {
+ gSafeOnload[gSafeOnload.length] = f;
+}
+function SafeOnload() {
+ for (var i=0;i<gSafeOnload.length;i++)
+ gSafeOnload[i]();
+}
+function SafeAddOnSubmit(f) {
+ gSafeOnsubmit[gSafeOnsubmit.length] = f;
+}
+function SafeOnsubmit() {
+ for (var i=0;i<gSafeOnsubmit.length;i++)
+ gSafeOnsubmit[i]();
+}
+</SCRIPT>
+
+<FORM NAME="OneTrueForm" METHOD="POST" ACTION="meta-import.cgi">
+%
+% #use DBIx::DBSchema;
+% my $schema = new_native DBIx::DBSchema
+% map { $cgi->param($_) } qw( data_source username password );
+% foreach my $field (qw( data_source username password )) {
+
+ <INPUT TYPE="hidden" NAME=<% $field %> VALUE="<% $cgi->param($field) %>">
+% }
+%
+% my %schema;
+% use Tie::DxHash;
+% tie %schema, 'Tie::DxHash';
+% if ( $cgi->param('schema') ) {
+% my $schema_string = $cgi->param('schema');
+%
+ <INPUT TYPE="hidden" NAME="schema" VALUE="<%$schema_string%>">
+%
+% %schema = map { /^\s*(\w+)\s*=>\s*(\w+)\s*$/
+% or die "guru meditation #420: $_";
+% ( $1 => $2 );
+% }
+% split( /\n/, $schema_string );
+% }
+%
+% #first page
+% unless ( $cgi->param('magic') ) {
+
+
+ <INPUT TYPE="hidden" NAME="magic" VALUE="process">
+ <% hashmaker('schema', [ $schema->tables ],
+ [ grep !/^h_/, dbdef->tables ], ) %>
+ <br><INPUT TYPE="submit" VALUE="done">
+%
+%
+% #second page
+% } elsif ( $cgi->param('magic') eq 'process' ) {
+
+
+ <INPUT TYPE="hidden" NAME="magic" VALUE="process2">
+%
+%
+% my %unique;
+% foreach my $table ( keys %schema ) {
+%
+% my @from_columns = $schema->table($table)->columns;
+% my @fs_columns = dbdef->table($schema{$table})->columns;
+%
+%
+
+ <% hashmaker( $table.'__'.$unique{$table}++,
+ \@from_columns => \@fs_columns,
+ $table => $schema{$table}, ) %>
+ <br><hr><br>
+%
+%
+% }
+%
+%
+
+ <br><INPUT TYPE="submit" VALUE="done">
+%
+%
+% #third (results)
+% } elsif ( $cgi->param('magic') eq 'process2' ) {
+%
+% print "<pre>\n";
+%
+% my %unique;
+% foreach my $table ( keys %schema ) {
+% ( my $spaces = $table ) =~ s/./ /g;
+% print "'$table' => { 'table' => '$schema{$table}',\n".
+% #(length($table) x ' '). " 'map' => {\n";
+% "$spaces 'map' => {\n";
+% my %map = map { /^\s*(\w+)\s*=>\s*(\w+)\s*$/
+% or die "guru meditation #420: $_";
+% ( $1 => $2 );
+% }
+% split( /\n/, $cgi->param($table.'__'.$unique{$table}++) );
+% foreach ( keys %map ) {
+% print "$spaces '$_' => '$map{$_}',\n";
+% }
+% print "$spaces },\n";
+% print "$spaces },\n";
+%
+% }
+% print "\n</pre>";
+%
+% } else {
+% warn "unrecognized magic: ". $cgi->param('magic');
+% }
+%
+%
+
+</FORM>
+</BODY>
+</HTML>
+%
+% #hashmaker widget
+% sub hashmaker {
+% my($name, $from, $to, $labelfrom, $labelto) = @_;
+% my $fromsize = scalar(@$from);
+% my $tosize = scalar(@$to);
+% "<TABLE><TR><TH>$labelfrom</TH><TH>$labelto</TH></TR><TR><TD>".
+% qq!<SELECT NAME="${name}_from" SIZE=$fromsize>\n!.
+% join("\n", map { qq!<OPTION VALUE="$_">$_</OPTION>! } sort { $a cmp $b } @$from ).
+% "</SELECT>\n<BR>".
+% qq!<INPUT TYPE="button" VALUE="refill" onClick="repack_${name}_from()">!.
+% '</TD><TD>'.
+% qq!<SELECT NAME="${name}_to" SIZE=$tosize>\n!.
+% join("\n", map { qq!<OPTION VALUE="$_">$_</OPTION>! } sort { $a cmp $b } @$to ).
+% "</SELECT>\n<BR>".
+% qq!<INPUT TYPE="button" VALUE="refill" onClick="repack_${name}_to()">!.
+% '</TD></TR>'.
+% '<TR><TD COLSPAN=2>'.
+% qq!<INPUT TYPE="button" VALUE="map" onClick="toke_$name(this.form)">!.
+% '</TD></TR><TR><TD COLSPAN=2>'.
+% qq!<TEXTAREA NAME="$name" COLS=80 ROWS=8></TEXTAREA>!.
+% '</TD></TR></TABLE>'.
+% "<script>
+% function toke_$name() {
+% fromObject = document.OneTrueForm.${name}_from;
+% for (var i=fromObject.options.length-1;i>-1;i--) {
+% if (fromObject.options[i].selected)
+% fromname = deleteOption_$name(fromObject,i);
+% }
+% toObject = document.OneTrueForm.${name}_to;
+% for (var i=toObject.options.length-1;i>-1;i--) {
+% if (toObject.options[i].selected)
+% toname = deleteOption_$name(toObject,i);
+% }
+% document.OneTrueForm.$name.value = document.OneTrueForm.$name.value + fromname + ' => ' + toname + '\\n';
+% }
+% function deleteOption_$name(object,index) {
+% value = object.options[index].value;
+% object.options[index] = null;
+% return value;
+% }
+% function repack_${name}_from() {
+% var object = document.OneTrueForm.${name}_from;
+% object.options.length = 0;
+% ". join("\n",
+% map { "addOption_$name(object, '$_');\n" }
+% ( sort { $a cmp $b } @$from ) ). "
+% }
+% function repack_${name}_to() {
+% var object = document.OneTrueForm.${name}_to;
+% object.options.length = 0;
+% ". join("\n",
+% map { "addOption_$name(object, '$_');\n" }
+% ( sort { $a cmp $b } @$to ) ). "
+% }
+% function addOption_$name(object,value) {
+% var length = object.length;
+% object.options[length] = new Option(value, value, false, false);
+% }
+% </script>".
+% '';
+% }
+%
+%
+<%init>
+
+#there's no ACL for this... haven't used in ages
+#make XSS-safe if this is used for more than just admins to import data....
+die 'meta-import not enabled; remove this if you want to use it';
+
+</%init>
diff --git a/httemplate/misc/process/payment.cgi b/httemplate/misc/process/payment.cgi
new file mode 100644
index 000000000..2baca1e39
--- /dev/null
+++ b/httemplate/misc/process/payment.cgi
@@ -0,0 +1,183 @@
+% if ( $cgi->param('batch') ) {
+
+ <% include( '/elements/header.html', ucfirst($type{$payby}). ' processing successful',
+ include('/elements/menubar.html'),
+
+ )
+ %>
+
+ <% include( '/elements/small_custview.html', $cust_main, '', '', popurl(3). "view/cust_main.cgi" ) %>
+
+ <% include('/elements/footer.html') %>
+
+% } else {
+<% $cgi->redirect(popurl(3). "view/cust_pay.html?paynum=$paynum" ) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Process payment');
+
+#some false laziness w/MyAccount::process_payment
+
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die "illegal custnum ". $cgi->param('custnum');
+my $custnum = $1;
+
+my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+die "unknown custnum $custnum" unless $cust_main;
+
+$cgi->param('amount') =~ /^\s*(\d*(\.\d\d)?)\s*$/
+ or errorpage("illegal amount ". $cgi->param('amount'));
+my $amount = $1;
+errorpage("amount <= 0") unless $amount > 0;
+
+$cgi->param('year') =~ /^(\d+)$/
+ or errorpage("illegal year ". $cgi->param('year'));
+my $year = $1;
+
+$cgi->param('month') =~ /^(\d+)$/
+ or errorpage("illegal month ". $cgi->param('month'));
+my $month = $1;
+
+$cgi->param('payby') =~ /^(CARD|CHEK)$/
+ or errorpage("illegal payby ". $cgi->param('payby'));
+my $payby = $1;
+my %payby2fields = (
+ 'CARD' => [ qw( address1 address2 city state zip ) ],
+ 'CHEK' => [ qw( ss paytype paystate stateid stateid_state ) ],
+);
+my %type = ( 'CARD' => 'credit card',
+ 'CHEK' => 'electronic check (ACH)',
+ );
+
+$cgi->param('payname') =~ /^([\w \,\.\-\']+)$/
+ or errorpage(gettext('illegal_name'). " payname: ". $cgi->param('payname'));
+my $payname = $1;
+
+$cgi->param('payunique') =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/
+ or errorpage(gettext('illegal_text'). " payunique: ". $cgi->param('payunique'));
+my $payunique = $1;
+
+$cgi->param('balance') =~ /^\s*(\-?\s*\d*(\.\d\d)?)\s*$/
+ or errorpage("illegal balance");
+my $balance = $1;
+
+my $payinfo;
+my $paycvv = '';
+if ( $payby eq 'CHEK' ) {
+
+ if ($cgi->param('payinfo1') =~ /xx/i || $cgi->param('payinfo2') =~ /xx/i ) {
+ $payinfo = $cust_main->payinfo;
+ } else {
+ $cgi->param('payinfo1') =~ /^(\d+)$/
+ or errorpage("illegal account number ". $cgi->param('payinfo1'));
+ my $payinfo1 = $1;
+ $cgi->param('payinfo2') =~ /^(\d+)$/
+ or errorpage("illegal ABA/routing number ". $cgi->param('payinfo2'));
+ my $payinfo2 = $1;
+ $payinfo = $payinfo1. '@'. $payinfo2;
+ }
+
+} elsif ( $payby eq 'CARD' ) {
+
+ $payinfo = $cgi->param('payinfo');
+ if ($payinfo eq $cust_main->paymask) {
+ $payinfo = $cust_main->payinfo;
+ }
+ $payinfo =~ s/\D//g;
+ $payinfo =~ /^(\d{13,16})$/
+ or errorpage(gettext('invalid_card')); # . ": ". $self->payinfo;
+ $payinfo = $1;
+ validate($payinfo)
+ or errorpage(gettext('invalid_card')); # . ": ". $self->payinfo;
+ errorpage(gettext('unknown_card_type'))
+ if cardtype($payinfo) eq "Unknown";
+
+ if ( defined $cust_main->dbdef_table->column('paycvv') ) {
+ if ( length($cgi->param('paycvv') ) ) {
+ if ( cardtype($payinfo) eq 'American Express card' ) {
+ $cgi->param('paycvv') =~ /^(\d{4})$/
+ or errorpage("CVV2 (CID) for American Express cards is four digits.");
+ $paycvv = $1;
+ } else {
+ $cgi->param('paycvv') =~ /^(\d{3})$/
+ or errorpage("CVV2 (CVC2/CID) is three digits.");
+ $paycvv = $1;
+ }
+ }
+ }
+
+} else {
+ die "unknown payby $payby";
+}
+
+my $error = '';
+my $paynum = '';
+if ( $cgi->param('batch') ) {
+
+ $error = $cust_main->batch_card(
+ 'payby' => $payby,
+ 'amount' => $amount,
+ 'payinfo' => $payinfo,
+ 'paydate' => "$year-$month-01",
+ 'payname' => $payname,
+ map { $_ => $cgi->param($_) }
+ @{$payby2fields{$payby}}
+ );
+ errorpage($error) if $error;
+
+} else {
+
+ $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $amount,
+ 'quiet' => 1,
+ 'manual' => 1,
+ 'balance' => $balance,
+ 'payinfo' => $payinfo,
+ 'paydate' => "$year-$month-01",
+ 'payname' => $payname,
+ 'payunique' => $payunique,
+ 'paycvv' => $paycvv,
+ 'paynum_ref' => \$paynum,
+ map { $_ => $cgi->param($_) } @{$payby2fields{$payby}}
+ );
+ errorpage($error) if $error;
+
+ $cust_main->apply_payments;
+
+}
+
+if ( $cgi->param('save') ) {
+ my $new = new FS::cust_main { $cust_main->hash };
+ if ( $payby eq 'CARD' ) {
+ $new->set( 'payby' => ( $cgi->param('auto') ? 'CARD' : 'DCRD' ) );
+ } elsif ( $payby eq 'CHEK' ) {
+ $new->set( 'payby' => ( $cgi->param('auto') ? 'CHEK' : 'DCHK' ) );
+ } else {
+ die "unknown payby $payby";
+ }
+ $new->set( 'payinfo' => $payinfo );
+ $new->set( 'paydate' => "$year-$month-01" );
+ $new->set( 'payname' => $payname );
+
+ #false laziness w/FS:;cust_main::realtime_bop - check both to make sure
+ # working correctly
+ my $conf = new FS::Conf;
+ if ( $payby eq 'CARD' &&
+ grep { $_ eq cardtype($payinfo) } $conf->config('cvv-save') ) {
+ $new->set( 'paycvv' => $paycvv );
+ } else {
+ $new->set( 'paycvv' => '');
+ }
+
+ $new->set( $_ => $cgi->param($_) ) foreach @{$payby2fields{$payby}};
+
+ my $error = $new->replace($cust_main);
+ errorpage("payment processed successfully, but error saving info: $error")
+ if $error;
+ $cust_main = $new;
+}
+
+#success!
+
+</%init>
diff --git a/httemplate/misc/process/phone_avail-import.html b/httemplate/misc/process/phone_avail-import.html
new file mode 100644
index 000000000..f1a2f2493
--- /dev/null
+++ b/httemplate/misc/process/phone_avail-import.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server = new FS::UI::Web::JSRPC 'FS::phone_avail::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/recharge_svc.html b/httemplate/misc/process/recharge_svc.html
new file mode 100755
index 000000000..147b9533a
--- /dev/null
+++ b/httemplate/misc/process/recharge_svc.html
@@ -0,0 +1,92 @@
+%unless ($error) {
+%
+% my ($amount, $seconds, $up, $down, $total) = (0, 0, 0, 0, 0);
+% #should probably use payby.pm but whatever
+% if ($payby eq 'PREP') {
+% $error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down, \$total)
+% || $svc_acct->increment_seconds($seconds)
+% || $svc_acct->increment_upbytes($up)
+% || $svc_acct->increment_downbytes($down)
+% || $svc_acct->increment_totalbytes($total)
+% || $cust_main->insert_cust_pay_prepay( $amount, $prepaid );
+% } elsif ( $payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP)$/ ) {
+% my $part_pkg = $svc_acct->cust_svc->cust_pkg->part_pkg;
+% $amount = $part_pkg->option('recharge_amount', 1);
+% my %rhash = map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_) }
+% grep { $part_pkg->option($_, 1) }
+% qw ( recharge_seconds recharge_upbytes recharge_downbytes
+% recharge_totalbytes );
+%
+% my $description = "Recharge";
+% $description .= " $rhash{seconds}s" if $rhash{seconds};
+% $description .= " $rhash{upbytes} up" if $rhash{upbytes};
+% $description .= " $rhash{downbytes} down" if $rhash{downbytes};
+% $description .= " $rhash{totalbytes} total" if $rhash{totalbytes};
+%
+% $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label,
+% $description, $part_pkg->taxclass);
+%
+% if ($part_pkg->option('recharge_reset', 1)) {
+% $error ||= $svc_acct->set_usage(\%rhash);
+% }else{
+% $error ||= $svc_acct->recharge(\%rhash);
+% }
+%
+% my $old_balance = $cust_main->balance;
+% $error ||= $cust_main->bill;
+% $error ||= $cust_main->apply_payments_and_credits;
+% my $bill_error = $cust_main->collect('realtime' => 1) unless $error;
+% $error ||= "Failed to collect - $bill_error"
+% if $cust_main->balance > $old_balance && $cust_main->balance > 0
+% && $payby ne 'BILL';
+%
+% } else {
+% $error = "fatal error - unknown payby: $payby";
+% }
+%}
+%
+%if ($error) {
+% $cgi->param('error', $error);
+% $dbh->rollback if $oldAutoCommit;
+% print $cgi->redirect(popurl(2). "recharge_svc.html?". $cgi->query_string );
+%}
+%$dbh->commit or die $dbh->errstr if $oldAutoCommit;
+%
+<% header("Package recharged") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+<%init>
+
+my $conf = new FS::Conf;
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Recharge customer service');
+
+#untaint svcnum
+my $svcnum = $cgi->param('svcnum');
+$svcnum =~ /^(\d+)$/ || die "Illegal svcnum";
+$svcnum = $1;
+
+#untaint prepaid
+my $prepaid = $cgi->param('prepaid');
+$prepaid =~ /^(\w*)$/;
+$prepaid = $1;
+
+#untaint payby
+my $payby = $cgi->param('payby');
+$payby =~ /^([A-Z]*)$/;
+$payby = $1;
+
+my $error = '';
+my $svc_acct = qsearchs( 'svc_acct', {'svcnum'=>$svcnum} );
+$error = "Can't recharge service $svcnum. " unless $svc_acct;
+
+my $cust_main = $svc_acct->cust_svc->cust_pkg->cust_main;
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+my $dbh = dbh;
+
+</%init>
diff --git a/httemplate/misc/process/recharge_svc.new b/httemplate/misc/process/recharge_svc.new
new file mode 100755
index 000000000..bc916e5da
--- /dev/null
+++ b/httemplate/misc/process/recharge_svc.new
@@ -0,0 +1,85 @@
+%
+%
+%#untaint svcnum
+%my $svcnum = $cgi->param('svcnum');
+%$svcnum =~ /^(\d+)$/ || die "Illegal svcnum";
+%$svcnum = $1;
+%
+%#untaint prepaid
+%my $prepaid = $cgi->param('prepaid');
+%$prepaid =~ /^(\w*)$/;
+%$prepaid = $1;
+
+%#untaint payby
+%my $payby = $cgi->param('payby');
+%$payby =~ /^([A-Z]*)$/;
+%$payby = $1;
+%
+%my $error = '';
+%my $svc_acct = qsearchs( 'svc_acct', {'svcnum'=>$svcnum} );
+%$error = "Can't recharge service $svcnum. " unless $svc_acct;
+%
+%my $cust_main = $svc_acct->cust_svc->cust_pkg->cust_main;
+%
+%my $oldAutoCommit = $FS::UID::AutoCommit;
+%local $FS::UID::AutoCommit = 0;
+%my $dbh = dbh;
+%
+%
+%unless ($error) {
+%
+% my ($amount, $seconds, $up, $down, $total) = (0, 0, 0, 0, 0);
+% #should probably use payby.pm but whatever
+% if ($payby eq 'PREP') {
+% $error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down, \$total)
+% || $svc_acct->increment_seconds($seconds)
+% || $svc_acct->increment_upbytes($up)
+% || $svc_acct->increment_downbytes($down)
+% || $svc_acct->increment_totalbytes($total)
+% || $cust_main->insert_cust_pay_prepay( $amount, $prepaid );
+% } elsif ( $payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP)$/ ) {
+% my $part_pkg = $svc_acct->cust_svc->cust_pkg->part_pkg;
+% $amount = $part_pkg->option('recharge_amount', 1);
+% my %rhash = map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_, 1) }
+% qw ( recharge_seconds recharge_upbytes recharge_downbytes
+% recharge_totalbytes );
+%
+% my $description = "Recharge";
+% $description .= " $rhash{seconds}s" if $rhash{seconds};
+% $description .= " $rhash{upbytes} up" if $rhash{upbytes};
+% $description .= " $rhash{downbytes} down" if $rhash{downbytes};
+% $description .= " $rhash{totalbytes} total" if $rhash{totalbytes};
+%
+% $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label,
+% $description, $part_pkg->taxclass);
+%
+% $error ||= $svc_acct->recharge(\%rhash);
+%
+% my $old_balance = $cust_main->balance;
+% $error ||= $cust_main->bill;
+% $error ||= $cust_main->apply_payments_and_credits;
+% my $bill_error = $cust_main->collect('realtime' => 1) unless $error;
+% $error ||= "Failed to collect - $bill_error"
+% if $cust_main->balance > $old_balance && $cust_main->balance > 0
+% && $payby ne 'BILL';
+%
+% } else {
+% $error = "fatal error - unknown payby: $payby";
+% }
+%}
+%
+%if ($error) {
+% $cgi->param('error', $error);
+% $dbh->rollback if $oldAutoCommit;
+% print $cgi->redirect(popurl(2). "recharge_svc.html?". $cgi->query_string );
+%}
+%$dbh->commit or die $dbh->errstr if $oldAutoCommit;
+%
+<% header("Package recharged") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+<%init>
+my $conf = new FS::Conf;
+</%init>
diff --git a/httemplate/misc/process/tax-import.cgi b/httemplate/misc/process/tax-import.cgi
new file mode 100644
index 000000000..016d4b60c
--- /dev/null
+++ b/httemplate/misc/process/tax-import.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::tax_rate::process_batch_import', $cgi;
+
+</%init>
diff --git a/httemplate/misc/process/tax-upgrade.cgi b/httemplate/misc/process/tax-upgrade.cgi
new file mode 100644
index 000000000..8782282bd
--- /dev/null
+++ b/httemplate/misc/process/tax-upgrade.cgi
@@ -0,0 +1,147 @@
+% if ( $error ) {
+% warn $error;
+% errorpage($error);
+% } else {
+ <% include('/elements/header.html','Import successful') %>
+ <% include('/elements/footer.html') %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $cfh = $cgi->upload('codefile');
+my $zfh = $cgi->upload('plus4file');
+my $tfh = $cgi->upload('txmatrix');
+my $dfh = $cgi->upload('detail');
+#warn $cgi;
+#warn $fh;
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+my $dbh = dbh;
+
+my $error = '';
+
+my ($cifh, $cdfh, $zifh, $zdfh, $tifh, $tdfh);
+
+if (defined($cfh)) {
+ $cifh = new File::Temp( TEMPLATE => 'code.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ $cdfh = new File::Temp( TEMPLATE => 'code.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ while(<$cfh>) {
+ my $fh = '';
+ $fh = $cifh if $_ =~ /"I"\s*$/;
+ $fh = $cdfh if $_ =~ /"D"\s*$/;
+ die "bad input line: $_" unless $fh;
+ print $fh $_;
+ }
+ seek $cifh, 0, 0;
+ seek $cdfh, 0, 0;
+
+}else{
+ $error = 'No code file';
+}
+
+$error ||= FS::tax_class::batch_import( {
+ filehandle => $cifh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+
+close $cifh if $cifh;
+
+if (defined($zfh)) {
+ $zifh = new File::Temp( TEMPLATE => 'plus4.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ $zdfh = new File::Temp( TEMPLATE => 'plus4.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ while(<$zfh>) {
+ my $fh = '';
+ $fh = $zifh if $_ =~ /"I"\s*$/;
+ $fh = $zdfh if $_ =~ /"D"\s*$/;
+ die "bad input line: $_" unless $fh;
+ print $fh $_;
+ }
+ seek $zifh, 0, 0;
+ seek $zdfh, 0, 0;
+
+}else{
+ $error = 'No plus4 file';
+}
+
+$error ||= FS::cust_tax_location::batch_import( {
+ filehandle => $zifh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+close $zifh if $zifh;
+
+if (defined($tfh)) {
+ $tifh = new File::Temp( TEMPLATE => 'txmatrix.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ $tdfh = new File::Temp( TEMPLATE => 'txmatrix.insert.XXXXXXXX',
+ DIR => $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc,
+ ) or die "can't open temp file: $!\n";
+
+ while(<$tfh>) {
+ my $fh = '';
+ $fh = $tifh if $_ =~ /"I"\s*$/;
+ $fh = $tdfh if $_ =~ /"D"\s*$/;
+ die "bad input line: $_" unless $fh;
+ print $fh $_;
+ }
+ seek $tifh, 0, 0;
+ seek $tdfh, 0, 0;
+
+}else{
+ $error = 'No tax matrix file';
+}
+
+$error ||= FS::part_pkg_taxrate::batch_import( {
+ filehandle => $tifh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+close $tifh if $tifh;
+
+$error ||= defined($dfh)
+ ? FS::tax_rate::batch_update( {
+ filehandle => $dfh,
+ 'format' => scalar($cgi->param('format')),
+ } )
+ : 'No tax detail file';
+
+$error ||= FS::part_pkg_taxrate::batch_import( {
+ filehandle => $tdfh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+close $tdfh if $tdfh;
+
+$error ||= FS::cust_tax_location::batch_import( {
+ filehandle => $zdfh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+close $zdfh if $zdfh;
+
+$error ||= FS::tax_class::batch_import( {
+ filehandle => $cdfh,
+ 'format' => scalar($cgi->param('format')),
+ } );
+close $cdfh if $cdfh;
+
+if ($error) {
+ $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+}else{
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+}
+
+</%init>
diff --git a/httemplate/misc/process/timeworked.html b/httemplate/misc/process/timeworked.html
new file mode 100644
index 000000000..860118e0c
--- /dev/null
+++ b/httemplate/misc/process/timeworked.html
@@ -0,0 +1,57 @@
+% if ($error) {
+<% $cgi->redirect(popurl(2). "timeworked.html?". $cgi->query_string) %>
+% } else {
+<% $cgi->redirect(popurl(3). "search/timeworked.html") %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Time queue');
+
+my @acct_rt_transaction;
+foreach my $transaction (
+ map { /^transactionid(\d+)$/; $1; } grep /^transactionid\d+$/, $cgi->param
+) {
+ my $s = "multiplier${transaction}_";
+ my %multipliers = map { /^$s(\d+)$/; $1 => $cgi->param("$s$1"); }
+ grep /^$s\d+$/, $cgi->param;
+ my $msum = 0;
+ foreach(values %multipliers) {$msum += $_};
+
+ my $seconds = $cgi->param("seconds$transaction");
+ my %seconds =
+ map { $_ => sprintf("%.0f", $seconds * $multipliers{$_} / $msum) }
+ (keys %multipliers);
+ my $sum = 0;
+ my $count = 0;
+ foreach (values %seconds) {
+ $sum += $_;
+ $count++;
+ }
+
+ #fudge in some time if we're close
+ if (abs($seconds-$sum) <= $count) {
+ my $adjustment = $seconds-$sum;
+ foreach (keys %seconds) { # explicitly choose one?
+ $seconds{$_} += $adjustment;
+ last;
+ }
+ } else {
+ die "unexpectedly cannot apportion time";
+ }
+
+ foreach my $customer ( grep {$seconds{$_}} keys %seconds ) {
+ push @acct_rt_transaction, new FS::acct_rt_transaction {
+ 'custnum' => $customer,
+ 'transaction_id' => $transaction,
+ 'seconds' => $seconds{$customer},
+ 'support' => int( $seconds{$customer} * $msum ),
+ };
+ }
+
+}
+
+my $error = FS::acct_rt_transaction->batch_insert(@acct_rt_transaction);
+$cgi->param('error', $error) if $error;
+
+</%init>
diff --git a/httemplate/misc/queue.cgi b/httemplate/misc/queue.cgi
new file mode 100644
index 000000000..5dee29b88
--- /dev/null
+++ b/httemplate/misc/queue.cgi
@@ -0,0 +1,49 @@
+<% $cgi->redirect(popurl(2). "search/queue.html") %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Job queue');
+
+$cgi->param('action') =~ /^(new|del|(retry|remove) selected)$/
+ or die "Illegal action";
+my $action = $1;
+
+my $job;
+if ( $action eq 'new' || $action eq 'del' ) {
+ $cgi->param('jobnum') =~ /^(\d+)$/ or die "Illegal jobnum";
+ my $jobnum = $1;
+ $job = qsearchs('queue', { 'jobnum' => $1 })
+ or die "unknown jobnum $jobnum - ".
+ "it probably completed normally or was removed by another user";
+}
+
+if ( $action eq 'new' ) {
+ my %hash = $job->hash;
+ $hash{'status'} = 'new';
+ $hash{'statustext'} = '';
+ my $new = new FS::queue \%hash;
+ my $error = $new->replace($job);
+ die $error if $error;
+} elsif ( $action eq 'del' ) {
+ my $error = $job->delete;
+ die $error if $error;
+} elsif ( $action =~ /^(retry|remove) selected$/ ) {
+ foreach my $jobnum (
+ map { /^jobnum(\d+)$/; $1; } grep /^jobnum\d+$/, $cgi->param
+ ) {
+ my $job = qsearchs('queue', { 'jobnum' => $jobnum });
+ if ( $action eq 'retry selected' && $job ) { #new
+ my %hash = $job->hash;
+ $hash{'status'} = 'new';
+ $hash{'statustext'} = '';
+ my $new = new FS::queue \%hash;
+ my $error = $new->replace($job);
+ die $error if $error;
+ } elsif ( $action eq 'remove selected' && $job ) { #del
+ my $error = $job->delete;
+ die $error if $error;
+ }
+ }
+}
+
+</%init>
diff --git a/httemplate/misc/recharge_svc.html b/httemplate/misc/recharge_svc.html
new file mode 100755
index 000000000..d8a8faad4
--- /dev/null
+++ b/httemplate/misc/recharge_svc.html
@@ -0,0 +1,105 @@
+<% include('/elements/header-popup.html', 'Recharge Service' ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="recharge_popup" ACTION="<% popurl(1) %>process/recharge_svc.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+
+<BR><BR>
+<% "Recharge $svcnum: $label - $value" %>
+<% ntable("#cccccc", 2) %>
+
+<SCRIPT>
+ function toggle_prep(what) {
+ if (what.value == "PREP"){
+ what.form.prepaid.disabled = false;
+ }else{
+ what.form.prepaid.disabled = true;
+ }
+ }
+</SCRIPT>
+<TR>
+ <TD><INPUT TYPE="radio" NAME="payby" onchange="toggle_prep(this)" VALUE="PREP" <% $payby eq "PREP" ? 'checked' : '' %> <% $recharge_label ? '' : 'disabled' %>></TD>
+ <TD>Prepaid Card</TD>
+% if ($recharge_label) {
+ <TD><INPUT TYPE="radio" NAME="payby" onchange="toggle_prep(this)" VALUE="<% $cust_svc->cust_pkg->cust_main->payby %>" <% $payby eq "PREP" ? '' : 'checked' %>></TD>
+ <TD><% $recharge_label %></TD>
+% }
+</TR>
+<TR>
+ <TD>Enter prepaid card: </TD>
+ <TD><INPUT TYPE="text" NAME="prepaid" VALUE="<% $prepaid |h %>" <% $payby eq "PREP" ? '' : 'disabled' %>></TD>
+</TR>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Recharge">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%once>
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Recharge customer service');
+
+my($svcnum, $prepaid, $payby);
+if ( $cgi->param('error') ) {
+ $svcnum = $cgi->param('svcnum');
+ $prepaid = $cgi->param('prepaid');
+ $payby = $cgi->param('payby');
+} elsif ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
+ $svcnum = $1;
+ $prepaid = '';
+} else {
+ die "illegal query ". $cgi->keywords;
+}
+
+my $title = 'Recharge Service';
+
+my $cust_svc = qsearchs('cust_svc', {'svcnum' => $svcnum});
+die "No such service: $svcnum" unless $cust_svc;
+
+my($label, $value) = $cust_svc->label;
+
+$payby = $cust_svc->cust_pkg->cust_main->payby unless $payby;
+my $part_pkg = $cust_svc->cust_pkg->part_pkg;
+my $amount = $part_pkg->option('recharge_amount', 1) || 0;
+
+my $recharge_label = "Charge $money_char$amount for ";
+
+$recharge_label .= $part_pkg->option('recharge_seconds', 1) . 's '
+ if $part_pkg->option('recharge_seconds', 1);
+
+
+$recharge_label .= FS::UI::bytecount::display_bytecount(
+ $part_pkg->option('recharge_upbytes', 1) )
+ . ' up '
+ if $part_pkg->option('recharge_upbytes', 1);
+
+
+$recharge_label .= FS::UI::bytecount::display_bytecount(
+ $part_pkg->option('recharge_downbytes', 1) )
+ . ' down '
+ if $part_pkg->option('recharge_downbytes', 1);
+
+
+$recharge_label .= FS::UI::bytecount::display_bytecount(
+ $part_pkg->option('recharge_totalbytes', 1) )
+ . ' total '
+ if $part_pkg->option('recharge_totalbytes', 1);
+
+
+$recharge_label = ''
+ unless ($recharge_label ne "Charge $money_char$amount for ");
+
+</%init>
+
diff --git a/httemplate/misc/spool_invoices.cgi b/httemplate/misc/spool_invoices.cgi
new file mode 100644
index 000000000..bfe24e6ea
--- /dev/null
+++ b/httemplate/misc/spool_invoices.cgi
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_respool', $cgi;
+
+</%init>
diff --git a/httemplate/misc/states.cgi b/httemplate/misc/states.cgi
new file mode 100644
index 000000000..cf2b46ee2
--- /dev/null
+++ b/httemplate/misc/states.cgi
@@ -0,0 +1,7 @@
+%
+%
+% my $country = $cgi->param('arg');
+% my @output = states_hash($country);
+%
+%
+[ <% join(', ', map { qq("$_") } @output) %> ]
diff --git a/httemplate/misc/svc_acct-domains.cgi b/httemplate/misc/svc_acct-domains.cgi
new file mode 100644
index 000000000..573457483
--- /dev/null
+++ b/httemplate/misc/svc_acct-domains.cgi
@@ -0,0 +1,31 @@
+[ <% join(', ', map { qq("$_->[0]", "$_->[1]") } @svc_domain) %> ]
+<%init>
+
+my $conf = new FS::Conf;
+
+my $pkgpart_svcpart = $cgi->param('arg');
+$pkgpart_svcpart =~ /^\d+_(\d+)$/;
+my $part_svc = qsearchs('part_svc', { 'svcpart' => $1 }) if $1;
+my $part_svc_column = $part_svc->part_svc_column('domsvc') if $part_svc;
+
+my @output = split /,/, $part_svc_column->columnvalue if $part_svc_column;
+my $columnflag = $part_svc_column->columnflag if $part_svc_column;
+my @svc_domain = ();
+my %seen = ();
+
+foreach (@output) {
+ my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $_ })
+ or warn "unknown svc_domain.svcnum $_ for part_svc_column domsvc; ".
+ "svcpart = " . $part_svc->svcpart;
+ push @svc_domain, [ $_ => $svc_domain->domain ];
+ $seen{$_}++;
+}
+if ($conf->exists('svc_acct-alldomains')
+ && ( $columnflag eq 'D' || $columnflag eq '' )
+ ) {
+ foreach (grep { $_->svcnum ne $output[0] } qsearch('svc_domain', {}) ){
+ push @svc_domain, [ $_->svcnum => $_->domain ];
+ }
+}
+
+</%init>
diff --git a/httemplate/misc/tax-import.cgi b/httemplate/misc/tax-import.cgi
new file mode 100644
index 000000000..a695e9706
--- /dev/null
+++ b/httemplate/misc/tax-import.cgi
@@ -0,0 +1,65 @@
+<% include("/elements/header.html",'Batch Tax Rate Import') %>
+
+Import a CSV file set containing tax rate records.
+<BR><BR>
+
+<% include( '/elements/form-file_upload.html',
+ 'name' => 'TaxRateUpload',
+ 'action' => 'process/tax-import.cgi',
+ 'num_files' => 5,
+ 'fields' => [ 'format', ],
+ 'message' => 'Tax rates imported',
+ )
+%>
+
+<% &ntable("#cccccc", 2) %>
+
+ <TR>
+ <TH ALIGN="right">Format</TH>
+ <TD>
+ <SELECT NAME="format">
+ <OPTION VALUE="cch-update" SELECTED>CCH update (CSV)
+ <OPTION VALUE="cch">CCH initial import (CSV)
+ <OPTION VALUE="cch-fixed-update">CCH update (fixed length)
+ <OPTION VALUE="cch-fixed">CCH initial import (fixed length)
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/file-upload.html',
+ 'field' => [ 'codefile',
+ 'plus4file',
+ 'zipfile',
+ 'txmatrix',
+ 'detail',
+ ],
+ 'label' => [ 'code filename',
+ 'plus4 filename',
+ 'zip filename',
+ 'txmatrix filename',
+ 'detail filename',
+ ],
+ 'debug' => 0,
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ VALUE = "Import CSV files"
+ onClick = "document.TaxRateUpload.submit.disabled=true;"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/misc/timeworked.html b/httemplate/misc/timeworked.html
new file mode 100755
index 000000000..db4b64ce7
--- /dev/null
+++ b/httemplate/misc/timeworked.html
@@ -0,0 +1,135 @@
+<% include('/elements/header.html', $title, '' ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="timeworked_form" ACTION="<% popurl(1) %>process/timeworked.html" METHOD=POST>
+
+<TABLE CELLSPACING="2" CELLPADDING="2" RULES="groups" FRAME="hsides">
+
+ <THEAD>
+ <TR>
+ <TH>Trans</TH>
+ <TH COLSPAN="2">Ticket</TH>
+ <TH>Time</TH>
+ <TH COLSPAN="2">Customer</TH>
+ <TH>Multiplier</TH>
+ </TR>
+
+ <TR>
+ <TH>#</TH>
+ <TH>#</TH>
+ <TH>Subject</TH>
+ <TH>hours</TH>
+ <TH>#</TH>
+ <TH>Name</TH>
+ <TH></TH>
+ </TR>
+ </THEAD>
+
+ <TBODY>
+
+% foreach my $tr_id ( keys %ticketmap ) {
+% my (@customers) = @{$customers{$ticketmap{$tr_id}}};
+% next unless @customers;
+% my $default_multiplier = sprintf("%.2f", 1/@customers);
+% my ($custnum, $name) = split(':', pop @customers, 2);
+% my $link = $p. 'rt/Ticket/Display.html?id='. $ticketmap{$tr_id}.
+% '#txn-'. $tr_id;
+
+ <TR>
+ <TD><a href="<% $link %>"><% $tr_id %></a></TD>
+ <TD><a href="<% $link %>"><% $ticketmap{$tr_id} %></a></TD>
+ <TD><a href="<% $link %>"><% $ticket{$ticketmap{$tr_id}} |h %></a></TD>
+
+% my $seconds = 0;
+% if ( $cgi->param("seconds$tr_id") =~ /^(\d+)$/ ) {
+% $seconds = $1;
+% }
+
+ <TD><% sprintf("%0.2f", $seconds/3600) %></TD>
+ <TD ALIGN="right"><% $custnum %></TD>
+ <TD ALIGN="right"><% $name %></TD>
+ <TD>
+ <INPUT TYPE="hidden" NAME="transactionid<%$tr_id%>" VALUE="1" >
+ <INPUT TYPE="hidden" NAME="seconds<%$tr_id%>" VALUE="<% $seconds %>" >
+
+% my $multiplier = $default_multiplier;
+% my $mult_paramname = "multiplier${tr_id}_$custnum";
+% if ( $cgi->param($mult_paramname) =~ /^\s*([\d\.]+)\s*$/ ) {
+% $multiplier = $1;
+% }
+
+ <INPUT TYPE="text" NAME="<% $mult_paramname %>" SIZE="5" VALUE="<% $multiplier %>" >
+ </TD>
+ </TR>
+
+% foreach ( @customers ) {
+% ($custnum, $name) = split(':', $_, 2);
+
+ <TR>
+ <TD ALIGN="right" COLSPAN="5" ><% $custnum %></TD>
+ <TD ALIGN="right"><% $name %></TD>
+ <TD>
+
+% $multiplier = $default_multiplier;
+% $mult_paramname = "multiplier${tr_id}_$custnum";
+% if ( $cgi->param($mult_paramname) =~ /^\s*([\d\.]+)\s*$/ ) {
+% $multiplier = $1;
+% }
+
+ <INPUT TYPE="text" NAME="<% $mult_paramname %>" SIZE="5" VALUE="<% $multiplier %>" >
+
+ </TD>
+
+ </TR>
+
+% }
+% }
+
+ </TBODY>
+
+</TABLE>
+
+<BR>
+
+<INPUT TYPE="submit" NAME="submit" VALUE="<% $title %>">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Time queue');
+
+my(%ticketmap, %ticket, %customers);
+my $title = 'Assign Time Worked';
+tie %ticketmap, 'Tie::IxHash';
+
+RT::Init();
+
+my $CurrentUser = RT::CurrentUser->new();
+$CurrentUser->LoadByName($FS::CurrentUser::CurrentUser->username);
+
+foreach my $id ( map { /^transactionid(\d+)$/; $1; }
+ grep /^transactionid\d+$/, $cgi->param) {
+ my $transaction = new RT::Transaction($CurrentUser);
+ $transaction->Load($id);
+ $ticketmap{$id} = $transaction->ObjectId;
+ unless(exists($ticket{$ticketmap{$id}})) {
+ my $ticket = new RT::Ticket($CurrentUser);
+ $ticket->Load($ticketmap{$id});
+ $ticket{$ticketmap{$id}} = $ticket->Subject;
+ $customers{$ticketmap{$id}} =
+ [ map { $_->Resolver->AsString }
+ grep { $_->Resolver->{'fstable'} eq 'cust_main' }
+ grep { $_->Scheme eq 'freeside' }
+ map { $_->TargetURI }
+ @{ $ticket->_Links('Base')->ItemsArrayRef }
+ ];
+
+ }
+}
+
+</%init>
+
diff --git a/httemplate/misc/unadjourn_pkg.cgi b/httemplate/misc/unadjourn_pkg.cgi
new file mode 100755
index 000000000..356b49cb3
--- /dev/null
+++ b/httemplate/misc/unadjourn_pkg.cgi
@@ -0,0 +1,17 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2). "view/cust_main.cgi?".$cust_pkg->getfield('custnum')) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Suspend customer package later');
+
+my ($pkgnum) = $cgi->keywords;
+my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+my $error = "No package $pkgnum" unless $cust_pkg;
+
+$error ||= $cust_pkg->unadjourn;
+
+</%init>
diff --git a/httemplate/misc/unapply-cust_credit.cgi b/httemplate/misc/unapply-cust_credit.cgi
new file mode 100755
index 000000000..ed739ac1b
--- /dev/null
+++ b/httemplate/misc/unapply-cust_credit.cgi
@@ -0,0 +1,20 @@
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unapply credit');
+
+#untaint crednum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal crednum";
+my $crednum = $1;
+
+my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } );
+my $custnum = $cust_credit->custnum;
+
+foreach my $cust_credit_bill ( $cust_credit->cust_credit_bill ) {
+ my $error = $cust_credit_bill->delete;
+ errorpage($error) if $error;
+}
+
+</%init>
diff --git a/httemplate/misc/unapply-cust_pay.cgi b/httemplate/misc/unapply-cust_pay.cgi
new file mode 100755
index 000000000..8cdac180b
--- /dev/null
+++ b/httemplate/misc/unapply-cust_pay.cgi
@@ -0,0 +1,20 @@
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unapply payment');
+
+#untaint paynum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal paynum";
+my $paynum = $1;
+
+my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } );
+my $custnum = $cust_pay->custnum;
+
+foreach my $cust_bill_pay ( $cust_pay->cust_bill_pay ) {
+ my $error = $cust_bill_pay->delete;
+ errorpage($error) if $error;
+}
+
+</%init>
diff --git a/httemplate/misc/unexpire_pkg.cgi b/httemplate/misc/unexpire_pkg.cgi
new file mode 100755
index 000000000..445025524
--- /dev/null
+++ b/httemplate/misc/unexpire_pkg.cgi
@@ -0,0 +1,17 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2). "view/cust_main.cgi?".$cust_pkg->getfield('custnum')) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Cancel customer package later');
+
+my ($pkgnum) = $cgi->keywords;
+my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+my $error = "No package $pkgnum" unless $cust_pkg;
+
+$error ||= $cust_pkg->unexpire;
+
+</%init>
diff --git a/httemplate/misc/unprovision.cgi b/httemplate/misc/unprovision.cgi
new file mode 100755
index 000000000..4ab15fdc0
--- /dev/null
+++ b/httemplate/misc/unprovision.cgi
@@ -0,0 +1,26 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2)."view/cust_main.cgi?$custnum") %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unprovision customer service');
+
+#untaint svcnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+
+#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
+#die "Unknown svcnum!" unless $svc_acct;
+
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "Unknown svcnum!" unless $cust_svc;
+
+my $custnum = $cust_svc->cust_pkg->custnum;
+
+my $error = $cust_svc->cancel;
+
+</%init>
diff --git a/httemplate/misc/unsusp_pkg.cgi b/httemplate/misc/unsusp_pkg.cgi
new file mode 100755
index 000000000..b350693dd
--- /dev/null
+++ b/httemplate/misc/unsusp_pkg.cgi
@@ -0,0 +1,20 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect(popurl(2). "view/cust_main.cgi?".$cust_pkg->getfield('custnum')) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unsuspend customer package');
+
+#untaint pkgnum
+my ($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal pkgnum";
+my $pkgnum = $1;
+
+my $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+
+my $error = $cust_pkg->unsuspend;
+
+</%init>
diff --git a/httemplate/misc/unvoid-cust_pay_void.cgi b/httemplate/misc/unvoid-cust_pay_void.cgi
new file mode 100755
index 000000000..91fe1c223
--- /dev/null
+++ b/httemplate/misc/unvoid-cust_pay_void.cgi
@@ -0,0 +1,21 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+%}
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Unvoid');
+
+#untaint paynum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal paynum";
+my $paynum = $1;
+
+my $cust_pay_void = qsearchs('cust_pay_void', { 'paynum' => $paynum } );
+my $custnum = $cust_pay_void->custnum;
+
+my $error = $cust_pay_void->unvoid;
+
+</%init>
diff --git a/httemplate/misc/upload-batch.cgi b/httemplate/misc/upload-batch.cgi
new file mode 100644
index 000000000..d1a84fd02
--- /dev/null
+++ b/httemplate/misc/upload-batch.cgi
@@ -0,0 +1,36 @@
+% if ( $error ) {
+% errorpage($error);
+% } else {
+ <% include('/elements/header.html','Batch results upload successful') %>
+ <% include('/elements/footer.html') %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Process batches');
+
+my $error;
+
+my $fh = $cgi->upload('batch_results');
+$error = 'No file uploaded' unless defined($fh);
+
+unless ( $error ) {
+
+ $cgi->param('batchnum') =~ /^(\d+)$/;
+ my $batchnum = $1;
+
+ my $pay_batch = qsearchs( 'pay_batch', { 'batchnum' => $batchnum } );
+ if ( ! $pay_batch ) {
+ $error = "batchnum $batchnum not found";
+ } elsif ( $pay_batch->status ne 'I' ) {
+ $error = "batch $batchnum is not in transit";
+ } else {
+ $error = $pay_batch->import_results(
+ 'filehandle' => $fh,
+ 'format' => $cgi->param('format'),
+ );
+ }
+
+}
+
+</%init>
diff --git a/httemplate/misc/void-cust_pay.cgi b/httemplate/misc/void-cust_pay.cgi
new file mode 100755
index 000000000..7b484e93e
--- /dev/null
+++ b/httemplate/misc/void-cust_pay.cgi
@@ -0,0 +1,26 @@
+%if ( $error ) {
+% errorpage($error);
+%} else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+%}
+<%init>
+
+#untaint paynum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal paynum";
+my $paynum = $1;
+
+my $cust_pay = qsearchs('cust_pay',{'paynum'=>$paynum});
+
+my $right = 'Regular void';
+$right = 'Credit card void' if $cust_pay->payby eq 'CARD';
+$right = 'Echeck void' if $cust_pay->payby eq 'CHEK';
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right($right);
+
+my $custnum = $cust_pay->custnum;
+
+my $error = $cust_pay->void;
+
+</%init>
diff --git a/httemplate/misc/whois.cgi b/httemplate/misc/whois.cgi
new file mode 100644
index 000000000..533b2d7a8
--- /dev/null
+++ b/httemplate/misc/whois.cgi
@@ -0,0 +1,33 @@
+<% include("/elements/header.html","Whois $domain", menubar(
+ ( $custnum
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ()
+ ),
+ "View this domain (#$svcnum)" => "${p}view/svc_domain.cgi?$svcnum",
+)) %>
+
+<PRE><% $whois %></PRE>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+my $svcnum = $cgi->param('svcnum');
+my $custnum = $cgi->param('custnum');
+my $domain = $cgi->param('domain');
+
+my $display_custnum;
+if ( $custnum ) {
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
+ $display_custnum = $cust_main->display_custnum;
+}
+
+my $whois = eval { whois($domain) };
+ if ( $@ ) {
+ ( $whois = $@ ) =~ s/ at \/.*Net\/Whois\/Raw\.pm line \d+.*$//s;
+ } else {
+ $whois =~ s/^\n+//;
+ }
+
+</%init>
diff --git a/httemplate/misc/xmlhttp-cust_main-address_standardize.html b/httemplate/misc/xmlhttp-cust_main-address_standardize.html
new file mode 100644
index 000000000..72fa4a464
--- /dev/null
+++ b/httemplate/misc/xmlhttp-cust_main-address_standardize.html
@@ -0,0 +1,89 @@
+<% objToJson($return) %>
+<%init>
+
+my $DEBUG = 0;
+
+my $conf = new FS::Conf;
+
+my $sub = $cgi->param('sub');
+
+my $return = {};
+
+if ( $sub eq 'address_standardize' ) {
+
+ my %arg = $cgi->param('arg');
+ $return = \%arg;
+ warn join('', map "$_: $arg{$_}\n", keys %arg )
+ if $DEBUG;
+
+ my $userid = $conf->config('usps_webtools-userid');
+ my $password = $conf->config('usps_webtools-password');
+
+ if ( length($userid) && length($password) ) {
+
+ my $verifier = Business::US::USPS::WebTools::AddressStandardization->new( {
+ UserID => $userid, #$ENV{USPS_WEBTOOLS_USERID},
+ Password => $password, #$ENV{USPS_WEBTOOLS_PASSWORD},
+ #Testing => 1,
+ } );
+
+ foreach my $pre ( '', 'ship_' ) {
+
+ my($zip5, $zip4) = split('-',$arg{$pre.'zip'});
+
+ my %usps_args = (
+ FirmName => $arg{$pre.'company'},
+ Address2 => $arg{$pre.'address1'},
+ Address1 => $arg{$pre.'address2'},
+ City => $arg{$pre.'city'},
+ State => $arg{$pre.'state'},
+ Zip5 => $zip5,
+ Zip4 => $zip4,
+ );
+ warn join('', map "$_: $usps_args{$_}\n", keys %usps_args )
+ if $DEBUG;
+
+ my $hash = $verifier->verify_address( %usps_args );
+
+ warn $verifier->response
+ if $DEBUG;
+
+ unless ( $verifier->is_error ) {
+
+ $return = {
+ %$return,
+ "new_$pre".'company' => $hash->{FirmName},
+ "new_$pre".'address1' => $hash->{Address2},
+ "new_$pre".'address2' => $hash->{Address1},
+ "new_$pre".'city' => $hash->{City},
+ "new_$pre".'state' => $hash->{State},
+ "new_$pre".'zip' => $hash->{Zip5}. '-'. $hash->{Zip4},
+ };
+
+ my @fields = (qw( company address1 address2 city state zip )); #hmm
+
+ my $changed =
+ scalar( grep { $return->{$pre.$_} ne $return->{"new_$pre$_"} }
+ @fields
+ )
+ ? 1 : 0;
+
+ $return->{$pre.'address_standardized'} = $changed;
+
+ } else {
+
+ $return->{$pre.'error'} = "USPS WebTools error: ".
+ $verifier->{error}{description};
+
+
+ }
+
+ }
+
+ }
+
+ $return;
+
+}
+
+</%init>
diff --git a/httemplate/misc/xmlhttp-cust_main-search.cgi b/httemplate/misc/xmlhttp-cust_main-search.cgi
new file mode 100644
index 000000000..26e68b5d8
--- /dev/null
+++ b/httemplate/misc/xmlhttp-cust_main-search.cgi
@@ -0,0 +1,36 @@
+% if ( $sub eq 'custnum_search' ) {
+%
+% my $custnum = $cgi->param('arg');
+% my $cust_main = '';
+% if ( $custnum <= 2147483647 ) {
+% $cust_main = qsearchs({
+% 'table' => 'cust_main',
+% 'hashref' => { 'custnum' => $custnum },
+% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+% });
+% }
+% if ( ! $cust_main ) {
+% $cust_main = qsearchs({
+% 'table' => 'cust_main',
+% 'hashref' => { 'agent_custid' => $custnum },
+% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+% });
+% }
+%
+"<% $cust_main ? $cust_main->name : '' %>"
+%
+% } elsif ( $sub eq 'smart_search' ) {
+%
+% my $string = $cgi->param('arg');
+% my @cust_main = smart_search( 'search' => $string );
+% my $return = [ map [ $_->custnum, $_->name ], @cust_main ];
+%
+<% objToJson($return) %>
+% }
+<%init>
+
+my $conf = new FS::Conf;
+
+my $sub = $cgi->param('sub');
+
+</%init>
diff --git a/httemplate/misc/xmlrpc.cgi b/httemplate/misc/xmlrpc.cgi
new file mode 100644
index 000000000..1d0383f2a
--- /dev/null
+++ b/httemplate/misc/xmlrpc.cgi
@@ -0,0 +1,18 @@
+%
+%
+% my $request_xml = $cgi->param('POSTDATA');
+%
+% #$r->log_error($request_xml);
+%
+% my $fsxmlrpc = new FS::XMLRPC;
+% my ($error, $response_xml) = $fsxmlrpc->serve($request_xml);
+%
+% #$r->log_error($error) if $error;
+%
+% http_header('Content-Type' => 'text/xml',
+% 'Content-Length' => length($response_xml));
+%
+% print $response_xml;
+%
+%
+
diff --git a/httemplate/pref/pref-process.html b/httemplate/pref/pref-process.html
new file mode 100644
index 000000000..96615169b
--- /dev/null
+++ b/httemplate/pref/pref-process.html
@@ -0,0 +1,58 @@
+% my $error = '';
+%
+% my $access_user;
+% if ( grep { $cgi->param($_) !~ /^\s*$/ }
+% qw(_password new_password new_password2)
+% ) {
+%
+% $access_user = qsearchs( 'access_user', {
+% 'username' => getotaker,
+% '_password' => $cgi->param('_password'),
+% } );
+%
+% $error = 'Current password incorrect; password not changed'
+% unless $access_user;
+%
+% $error ||= "New passwords don't match"
+% unless $cgi->param('new_password') eq $cgi->param('new_password2');
+%
+% $error ||= "No new password entered"
+% unless length($cgi->param('new_password'));
+%
+% $access_user->_password($cgi->param('new_password')) unless $error;
+%
+% } else {
+%
+% $access_user = $FS::CurrentUser::CurrentUser;
+%
+% }
+%
+% my %param = $access_user->options;
+%
+% #XXX autogen
+% my @paramlist = qw( menu_position
+% email_address
+% vonage-fromnumber vonage-username vonage-password
+% show_pkgnum show_db_profile save_db_profile
+% height width availHeight availWidth colorDepth
+% );
+%
+% foreach (@paramlist) {
+% scalar($cgi->param($_)) =~ /^[,.\-\@\w]*$/ && next;
+% $error ||= "Illegal value for parameter $_";
+% last;
+% }
+%
+% foreach (@paramlist) {
+% $param{$_} = scalar($cgi->param($_));
+% }
+%
+% $error ||= $access_user->replace( \%param );
+%
+% if ( $error ) {
+% $cgi->param('error', $error);
+% print $cgi->redirect(popurl(1). "pref.html?". $cgi->query_string );
+% } else {
+<% include('/elements/header.html', 'Preferences updated') %>
+<% include('/elements/footer.html') %>
+% }
diff --git a/httemplate/pref/pref.html b/httemplate/pref/pref.html
new file mode 100644
index 000000000..57e22b345
--- /dev/null
+++ b/httemplate/pref/pref.html
@@ -0,0 +1,124 @@
+<% include('/elements/header.html', 'Preferences for '. getotaker ) %>
+
+<FORM METHOD="POST" NAME="pref_form" ACTION="pref-process.html">
+
+<% include('/elements/error.html') %>
+
+
+Change password (leave blank for no change)
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TH ALIGN="right">Current password: </TH>
+ <TD><INPUT TYPE="password" NAME="_password"></TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">New password: </TH>
+ <TD><INPUT TYPE="password" NAME="new_password"></TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Re-enter new password: </TH>
+ <TD><INPUT TYPE="password" NAME="new_password2"></TD>
+ </TR>
+
+</TABLE>
+<BR>
+
+
+Interface
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TH>Menu location: </TH>
+ <TD>
+ <INPUT TYPE="radio" NAME="menu_position" VALUE="left" onClick="document.images['menu_example'].src='../images/menu-left-example.png';" <% $menu_position eq 'left' ? ' CHECKED' : ''%>> Left<BR>
+ <INPUT TYPE="radio" NAME="menu_position" VALUE="top"onClick="document.images['menu_example'].src='../images/menu-top-example.png';" <% $menu_position eq 'top' ? ' CHECKED' : ''%>> Top <BR>
+ </TD>
+ <TD><IMG NAME="menu_example" SRC="../images/menu-<% $menu_position %>-example.png"></TD>
+ </TR>
+
+</TABLE>
+<BR>
+
+
+Email Address
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TH>Email Address(es) (comma separated) </TH>
+ <TD>
+ <TD><INPUT TYPE="text" NAME="email_address" VALUE="<% $email_address %>">
+ </TD>
+ </TR>
+
+</TABLE>
+<BR>
+
+
+Development
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TH>Show internal package numbers: </TH>
+ <TD><INPUT TYPE="checkbox" NAME="show_pkgnum" VALUE="1" <% $curuser->option('show_pkgnum') ? 'CHECKED' : '' %>></TD>
+ </TR>
+ <TR>
+ <TH>Show database profiling (when available): </TH>
+ <TD><INPUT TYPE="checkbox" NAME="show_db_profile" VALUE="1" <% $curuser->option('show_db_profile') ? 'CHECKED' : '' %>></TD>
+ </TR>
+ <TR>
+ <TH>Save database profiling logs (when available): </TH>
+ <TD><INPUT TYPE="checkbox" NAME="save_db_profile" VALUE="1" <% $curuser->option('save_db_profile') ? 'CHECKED' : '' %>></TD>
+ </TR>
+
+</TABLE>
+<BR>
+
+
+Vonage integration (see <a href="https://secure.click2callu.com/">Click2Call</a>)
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TH ALIGN="right">Vonage phone number</TH>
+ <TD><INPUT TYPE="text" NAME="vonage-fromnumber" VALUE="<% $curuser->option('vonage-fromnumber') %>"></TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Vonage username</TH>
+ <TD><INPUT TYPE="text" NAME="vonage-username" VALUE="<% $curuser->option('vonage-username') %>"></TD>
+ </TR>
+
+ <TR>
+ <TH ALIGN="right">Vonage password</TH>
+ <TD><INPUT TYPE="password" NAME="vonage-password" VALUE="<% $curuser->option('vonage-password') %>"></TD>
+ </TR>
+
+</TABLE>
+<BR>
+
+
+% foreach my $prop (qw( height width availHeight availWidth colorDepth )) {
+ <INPUT TYPE="hidden" NAME="<% $prop %>" VALUE="">
+ <SCRIPT TYPE="text/javascript">
+ document.pref_form.<% $prop %>.value = screen.<% $prop %>;
+ </script>
+% }
+
+<INPUT TYPE="submit" VALUE="Update preferences">
+
+<% include('/elements/footer.html') %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+# XSS via your own preferences? seems unlikely, but nice try anyway...
+( $curuser->option('menu_position') || 'left' )
+ =~ /^(\w+)$/ or die "illegal menu_position";
+my $menu_position = $1;
+( $curuser->option('email_address') )
+ =~ /^([,\w\@.]*)$/ or die "illegal email_address"; #too late
+my $email_address = $1;
+
+</%init>
diff --git a/httemplate/search/cdr.html b/httemplate/search/cdr.html
new file mode 100644
index 000000000..852eebadb
--- /dev/null
+++ b/httemplate/search/cdr.html
@@ -0,0 +1,159 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name' => 'call detail records',
+
+ 'query' => { 'table' => 'cdr',
+ 'hashref' => $hashref,
+ 'extra_sql' => $qsearch,
+ 'order_by' => 'ORDER BY calldate',
+ },
+ 'count_query' => $count_query,
+ 'header' => [
+ '', # checkbox column
+ fields('cdr'), #XXX fill in some nice names
+ ],
+ 'fields' => [
+ sub {
+ return '' unless $edit_data;
+ $areboxes = 1;
+ my $cdr = shift;
+ my $acctid = $cdr->acctid;
+ qq!<INPUT NAME="acctid$acctid" TYPE="checkbox" VALUE="1">!;
+ },
+ fields('cdr'), #XXX fill in some pretty-print
+ #processing, etc.
+ ],
+
+ 'html_form' => qq!<FORM NAME="cdrForm" ACTION="$p/misc/cdr.cgi" METHOD="POST">!,
+ #false laziness w/queue.html
+ 'html_foot' => sub {
+ if ( $areboxes ) {
+ '<BR><INPUT TYPE="button" VALUE="select all" onClick="setAll(true)">'.
+ '<INPUT TYPE="button" VALUE="unselect all" onClick="setAll(false)">'.
+ qq!<BR><INPUT TYPE="submit" NAME="action" VALUE="reprocess selected" onClick="return confirm('Are you sure you want to reprocess the selected CDRs?')">!.
+ qq!<INPUT TYPE="submit" NAME="action" VALUE="delete selected" onClick="return confirm('Are you sure you want to delete the selected CDRs?')"><BR>!.
+ '<SCRIPT TYPE="text/javascript">'.
+ ' function setAll(setTo) { '.
+ ' theForm = document.cdrForm;'.
+ ' for (i=0,n=theForm.elements.length;i<n;i++)'.
+ ' if (theForm.elements[i].name.indexOf("acctid") != -1)'.
+ ' theForm.elements[i].checked = setTo;'.
+ ' }'.
+ '</SCRIPT>';
+ } else {
+ '';
+ }
+ },
+
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+my $edit_data = $FS::CurrentUser::CurrentUser->access_right('Edit rating data');
+
+my $areboxes = 0;
+
+my $title = 'Call Detail Records';
+my $hashref = {};
+
+#process params for CDR search, populate $hashref...
+# and fixup $count_query
+
+my @search = ();
+
+###
+# freesidestatus
+###
+
+if ( $cgi->param('freesidestatus') eq 'NULL' ) {
+
+ my $title = "Unprocessed $title";
+ $hashref->{'freesidestatus'} = ''; # Record.pm will take care of it
+ push @search, "( freesidestatus IS NULL OR freesidestatus = '' )";
+
+} elsif ( $cgi->param('freesidestatus') =~ /^([\w ]+)$/ ) {
+
+ my $title = "Processed $title";
+ $hashref->{'freesidestatus'} = $1;
+ push @search, "freesidestatus = '$1'";
+
+}
+
+###
+# dates
+###
+
+my $str2time_sql = str2time_sql;
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "$str2time_sql calldate) >= $beginning ",
+ "$str2time_sql calldate) <= $ending";
+
+###
+# duration / billsec
+###
+
+push @search, FS::UI::Web::parse_lt_gt($cgi, 'duration');
+push @search, FS::UI::Web::parse_lt_gt($cgi, 'billsec');
+
+###
+# src/dest/charged_party
+###
+
+my @qsearch = @search;
+
+if ( $cgi->param('src') =~ /^\s*([\d\-\+\ ]+)\s*$/ ) {
+ ( my $src = $1 ) =~ s/\D//g;
+ $hashref->{'src'} = $src;
+ push @search, "src = '$src'";
+}
+
+if ( $cgi->param('dst') =~ /^\s*([\d\-\+ ]+)\s*$/ ) {
+ ( my $dst = $1 ) =~ s/\D//g;
+ $hashref->{'dst'} = $dst;
+ push @search, "dst = '$dst'";
+}
+
+if ( $cgi->param('charged_party') =~ /^\s*([\d\-\+\ ]+)\s*$/ ) {
+ ( my $charged_party = $1 ) =~ s/\D//g;
+ #$hashref->{'charged_party'} = $charged_party;
+ #push @search, "charged_party = '$charged_party'";
+ #XXX countrycode
+ push @search, " ( charged_party = '$charged_party'
+ OR charged_party = '1$charged_party' ) ";
+ push @qsearch, " ( charged_party = '$charged_party'
+ OR charged_party = '1$charged_party' ) ";
+}
+
+###
+# cdrbatch
+###
+
+if ( $cgi->param('cdrbatch') ne '__ALL__' ) {
+ if ( $cgi->param('cdrbatch') eq '' ) {
+ my $search = "( cdrbatch IS NULL OR cdrbatch = '' )";
+ push @qsearch, $search;
+ push @search, $search;
+ } else {
+ $hashref->{cdrbatch} = $cgi->param('cdrbatch');
+ push @search, 'cdrbatch = '. dbh->quote($cgi->param('cdrbatch'));
+ }
+}
+
+###
+# finish it up
+###
+
+my $search = join(' AND ', @search);
+$search = "WHERE $search" if $search;
+
+my $count_query = "SELECT COUNT(*) FROM cdr $search";
+
+my $qsearch = join(' AND ', @qsearch);
+$qsearch = ( scalar(keys %$hashref) ? ' AND ' : ' WHERE ' ) . $qsearch
+ if $qsearch;
+
+</%init>
diff --git a/httemplate/search/cust_bill.html b/httemplate/search/cust_bill.html
new file mode 100755
index 000000000..6f440db7e
--- /dev/null
+++ b/httemplate/search/cust_bill.html
@@ -0,0 +1,251 @@
+<% include( 'elements/search.html',
+ 'title' => 'Invoice Search Results',
+ 'html_init' => $html_init,
+ 'menubar' => $menubar,
+ 'name' => 'invoices',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => $count_addl,
+ 'redirect' => $link,
+ 'header' => [ 'Invoice #',
+ 'Balance',
+ 'Net Amount',
+ 'Gross Amount',
+ 'Date',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'invnum',
+ sub { sprintf($money_char.'%.2f', shift->get('owed') ) },
+ sub { sprintf($money_char.'%.2f', shift->get('net') ) },
+ sub { sprintf($money_char.'%.2f', shift->charged ) },
+ sub { time2str('%b %d %Y', shift->_date ) },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'rrrr'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ $link,
+ $link,
+ $link,
+ $link,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+
+
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List invoices');
+
+my $join_cust_main = 'LEFT JOIN cust_main USING ( custnum )';
+#here is the agent virtualization
+my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my( $count_query, $sql_query );
+my $count_addl = '';
+#my $distinct = '';
+my %search;
+
+if ( $cgi->param('invnum') =~ /^\s*(FS-)?(\d+)\s*$/ ) {
+
+ $count_query =
+ "SELECT COUNT(*) FROM cust_bill $join_cust_main".
+ " WHERE invnum = $2 AND $agentnums_sql"; #agent virtualization
+ $sql_query = {
+ 'table' => 'cust_bill',
+ 'addl_from' => $join_cust_main,
+ 'hashref' => { 'invnum' => $2 },
+ #'select' => '*',
+ 'extra_sql' => " AND $agentnums_sql", #agent virtualization
+ };
+
+} else {
+
+ #some false laziness w/cust_bill::re_X
+ my @where;
+ my $orderby = 'ORDER BY cust_bill._date';
+
+ if ( $cgi->param('beginning')
+ && $cgi->param('beginning') =~ /^([ 0-9\-\/]{0,10})$/ ) {
+ $search{'begin'} = str2time($1);
+ }
+ if ( $cgi->param('ending')
+ && $cgi->param('ending') =~ /^([ 0-9\-\/]{0,10})$/ ) {
+ $search{'end'} = str2time($1) + 86399;
+ }
+
+ if ( $cgi->param('begin') =~ /^(\d+)$/ ) {
+ $search{'begin'} = $1;
+ }
+ if ( $cgi->param('end') =~ /^(\d+)$/ ) {
+ $search{'end'} = $1;
+ }
+
+ if ( $cgi->param('invnum_min') =~ /^\s*(\d+)\s*$/ ) {
+ $search{'invnum_min'} = $1;
+ }
+ if ( $cgi->param('invnum_max') =~ /^\s*(\d+)\s*$/ ) {
+ $search{'invnum_max'} = $1;
+ }
+
+ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $search{'agentnum'} = $1;
+ }
+
+ $search{'open'} = 1 if $cgi->param('open');
+ $search{'net'} = 1 if $cgi->param('net' );
+
+ my($query) = $cgi->keywords;
+ if ( $query =~ /^(OPEN(\d*)_)?(invnum|date|custnum)$/ ) {
+ $search{'open'} = 1 if $1;
+ ($search{'days'}, my $field) = ($2, $3);
+ $field = "_date" if $field eq 'date';
+ $orderby = "ORDER BY cust_bill.$field";
+ }
+
+ if ( $cgi->param('newest_percust') ) {
+ $search{'newest_percust'} = 1;
+ $count_query = "SELECT COUNT(DISTINCT cust_bill.custnum), 'N/A', 'N/A'";
+ }
+
+ my $extra_sql = ' WHERE '. FS::cust_bill->search_sql( \%search );
+
+ unless ( $count_query ) {
+ $count_query = 'SELECT COUNT(*), '. join(', ',
+ map "SUM($_)",
+ ( 'charged',
+ FS::cust_bill->net_sql,
+ FS::cust_bill->owed_sql,
+ )
+ );
+ $count_addl = [ '$%.2f invoiced (gross)',
+ '$%.2f invoiced (net)',
+ '$%.2f outstanding balance',
+ ];
+ }
+ $count_query .= " FROM cust_bill $join_cust_main $extra_sql";
+
+ $sql_query = {
+ 'table' => 'cust_bill',
+ 'addl_from' => $join_cust_main,
+ 'hashref' => {},
+ #'select' => "$distinct ". join(', ',
+ 'select' => join(', ',
+ 'cust_bill.*',
+ #( map "cust_main.$_", qw(custnum last first company) ),
+ 'cust_main.custnum as cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ FS::cust_bill->owed_sql. ' AS owed',
+ FS::cust_bill->net_sql. ' AS net',
+ ),
+ 'extra_sql' => $extra_sql,
+ 'order_by' => $orderby,
+ };
+
+}
+
+my $link = [ "${p}view/cust_bill.cgi?", 'invnum', ];
+my $clink = sub {
+ my $cust_bill = shift;
+ $cust_bill->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+ : '';
+};
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $html_init = join("\n", map {
+ ( my $action = $_ ) =~ s/_$//;
+ include('/elements/progress-init.html',
+ $_.'form',
+ [ keys %search ],
+ "../misc/${_}invoices.cgi",
+ { 'message' => "Invoices re-${action}ed" }, #would be nice to show the number of them, but...
+ $_, #key
+ ),
+ qq!<FORM NAME="${_}form">!,
+ ( map qq!<INPUT TYPE="hidden" NAME="$_" VALUE="$search{$_}">!, keys %search ),
+ qq!</FORM>!
+} qw( print_ email_ fax_ ftp_ spool_ ) ).
+
+'<SCRIPT TYPE="text/javascript">
+
+function confirm_print_process() {
+ if ( ! confirm("Are you sure you want to reprint these invoices?") ) {
+ return;
+ }
+ print_process();
+}
+function confirm_email_process() {
+ if ( ! confirm("Are you sure you want to re-email these invoices?") ) {
+ return;
+ }
+ email_process();
+}
+function confirm_fax_process() {
+ if ( ! confirm("Are you sure you want to re-fax these invoices?") ) {
+ return;
+ }
+ fax_process();
+}
+function confirm_ftp_process() {
+ if ( ! confirm("Are you sure you want to re-FTP these invoices?") ) {
+ return;
+ }
+ ftp_process();
+}
+function confirm_spool_process() {
+ if ( ! confirm("Are you sure you want to re-spool these invoices?") ) {
+ return;
+ }
+ spool_process();
+}
+
+</SCRIPT>';
+
+my $menubar = [];
+
+if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
+
+ push @$menubar, 'Print these invoices' =>
+ "javascript:confirm_print_process()",
+ 'Email these invoices' =>
+ "javascript:confirm_email_process()";
+
+ push @$menubar, 'Fax these invoices' =>
+ "javascript:confirm_fax_process()"
+ if $conf->exists('hylafax');
+
+ push @$menubar, 'FTP these invoices' =>
+ "javascript:confirm_ftp_process()"
+ if $conf->exists('cust_bill-ftpformat');
+
+ push @$menubar, 'Spool these invoices' =>
+ "javascript:confirm_spool_process()"
+ if $conf->exists('cust_bill-spoolformat');
+
+}
+
+</%init>
diff --git a/httemplate/search/cust_bill_event.cgi b/httemplate/search/cust_bill_event.cgi
new file mode 100644
index 000000000..ff4168d6d
--- /dev/null
+++ b/httemplate/search/cust_bill_event.cgi
@@ -0,0 +1,166 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'html_init' => $html_init,
+ 'menubar' => $menubar,
+ 'name' => 'billing events',
+ 'query' => $sql_query,
+ 'count_query' => $count_sql,
+ 'header' => [ 'Event',
+ 'Date',
+ 'Status',
+ #'Inv #', 'Inv Date', 'Cust #',
+ 'Invoice',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'event',
+ sub { time2str("%b %d %Y %T", $_[0]->_date) },
+ sub {
+ #my $cust_bill_event = shift;
+ my $status = $_[0]->status;
+ $status .= ': '.$_[0]->statustext
+ if $_[0]->statustext;
+ $status;
+ },
+ sub {
+ #my $cust_bill_event = shift;
+ 'Invoice #'. $_[0]->invnum.
+ ' ('.
+ time2str("%D", $_[0]->cust_bill_date).
+ ')';
+ },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'lrlr'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ '',
+ sub {
+ my $part_bill_event = shift;
+ my $template = $part_bill_event->templatename;
+ $template .= '-' if $template;
+ [ "${p}view/cust_bill.cgi?$template", 'invnum'];
+ },
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Billing event reports')
+ or $curuser->access_right('View customer billing events')
+ && $cgi->param('invnum') =~ /^(\d+)$/;
+
+my $title = $cgi->param('failed')
+ ? 'Failed invoice events'
+ : 'Invoice events';
+
+my %search = ();
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $search{agentnum} = $1;
+}
+
+($search{beginning}, $search{ending})
+ = FS::UI::Web::parse_beginning_ending($cgi);
+
+if ( $cgi->param('failed') ) {
+ $search{failed} = '1';
+}
+
+if ( $cgi->param('part_bill_event.payby') =~ /^(\w+)$/ ) {
+ $search{payby} = $1;
+}
+
+if ( $cgi->param('invnum') =~ /^(\d+)$/ ) {
+ $search{invnum} = $1;
+}
+
+my $where = 'WHERE '. FS::cust_bill_event->search_sql( \%search );
+
+my $join = 'LEFT JOIN part_bill_event USING ( eventpart ) '.
+ 'LEFT JOIN cust_bill USING ( invnum ) '.
+ 'LEFT JOIN cust_main USING ( custnum ) ';
+
+my $sql_query = {
+ 'table' => 'cust_bill_event',
+ 'select' => join(', ',
+ 'cust_bill_event.*',
+ 'part_bill_event.event',
+ 'cust_bill.custnum',
+ 'cust_bill._date AS cust_bill_date',
+ 'cust_main.custnum AS cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => "$where ORDER BY _date ASC",
+ 'addl_from' => $join,
+};
+
+my $count_sql = "SELECT COUNT(*) FROM cust_bill_event $join $where";
+
+my $conf = new FS::Conf;
+
+my $html_init = '
+ <FONT SIZE="+1">Invoice events are the deprecated, old-style actions taken o
+n open invoices. See Reports-&gt;Billing events-&gt;Billing events for current event reports.</FONT><BR><BR>';
+
+$html_init .= join("\n", map {
+ ( my $action = $_ ) =~ s/_$//;
+ include('/elements/progress-init.html',
+ $_.'form',
+ [ keys(%search) ],
+ "../misc/${_}invoice_events.cgi",
+ { 'message' => "Invoices re-${action}ed" }, #would be nice to show the number of them, but...
+ $_, #key
+ ),
+ qq!<FORM NAME="${_}form">!,
+ qq!<INPUT TYPE="hidden" NAME="action" VALUE="$_">!, #not used though
+ (map {qq!<INPUT TYPE="hidden" NAME="$_" VALUE="$search{$_}">!} keys(%search)),
+ qq!</FORM>!
+} qw( print_ email_ fax_ ) );
+
+my $menubar = [];
+
+if ( $curuser->access_right('Resend invoices') ) {
+
+ push @$menubar, 'Re-print these events' =>
+ "javascript:print_process()",
+ 'Re-email these events' =>
+ "javascript:email_process()",
+ ;
+
+ push @$menubar, 'Re-fax these events' =>
+ "javascript:fax_process()"
+ if $conf->exists('hylafax');
+
+}
+
+my $link_cust = sub {
+ my $cust_bill_event = shift;
+ $cust_bill_event->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/cust_bill_event.html b/httemplate/search/cust_bill_event.html
new file mode 100755
index 000000000..0f84a5581
--- /dev/null
+++ b/httemplate/search/cust_bill_event.html
@@ -0,0 +1,67 @@
+<% include(
+ '/elements/header.html',
+ ( $cgi->param('failed') ? 'Failed invoice events' : 'Invoice events' ),
+ )
+%>
+
+ <FONT SIZE="+1">Invoice events are the deprecated, old-style actions taken
+ on open invoices. See Reports-&gt;Billing events-&gt;Billing events for current event reports.</FONT><BR><BR>
+
+ <FORM ACTION="cust_bill_event.cgi" METHOD="GET">
+ <INPUT TYPE="hidden" NAME="failed" VALUE="<% $cgi->param('failed') ? 1 : 0 %>">
+ <TABLE>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <!--<TR>
+ <TD ALIGN="right">Customer type</TD>
+ <TD><SELECT MULTIPLE NAME="perhaps_payby">
+ <OPTION SELECTED VALUE="CARD">Credit card (automatic)
+ <OPTION SELECTED VALUE="CHEK">E-check (automatic)
+ <OPTION SELECTED VALUE="LECB">Phone bill billing
+ <OPTION SELECTED VALUE="BILL">Billing
+ <OPTION SELECTED VALUE="DCRD">Credit card (on-demand)
+ <OPTION SELECTED VALUE="DCHK">E-check (on-demand)
+ </TD>
+ </TR>
+ -->
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+ <!--
+ <TR>
+ <TD ALIGN="right">Events: </TD>
+ <TD>
+ <SELECT NAME="eventpart">
+ <OPTION SELECTED VALUE=""><% $cgi->param('failed') ? '(all failed events)' : '(all events)' %>
+% #foreach my $part_bill_event ( qsearch( 'part_bill_event', {} ) ) {
+% #}
+
+ </SELECT>
+ </TD>
+ </TR>
+ -->
+ <TR>
+ <TD ALIGN="right">Events for payment type: </TD>
+ <TD>
+ <SELECT NAME="part_bill_event.payby">
+ <OPTION SELECTED VALUE="">(all)
+ <OPTION VALUE="CARD">Credit card (automatic)
+ <OPTION VALUE="BILL">Billing
+ <OPTION VALUE="CHEK">Electronic check (automatic)
+ <OPTION VALUE="DCRD">Credit card (on-demand)
+ <OPTION VALUE="DCHK">Electronic check (on-demand)
+ <OPTION VALUE="LECB">Phone bill billing
+ <OPTION VALUE="COMP">Complimentary
+ </SELECT>
+ </TD>
+ </TR>
+ </TABLE>
+ <BR><INPUT TYPE="submit" VALUE="Get Report">
+ </FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Billing event reports');
+
+</%init>
diff --git a/httemplate/search/cust_bill_pay.html b/httemplate/search/cust_bill_pay.html
new file mode 100644
index 000000000..3c390e706
--- /dev/null
+++ b/httemplate/search/cust_bill_pay.html
@@ -0,0 +1,131 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name' => 'net payments',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ '$%.2f total paid (net)', ],
+ 'header' => [ 'Net applied',
+ 'to Invoice',
+ 'Payment',
+ 'By',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ sub { $money_char. sprintf('%.2f', shift->amount ) },
+ sub { my $cbp = shift;
+ '#'.$cbp->invnum. ' '.
+ time2str('%b %d %Y', $cbp->cust_bill_date ).
+ " ($money_char".
+ sprintf('%.2f', $cbp->cust_bill_amount).
+ ")"
+ },
+ sub { my $cbp = shift;
+ $cbp->cust_pay->payby_payinfo_pretty. ' '.
+ time2str('%b %d %Y', $cbp->_date ).
+ " ($money_char".
+ sprintf('%.2f', $cbp->cust_pay_paid ).
+ ")"
+ },
+ sub { shift->cust_pay->otaker },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'rrrl'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ $cust_bill_link,
+ $cust_pay_link,
+ '',
+ ( map { $_ ne 'Cust. Status' ? $cust_link : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $title = 'Net Payment Search Results';
+
+my @search = ();
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "agentnum = $1";
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "unknown agentnum $1" unless $agent;
+ $title = $agent->agent. " $title";
+}
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "cust_bill._date >= $beginning ",
+ "cust_bill._date <= $ending";
+
+#here is the agent virtualization
+push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = 'WHERE '. join(' AND ', @search);
+#
+my $count_query = 'SELECT COUNT(*), SUM(amount)
+ FROM cust_bill_pay
+ LEFT JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum ) '.
+ $where;
+
+my $sql_query = {
+ 'table' => 'cust_bill_pay',
+ 'select' => join(', ',
+ 'cust_bill_pay.*',
+ 'cust_pay.paid AS cust_pay_paid',
+ 'cust_bill._date AS cust_bill_date',
+ #'cust_bill.charged AS cust_bill_charged',
+ 'cust_pay.custnum AS custnum',
+ 'cust_main.custnum AS cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => $where,
+ 'addl_from' => 'LEFT JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_pay USING ( paynum )
+ LEFT JOIN cust_main ON ( cust_bill.custnum = cust_main.custnum )',
+};
+
+my $cust_bill_link = sub {
+ my $cust_bill_pay = shift;
+ $cust_bill_pay->invnum
+ ? [ "${p}view/cust_bill.cgi?", 'invnum' ]
+ : '';
+};
+
+my $cust_pay_link = sub {
+ my $cust_bill_pay = shift;
+ $cust_bill_pay->paynum
+ ? [ "${p}view/cust_pay.html?paynum=", 'paynum' ]
+ : '';
+};
+
+my $cust_link = sub {
+ my $cust_credit_bill = shift;
+ $cust_credit_bill->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
new file mode 100644
index 000000000..89901ac40
--- /dev/null
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -0,0 +1,335 @@
+<% include( 'elements/search.html',
+ 'title' => 'Line items',
+ 'name' => 'line items',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ $money_char. '%.2f total', ],
+ 'header' => [
+ '#',
+ 'Description',
+ 'Setup charge',
+ 'Recurring charge',
+ 'Invoice',
+ 'Date',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'billpkgnum',
+ sub { $_[0]->pkgnum > 0
+ ? $_[0]->get('pkg')
+ : $_[0]->get('itemdesc')
+ },
+ #strikethrough or "N/A ($amount)" or something these when
+ # they're not applicable to pkg_tax search
+ sub { sprintf($money_char.'%.2f', shift->setup ) },
+ sub { sprintf($money_char.'%.2f', shift->recur ) },
+ 'invnum',
+ sub { time2str('%b %d %Y', shift->_date ) },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [
+ '',
+ '',
+ '',
+ '',
+ $ilink,
+ $ilink,
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rlrrrc'.FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+
+#here is the agent virtualization
+my $agentnums_sql =
+ $FS::CurrentUser::CurrentUser->agentnums_sql( 'table' => 'cust_main' );
+
+my @where = ( $agentnums_sql );
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @where, "_date >= $beginning",
+ "_date <= $ending";
+
+push @where , " payby != 'COMP' "
+ unless $cgi->param('include_comp_cust');
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @where, "cust_main.agentnum = $1";
+}
+
+if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
+ if ( $1 == 0 ) {
+ push @where, "classnum IS NULL";
+ } else {
+ push @where, "classnum = $1";
+ }
+}
+
+#sub _where {
+# my $table = shift;
+# my $prefix = @_ ? shift : '';
+# "
+# ( cust_main_county.county = $table.${prefix}.county
+# OR ( cust_main_county.county IS NULL AND $table.${prefix}.county = '' )
+# OR ( cust_main_county.county = '' AND $table.${prefix}.county IS NULL)
+# OR ( cust_main_county.county IS NULL AND $table.${prefix}.county IS NULL)
+# )
+# AND ( cust_main_county.state = $table.${prefix}.state
+# OR ( cust_main_county.state IS NULL AND $table.${prefix}.state = '' )
+# OR ( cust_main_county.state = '' AND $table.${prefix}.state IS NULL )
+# OR ( cust_main_county.state IS NULL AND $table.${prefix}.state IS NULL )
+# )
+# AND cust_main_county.country = $table.${prefix}.country
+# ";
+#
+#}
+
+if ( $cgi->param('out') ) {
+
+ my ( $loc_sql, @param ) = FS::cust_pkg->location_sql( 'ornull' => 1 );
+ while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
+ $loc_sql =~ s/\?/'cust_main_county.'.shift(@param)/e;
+ }
+
+ $loc_sql =~ s/cust_pkg\.locationnum/cust_bill_pkg_tax_location.locationnum/g
+ if $cgi->param('istax');
+
+ push @where, "
+ 0 = (
+ SELECT COUNT(*) FROM cust_main_county
+ WHERE cust_main_county.tax > 0
+ AND $loc_sql
+ )
+ ";
+
+ #not linked to by anything, but useful for debugging "out of taxable region"
+ if ( grep $cgi->param($_), qw( county state country ) ) {
+
+ my %ph = map { $_ => dbh->quote( $cgi->param($_) ) }
+ qw( county state country );
+
+ my ( $loc_sql, @param ) = FS::cust_pkg->location_sql;
+ while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
+ $loc_sql =~ s/\?/$ph{shift(@param)}/e;
+ }
+
+ push @where, $loc_sql;
+
+ }
+
+} elsif ( $cgi->param('country' ) ) {
+
+ my %ph = map { $_ => dbh->quote( $cgi->param($_) ) }
+ qw( county state country );
+
+ my ( $loc_sql, @param ) = FS::cust_pkg->location_sql;
+ while ( $loc_sql =~ /\?/ ) { #easier to do our own substitution
+ $loc_sql =~ s/\?/$ph{shift(@param)}/e;
+ }
+
+ push @where, $loc_sql;
+
+ if ( $cgi->param('istax') ) {
+ if ( $cgi->param('taxname') ) {
+ push @where, 'itemdesc = '. dbh->quote( $cgi->param('taxname') );
+ #} elsif ( $cgi->param('taxnameNULL') {
+ } else {
+ push @where, "( itemdesc IS NULL OR itemdesc = '' OR itemdesc = 'Tax' )";
+ }
+ } elsif ( $cgi->param('nottax') ) {
+ #what can we usefully do with "taxname" ???? look up a class???
+ } else {
+ #warn "neither nottax nor istax parameters specified";
+ }
+
+ push @where, ' taxclass = '. dbh->quote( $cgi->param('taxclass') )
+ if $cgi->param('taxclass')
+ && ! $cgi->param('istax'); #no part_pkg.taxclass in this case
+ #(should we save a taxclass or a link to taxnum
+ # in cust_bill_pkg or something like
+ # cust_bill_pkg_tax_location?)
+
+ if ( $cgi->param('taxclassNULL') ) {
+
+ my %hash = ( 'country' => scalar($cgi->param('country')) );
+ foreach (qw( state county )) {
+ $hash{$_} = scalar($cgi->param($_)) if $cgi->param($_);
+ }
+ my $cust_main_county = qsearchs('cust_main_county', \%hash);
+ die "unknown base region for empty taxclass" unless $cust_main_county;
+
+ my $same_sql = $cust_main_county->sql_taxclass_sameregion;
+ push @where, $same_sql if $same_sql;
+
+ }
+
+}
+
+if ($cgi->param('itemdesc')) {
+ if ($cgi->param('itemdesc') eq 'Tax') {
+ push @where, "(itemdesc='Tax' OR itemdesc is null)";
+ }else{
+ push @where, 'itemdesc='. dbh->quote($cgi->param('itemdesc'));
+ }
+}
+push @where, 'cust_bill_pkg.pkgnum != 0' if $cgi->param('nottax');
+push @where, 'cust_bill_pkg.pkgnum = 0' if $cgi->param('istax');
+
+push @where, " tax = 'Y' " if $cgi->param('cust_tax');
+
+my $count_query;
+if ( $cgi->param('pkg_tax') ) {
+
+ $count_query =
+ "SELECT COUNT(*),
+ SUM(
+ ( CASE WHEN part_pkg.setuptax = 'Y'
+ THEN cust_bill_pkg.setup
+ ELSE 0
+ END
+ )
+ +
+ ( CASE WHEN part_pkg.recurtax = 'Y'
+ THEN cust_bill_pkg.recur
+ ELSE 0
+ END
+ )
+ )
+ ";
+
+ push @where, "( ( part_pkg.setuptax = 'Y' AND cust_bill_pkg.setup > 0 )
+ OR ( part_pkg.recurtax = 'Y' AND cust_bill_pkg.recur > 0 ) )",
+ "( tax != 'Y' OR tax IS NULL )";
+
+} elsif ( $cgi->param('taxable') ) {
+
+ my $setup_taxable = "(
+ CASE WHEN part_pkg.setuptax = 'Y'
+ THEN 0
+ ELSE cust_bill_pkg.setup
+ END
+ )";
+
+ my $recur_taxable = "(
+ CASE WHEN part_pkg.recurtax = 'Y'
+ THEN 0
+ ELSE cust_bill_pkg.recur
+ END
+ )";
+
+ my $exempt = "(
+ SELECT COALESCE( SUM(amount), 0 ) FROM cust_tax_exempt_pkg
+ WHERE cust_tax_exempt_pkg.billpkgnum = cust_bill_pkg.billpkgnum
+ )";
+
+ $count_query =
+ "SELECT COUNT(*), SUM( $setup_taxable + $recur_taxable - $exempt )";
+
+ push @where,
+ #not tax-exempt package (setup or recur)
+ "(
+ ( ( part_pkg.setuptax != 'Y' OR part_pkg.setuptax IS NULL )
+ AND cust_bill_pkg.setup > 0 )
+ OR
+ ( ( part_pkg.recurtax != 'Y' OR part_pkg.recurtax IS NULL )
+ AND cust_bill_pkg.recur > 0 )
+ )",
+ #not a tax_exempt customer
+ "( tax != 'Y' OR tax IS NULL )";
+ #not covered in full by a monthly tax exemption (texas tax)
+ "0 < ( $setup_taxable + $recur_taxable - $exempt )",
+
+} else {
+
+ $count_query =
+ "SELECT COUNT(*), SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)";
+
+}
+
+my $where = ' WHERE '. join(' AND ', @where);
+
+my $join_cust = ' JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum ) ';
+
+
+my $join_pkg;
+if ( $cgi->param('nottax') ) {
+
+ $join_pkg = ' LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN part_pkg USING ( pkgpart ) ';
+ $join_pkg .= ' LEFT JOIN cust_location USING ( locationnum ) '
+ if $conf->exists('tax-pkg_address');
+
+} elsif ( $cgi->param('istax') ) {
+
+ #false laziness w/report_tax.cgi $taxfromwhere
+ if ( $conf->exists('tax-pkg_address') ) {
+ $join_pkg .= ' LEFT JOIN cust_bill_pkg_tax_location USING ( billpkgnum )
+ LEFT JOIN cust_location USING ( locationnum ) ';
+
+ #quelle kludge, false laziness w/report_tax.cgi
+ $where =~ s/cust_pkg\.locationnum/cust_bill_pkg_tax_location.locationnum/g;
+ }
+
+} else {
+
+ #die?
+ warn "neiether nottax nor istax parameters specified";
+ #same as before?
+ $join_pkg = ' LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN part_pkg USING ( pkgpart ) ';
+
+}
+
+$count_query .= " FROM cust_bill_pkg $join_cust $join_pkg $where";
+
+my @select = (
+ 'cust_bill_pkg.*',
+ 'cust_bill._date',
+ );
+push @select, 'part_pkg.pkg' unless $cgi->param('istax');
+push @select, 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields();
+
+my $query = {
+ 'table' => 'cust_bill_pkg',
+ 'addl_from' => "$join_cust $join_pkg",
+ 'hashref' => {},
+ 'select' => join(', ', @select ),
+ 'extra_sql' => $where,
+ 'order_by' => 'ORDER BY _date, billpkgnum',
+};
+
+my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ];
+my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/search/cust_credit.html b/httemplate/search/cust_credit.html
new file mode 100755
index 000000000..9a14dceca
--- /dev/null
+++ b/httemplate/search/cust_credit.html
@@ -0,0 +1,104 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name' => 'credits',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ '$%.2f total credited (gross)', ],
+ #'redirect' => $link,
+ 'header' => [ 'Amount',
+ 'Date',
+ 'By',
+ 'Reason',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ #'crednum',
+ sub { sprintf('$%.2f', shift->amount ) },
+ sub { time2str('%b %d %Y', shift->_date ) },
+ 'otaker',
+ 'reason',
+ \&FS::UI::Web::cust_fields,
+ ],
+ #'align' => 'rrrllll',
+ 'align' => 'rrll'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ '',
+ '',
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $title = 'Credit Search Results';
+#my( $count_query, $sql_query );
+
+my @search = ();
+
+if ( $cgi->param('otaker') && $cgi->param('otaker') =~ /^([\w\.\-]+)$/ ) {
+ push @search, "cust_credit.otaker = '$1'";
+}
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "agentnum = $1";
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "unknown agentnum $1" unless $agent;
+ $title = $agent->agent. " $title";
+}
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "_date >= $beginning ",
+ "_date <= $ending";
+
+push @search, FS::UI::Web::parse_lt_gt($cgi, 'amount' );
+
+#here is the agent virtualization
+push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = 'WHERE '. join(' AND ', @search);
+
+my $count_query = 'SELECT COUNT(*), SUM(amount) '.
+ 'FROM cust_credit LEFT JOIN cust_main USING ( custnum ) '.
+ $where;
+
+my $sql_query = {
+ 'table' => 'cust_credit',
+ 'select' => join(', ',
+ 'cust_credit.*',
+ 'cust_main.custnum as cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => $where,
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+};
+
+ my $clink = sub {
+ my $cust_bill = shift;
+ $cust_bill->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+ : '';
+ };
+
+</%init>
diff --git a/httemplate/search/cust_credit_bill.html b/httemplate/search/cust_credit_bill.html
new file mode 100644
index 000000000..818e603a1
--- /dev/null
+++ b/httemplate/search/cust_credit_bill.html
@@ -0,0 +1,135 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name' => 'net credits',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ '$%.2f total credited (net)', ],
+ 'header' => [ 'Net applied',
+ 'to Invoice',
+ 'Credit',
+ 'By',
+ 'Reason',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ sub { $money_char. sprintf('%.2f', shift->amount ) },
+ sub { my $ccb = shift;
+ '#'.$ccb->invnum. ' '.
+ time2str('%b %d %Y', $ccb->cust_bill_date ).
+ " ($money_char".
+ sprintf('%.2f', $ccb->cust_bill_amount).
+ ")"
+ },
+ sub { my $ccb = shift;
+ time2str('%b %d %Y', $ccb->_date ).
+ " ($money_char".
+ sprintf('%.2f', $ccb->cust_credit_amount ).
+ ")"
+ },
+ sub { shift->cust_credit->otaker },
+ sub { shift->cust_credit->reason },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'rrrll'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ $cust_bill_link,
+ '',
+ '',
+ '',
+ ( map { $_ ne 'Cust. Status' ? $cust_link : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $title = 'Net Credit Search Results';
+
+my @search = ();
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "agentnum = $1";
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "unknown agentnum $1" unless $agent;
+ $title = $agent->agent. " $title";
+}
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "cust_bill._date >= $beginning ",
+ "cust_bill._date <= $ending";
+
+#here is the agent virtualization
+push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = 'WHERE '. join(' AND ', @search);
+#
+my $count_query = 'SELECT COUNT(*), SUM(amount)
+ FROM cust_credit_bill
+ LEFT JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum ) '.
+ $where;
+
+my $sql_query = {
+ 'table' => 'cust_credit_bill',
+ 'select' => join(', ',
+ 'cust_credit_bill.*',
+ 'cust_credit.amount AS cust_credit_amount',
+ 'cust_bill._date AS cust_bill_date',
+ 'cust_bill.charged AS cust_bill_charged',
+ 'cust_credit.custnum AS custnum',
+ 'cust_main.custnum AS cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => $where,
+ 'addl_from' => 'LEFT JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_credit USING ( crednum )
+ LEFT JOIN cust_main ON ( cust_bill.custnum = cust_main.custnum )',
+};
+
+my $cust_bill_link = sub {
+ my $cust_credit_bill = shift;
+ $cust_credit_bill->invnum
+ ? [ "${p}view/cust_bill.cgi?", 'invnum' ]
+ : '';
+};
+
+#my $cust_credit_link = sub {
+# my $cust_credit_bill = shift;
+# $cust_credit_bill->crednum
+# ? [ "${p}view/cust_credit.cgi?", 'crednum' ]
+# : '';
+#};
+
+my $cust_link = sub {
+ my $cust_credit_bill = shift;
+ $cust_credit_bill->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/cust_credit_refund.html b/httemplate/search/cust_credit_refund.html
new file mode 100644
index 000000000..d9abe2e00
--- /dev/null
+++ b/httemplate/search/cust_credit_refund.html
@@ -0,0 +1,130 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'name' => 'net refunds',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ '$%.2f total refunded (net)', ],
+ 'header' => [ 'Net applied',
+ 'to Credit',
+ 'Refund',
+ 'By',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ sub { $money_char. sprintf('%.2f', shift->amount ) },
+ sub { my $ccr = shift;
+ '#'.$ccr->crednum. ' '.
+ time2str('%b %d %Y', $ccr->cust_credit_date ).
+ " ($money_char".
+ sprintf('%.2f', $ccr->cust_credit_amount).
+ ")"
+ },
+ sub { my $ccr = shift;
+ time2str('%b %d %Y', $ccr->_date ).
+ " ($money_char".
+ sprintf('%.2f', $ccr->cust_refund_refund ).
+ ")"
+ },
+ sub { shift->cust_refund->otaker },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'rrrl'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ '',
+ '',
+ ( map { $_ ne 'Cust. Status' ? $cust_link : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $title = 'Net Refund Search Results';
+
+my @search = ();
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "agentnum = $1";
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "unknown agentnum $1" unless $agent;
+ $title = $agent->agent. " $title";
+}
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "cust_credit._date >= $beginning ",
+ "cust_credit._date <= $ending";
+
+#here is the agent virtualization
+push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = 'WHERE '. join(' AND ', @search);
+#
+my $count_query = 'SELECT COUNT(*), SUM(cust_credit_refund.amount)
+ FROM cust_credit_refund
+ LEFT JOIN cust_credit USING ( crednum )
+ LEFT JOIN cust_main USING ( custnum ) '.
+ $where;
+
+my $sql_query = {
+ 'table' => 'cust_credit_refund',
+ 'select' => join(', ',
+ 'cust_credit_refund.*',
+ 'cust_refund.refund AS cust_refund_refund',
+ 'cust_credit._date AS cust_credit_date',
+ 'cust_credit.amount AS cust_credit_amnount',
+ 'cust_refund.custnum AS custnum',
+ 'cust_main.custnum AS cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => $where,
+ 'addl_from' => 'LEFT JOIN cust_credit USING ( crednum )
+ LEFT JOIN cust_refund USING ( refundnum )
+ LEFT JOIN cust_main ON ( cust_credit.custnum = cust_main.custnum )',
+};
+
+#my $cust_credit_link = sub {
+# my $cust_credit_refund = shift;
+# $cust_credit_refund->crednum
+# ? [ "${p}view/cust_credit.cgi?", 'credum' ]
+# : '';
+#};
+
+#my $cust_refund_link = sub {
+# my $cust_credit_refund = shift;
+# $cust_credit_refund->refundnum
+# ? [ "${p}view/cust_refund.cgi?", 'refundnum' ]
+# : '';
+#};
+
+my $cust_link = sub {
+ my $cust_credit_refund = shift;
+ $cust_credit_refund->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/cust_event.html b/httemplate/search/cust_event.html
new file mode 100644
index 000000000..d55b5c6d2
--- /dev/null
+++ b/httemplate/search/cust_event.html
@@ -0,0 +1,285 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+ 'html_init' => $html_init,
+ 'menubar' => $menubar,
+ 'name' => 'billing events',
+ 'query' => $sql_query,
+ 'count_query' => $count_sql,
+ 'header' => [ 'Event',
+ 'Date',
+ 'Status',
+ 'Trigger',
+ #'Inv #', 'Inv Date', 'Cust #',
+ #'Invoice',
+
+ FS::UI::Web::cust_header(), #'cust_main_custnum',
+ ],
+ 'fields' => [
+ 'event',
+ sub { time2str("%b %d %Y %T", $_[0]->_date) },
+ $status_sub,
+ $trigger_sub,
+ #sub {
+ # #my $cust_event = shift;
+ # 'Invoice #'. $_[0]->invnum.
+ # ' ('.
+ # time2str("%D", $_[0]->cust_bill_date).
+ # ')';
+ # },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'lrll'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ '',
+ $trigger_link,
+ #sub {
+ # my $part_event = shift;
+ # #XXX
+ # my $template = $part_event->templatename;
+ # $template .= '-' if $template;
+ # [ "${p}view/cust_bill.cgi?$template", 'invnum'];
+ #},
+
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ #'',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ #'',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%once>
+
+my $status_sub = sub {
+ my $cust_event = shift;
+
+ my $status = $cust_event->status;
+ $status .= ': '.$cust_event->statustext
+ if $cust_event->statustext;
+
+ my $part_event = $cust_event->part_event;
+
+ if ( $part_event->eventtable eq 'cust_bill' && $part_event->templatename ) {
+ my $alt_templatename = $part_event->templatename;
+ my $alt_link = "$alt_templatename-". $cust_event->tablenum;
+
+ my $conf = new FS::Conf;
+ my $cust_bill = $cust_event->cust_X;
+
+ $status .= qq{
+ ( <A HREF="${p}view/cust_bill.cgi?$alt_link">view</A>
+ | <A HREF="${p}view/cust_bill-pdf.cgi?$alt_link.pdf">view
+ typeset</A>
+ | <A HREF="${p}misc/print-invoice.cgi?$alt_link">re-print</A>
+ };
+
+ if ( grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ) {
+ $status .= qq{
+ | <A HREF="${p}misc/email-invoice.cgi?$alt_link">re-email</A>
+ };
+ }
+
+ if ( $conf->exists('hylafax') && length($cust_bill->cust_main->fax) ) {
+ $status .= qq{
+ | <A HREF="${p}misc/fax-invoice.cgi?$alt_link">re-fax</A>
+ }
+ }
+
+ $status .= ' ) ';
+
+ }
+
+ $status;
+};
+
+my $trigger_sub = sub {
+ my $cust_event = shift;
+ my $eventtable = $cust_event->eventtable;
+ my $label = FS::part_event->eventtable_labels->{$eventtable};
+ #if ( $eventtable eq 'cust_pkg' || $eventtable eq 'cust_bill' ) {
+ "$label #". $cust_event->tablenum;
+ #} else {
+ # $label;
+ #}
+};
+
+my $trigger_link = sub {
+ my $cust_event = shift;
+ my $eventtable = $cust_event->eventtable;
+ if ( $eventtable eq 'cust_pkg' ) {
+ my $custnum = $cust_event->cust_main_custnum;
+ [ "${p}view/cust_main.cgi?$custnum#cust_pkg", 'tablenum' ];
+ } else {
+ [ "${p}view/$eventtable.cgi?", 'tablenum' ];
+ }
+};
+
+</%once>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Billing event reports')
+ or $curuser->access_right('View customer billing events')
+ && ( $cgi->param('custnum') =~ /^(\d+)$/
+ || $cgi->param('invnum') =~ /^(\d+)$/
+ || $cgi->param('pkgnum') =~ /^(\d+)$/
+ );
+
+
+my $title = $cgi->param('failed')
+ ? 'Failed billing events'
+ : 'Billing events';
+
+my @search = ();
+
+if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "cust_main.agentnum = $1";
+ #my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ #die "unknown agentnum $1" unless $agent;
+}
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+push @search, "cust_event._date >= $beginning",
+ "cust_event._date <= $ending";
+
+if ( $cgi->param('failed') ) {
+ push @search, "statustext != ''",
+ "statustext IS NOT NULL",
+ "statustext != 'N/A'";
+}
+
+#if ( $cgi->param('part_event.payby') =~ /^(\w+)$/ ) {
+# push @search, "part_event.payby = '$1'";
+#}
+
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @search, "cust_main.custnum = '$1'";
+}
+if ( $cgi->param('invnum') =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_bill'",
+ "tablenum = '$1'";
+}
+if ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_pkg'",
+ "tablenum = '$1'";
+}
+
+#here is the agent virtualization
+push @search, $curuser->agentnums_sql( 'table' => 'cust_main' );
+
+my $where = 'WHERE '. join(' AND ', @search );
+
+my $join = "
+ JOIN part_event USING ( eventpart )
+ LEFT JOIN cust_bill ON ( eventtable = 'cust_bill' AND tablenum = invnum )
+ LEFT JOIN cust_pkg ON ( eventtable = 'cust_pkg' AND tablenum = pkgnum )
+ LEFT JOIN cust_main ON ( ( eventtable = 'cust_main' AND tablenum = cust_main.custnum )
+ OR ( eventtable = 'cust_bill' AND cust_bill.custnum = cust_main.custnum )
+ OR ( eventtable = 'cust_pkg' AND cust_pkg.custnum = cust_main.custnum )
+ )
+";
+ #'LEFT JOIN cust_main USING ( custnum ) ';
+
+my $sql_query = {
+ 'table' => 'cust_event',
+ 'select' => join(', ',
+ 'cust_event.*',
+ 'part_event.*',
+ #'cust_bill.custnum',
+ #'cust_bill._date AS cust_bill_date',
+ 'cust_main.custnum AS cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => "$where ORDER BY _date ASC",
+ 'addl_from' => $join,
+};
+
+my $count_sql = "SELECT COUNT(*) FROM cust_event $join $where";
+
+my $conf = new FS::Conf;
+
+my $failed = $cgi->param('failed');
+
+my $html_init = join("\n", map {
+ ( my $action = $_ ) =~ s/_$//;
+ include('/elements/progress-init.html',
+ $_.'form',
+ [ 'action', 'beginning', 'ending', 'failed' ],
+ "../misc/${_}events.cgi",
+ { 'message' => "Invoices re-${action}ed" }, #would be nice to show the number of them, but...
+ $_, #key
+ ),
+ qq!<FORM NAME="${_}form">!,
+ qq!<INPUT TYPE="hidden" NAME="action" VALUE="$_">!, #not used though
+ qq!<INPUT TYPE="hidden" NAME="beginning" VALUE="$beginning">!,
+ qq!<INPUT TYPE="hidden" NAME="ending" VALUE="$ending">!,
+ qq!<INPUT TYPE="hidden" NAME="failed" VALUE="$failed">!,
+ qq!</FORM>!
+} qw( print_ email_ fax_ ) ).
+
+'<SCRIPT TYPE="text/javascript">
+
+function confirm_print_process() {
+ if ( ! confirm("Are you sure you want to reprint these invoices?") ) {
+ return;
+ }
+ print_process();
+}
+function confirm_email_process() {
+ if ( ! confirm("Are you sure you want to re-email these invoices?") ) {
+ return;
+ }
+ email_process();
+}
+function confirm_fax_process() {
+ if ( ! confirm("Are you sure you want to re-fax these invoices?") ) {
+ return;
+ }
+ fax_process();
+}
+
+</SCRIPT>';
+
+my $menubar = [];
+
+if ( $curuser->access_right('Resend invoices') ) {
+
+ push @$menubar, 'Re-print these events' =>
+ "javascript:confirm_print_process()",
+ 'Re-email these events' =>
+ "javascript:confirm_email_process()",
+ ;
+
+ push @$menubar, 'Re-fax these events' =>
+ "javascript:confirm_fax_process()"
+ if $conf->exists('hylafax');
+
+}
+
+my $link_cust = sub {
+ my $cust_event = shift;
+ $cust_event->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/cust_main-otaker.cgi b/httemplate/search/cust_main-otaker.cgi
new file mode 100755
index 000000000..0c252e44b
--- /dev/null
+++ b/httemplate/search/cust_main-otaker.cgi
@@ -0,0 +1,31 @@
+<% include('/elements/header.html', 'Customer Search' ) %>
+
+<FORM ACTION="cust_main.cgi" METHOD="GET">
+
+Search for <B>Order taker</B>:
+ <INPUT TYPE="hidden" NAME="otaker_on" VALUE="TRUE">
+% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main")
+% or die dbh->errstr;
+% $sth->execute() or die $sth->errstr;
+% #my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref};
+%
+
+<SELECT NAME="otaker">
+% my $otaker; while ( $otaker = $sth->fetchrow_arrayref ) {
+
+ <OPTION><% $otaker->[0] %>
+% }
+
+</SELECT>
+
+<P><INPUT TYPE="submit" VALUE="Search">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/search/cust_main-zip.html b/httemplate/search/cust_main-zip.html
new file mode 100644
index 000000000..56df924bc
--- /dev/null
+++ b/httemplate/search/cust_main-zip.html
@@ -0,0 +1,99 @@
+<% include( 'elements/search.html',
+ 'title' => 'Zip code Search Results',
+ 'name' => 'zip codes',
+ 'query' => $sql_query,
+ 'count_query' => $count_sql,
+ 'header' => [ 'Zip code', 'Customers', ],
+ #'fields' => [ 'zip', 'num_cust', ],
+ 'links' => [ '', sub { 'somewhere'; } ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List zip codes');
+
+# XXX link to customers
+
+my @where = ();
+
+# select status
+
+if ( $cgi->param('status') =~ /^(prospect|uncancel|active|susp|cancel)$/ ) {
+ my $method = $1.'_sql';
+ push @where, FS::cust_main->$method();
+}
+
+# select agent
+# XXX this needs to be virtualized by agent too (like lots of stuff)
+
+my $agentnum = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+ push @where, "cust_main.agentnum = $agentnum";
+}
+my $where = scalar(@where) ? 'WHERE '. join(' AND ', @where) : '';
+
+# bill zip vs ship zip
+
+sub fieldorempty {
+ my $field = shift;
+ "CASE WHEN $field IS NULL THEN '' ELSE $field END";
+}
+
+sub strip_plus4 {
+ my $field = shift;
+ "CASE WHEN $field is NULL
+ THEN ''
+ ELSE CASE WHEN $field LIKE '_____-____'
+ THEN SUBSTRING($field FROM 1 FOR 5)
+ ELSE $field
+ END
+ END";
+}
+
+my( $zip, $czip);
+if ( $cgi->param('column') eq 'ship_zip' ) {
+
+ my $casewhen_noship =
+ "CASE WHEN ( ship_last IS NULL OR ship_last = '' ) THEN ";
+
+ $czip = "$casewhen_noship zip ELSE ship_zip END";
+
+ if ( $cgi->param('ignore_plus4') ) {
+ $zip = $casewhen_noship. strip_plus4('zip').
+ " ELSE ". strip_plus4('ship_zip'). ' END';
+
+ } else {
+ $zip = $casewhen_noship. fieldorempty('zip').
+ " ELSE ". fieldorempty('ship_zip'). ' END';
+ }
+
+} else {
+
+ $czip = 'zip';
+
+ if ( $cgi->param('ignore_plus4') ) {
+ $zip = strip_plus4('zip');
+ } else {
+ $zip = fieldorempty('zip');
+ }
+
+}
+
+# construct the queries and send 'em off
+
+my $sql_query =
+ "SELECT $zip AS zipcode,
+ COUNT(*) AS num_cust
+ FROM cust_main
+ $where
+ GROUP BY zipcode
+ ORDER BY num_cust DESC
+ ";
+
+my $count_sql = "select count(distinct $czip) from cust_main $where";
+
+# XXX should link...
+
+</%init>
diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi
new file mode 100755
index 000000000..36e4374ee
--- /dev/null
+++ b/httemplate/search/cust_main.cgi
@@ -0,0 +1,736 @@
+%die "access denied"
+% unless $FS::CurrentUser::CurrentUser->access_right('List customers');
+%
+%my $conf = new FS::Conf;
+%my $maxrecords = $conf->config('maxsearchrecordsperpage');
+%
+%#my $cache;
+%
+%#my $monsterjoin = <<END;
+%#cust_main left outer join (
+%# ( cust_pkg left outer join part_pkg using(pkgpart)
+%# ) left outer join (
+%# (
+%# (
+%# ( cust_svc left outer join part_svc using (svcpart)
+%# ) left outer join svc_acct using (svcnum)
+%# ) left outer join svc_domain using(svcnum)
+%# ) left outer join svc_forward using(svcnum)
+%# ) using (pkgnum)
+%#) using (custnum)
+%#END
+%
+%#my $monsterjoin = <<END;
+%#cust_main left outer join (
+%# ( cust_pkg left outer join part_pkg using(pkgpart)
+%# ) left outer join (
+%# (
+%# (
+%# ( cust_svc left outer join part_svc using (svcpart)
+%# ) left outer join (
+%# svc_acct left outer join (
+%# select svcnum, domain, catchall from svc_domain
+%# ) as svc_acct_domsvc (
+%# svc_acct_svcnum, svc_acct_domain, svc_acct_catchall
+%# ) on svc_acct.domsvc = svc_acct_domsvc.svc_acct_svcnum
+%# ) using (svcnum)
+%# ) left outer join svc_domain using(svcnum)
+%# ) left outer join svc_forward using(svcnum)
+%# ) using (pkgnum)
+%#) using (custnum)
+%#END
+%
+%my $limit = '';
+%$limit .= "LIMIT $maxrecords" if $maxrecords;
+%
+%my $offset = $cgi->param('offset') || 0;
+%$limit .= " OFFSET $offset" if $offset;
+%
+%my $total = 0;
+%
+%my(@cust_main, $sortby, $orderby);
+%my @select = ();
+%my @addl_headers = ();
+%my @addl_cols = ();
+%if ( $cgi->param('browse')
+% || $cgi->param('otaker_on')
+% || $cgi->param('agentnum_on')
+%) {
+%
+% my %search = ();
+%
+% if ( $cgi->param('browse') ) {
+% my $query = $cgi->param('browse');
+% if ( $query eq 'custnum' ) {
+% if ( $conf->exists('cust_main-default_agent_custid') ) {
+% $sortby=\*display_custnum_sort;
+% $orderby = "ORDER BY CASE WHEN agent_custid IS NOT NULL AND agent_custid != '' THEN CAST(agent_custid AS BIGINT) ELSE custnum END";
+% } else {
+% $sortby=\*custnum_sort;
+% $orderby = "ORDER BY custnum";
+% }
+% } elsif ( $query eq 'last' ) {
+% $sortby=\*last_sort;
+% $orderby = "ORDER BY LOWER(last || ' ' || first)";
+% } elsif ( $query eq 'company' ) {
+% $sortby=\*company_sort;
+% $orderby = "ORDER BY LOWER(company || ' ' || last || ' ' || first )";
+% } elsif ( $query eq 'tickets' ) {
+% $sortby = \*tickets_sort;
+% $orderby = "ORDER BY tickets DESC";
+% push @select, FS::TicketSystem->sql_num_customer_tickets. " as tickets";
+% push @addl_headers, 'Tickets';
+% push @addl_cols, 'tickets';
+% } else {
+% die "unknown browse field $query";
+% }
+% } else {
+% $sortby = \*last_sort; #??
+% $orderby = "ORDER BY LOWER(last || ' ' || first)"; #??
+% }
+%
+% if ( $cgi->param('otaker_on') ) {
+% die "access denied"
+% unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+% $cgi->param('otaker') =~ /^(\w{1,32})$/ or errorpage("Illegal otaker");
+% $search{otaker} = $1;
+% } elsif ( $cgi->param('agentnum_on') ) {
+% $cgi->param('agentnum') =~ /^(\d+)$/ or errorpage("Illegal agentnum");
+% $search{agentnum} = $1;
+%# } else {
+%# die "unknown query...";
+% }
+%
+% my @qual = ();
+%
+% my $ncancelled = '';
+%
+% if ( $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
+% || ( $conf->exists('hidecancelledcustomers')
+% && ! $cgi->param('showcancelledcustomers') )
+% ) {
+% #grep { $_->ncancelled_pkgs || ! $_->all_pkgs }
+% push @qual, FS::cust_main->uncancel_sql;
+%
+% }
+%
+% push @qual, FS::cust_main->cancel_sql if $cgi->param('cancelled');
+% push @qual, FS::cust_main->prospect_sql if $cgi->param('prospect');
+% push @qual, FS::cust_main->active_sql if $cgi->param('active');
+% push @qual, FS::cust_main->inactive_sql if $cgi->param('inactive');
+% push @qual, FS::cust_main->susp_sql if $cgi->param('suspended');
+%
+% #EWWWWWW
+% my $qual = join(' AND ',
+% map { "$_ = ". dbh->quote($search{$_}) } keys %search );
+%
+% my $addl_qual = join(' AND ', @qual);
+%
+% #here is the agent virtualization
+% $addl_qual .= ( $addl_qual ? ' AND ' : '' ).
+% $FS::CurrentUser::CurrentUser->agentnums_sql;
+%
+% if ( $addl_qual ) {
+% $qual .= ' AND ' if $qual;
+% $qual .= $addl_qual;
+% }
+%
+% $qual = " WHERE $qual" if $qual;
+% my $statement = "SELECT COUNT(*) FROM cust_main $qual";
+% my $sth = dbh->prepare($statement) or die dbh->errstr." preparing $statement";
+% $sth->execute or die "Error executing \"$statement\": ". $sth->errstr;
+%
+% $total = $sth->fetchrow_arrayref->[0];
+%
+% if ( $addl_qual ) {
+% if ( %search ) {
+% $addl_qual = " AND $addl_qual";
+% } else {
+% $addl_qual = " WHERE $addl_qual";
+% }
+% }
+%
+% my $select;
+% if ( @select ) {
+% $select = 'cust_main.*, '. join (', ', @select);
+% } else {
+% $select = '*';
+% }
+%
+% @cust_main = qsearch('cust_main', \%search, $select,
+% "$addl_qual $orderby $limit" );
+%
+%# foreach my $cust_main ( @just_cust_main ) {
+%#
+%# my @one_cust_main;
+%# $FS::Record::DEBUG=1;
+%# ( $cache, @one_cust_main ) = jsearch(
+%# "$monsterjoin",
+%# { 'custnum' => $cust_main->custnum },
+%# '',
+%# '',
+%# 'cust_main',
+%# 'custnum',
+%# );
+%# push @cust_main, @one_cust_main;
+%# }
+%
+%} else {
+% @cust_main=();
+% $sortby = \*last_sort;
+%
+% push @cust_main, @{&custnumsearch}
+% if $cgi->param('custnum_on') && $cgi->param('custnum_text');
+% push @cust_main, @{&cardsearch}
+% if $cgi->param('card_on') && $cgi->param('card');
+% push @cust_main, @{&lastsearch}
+% if $cgi->param('last_on') && $cgi->param('last_text');
+% push @cust_main, @{&companysearch}
+% if $cgi->param('company_on') && $cgi->param('company_text');
+% push @cust_main, @{&address2search}
+% if $cgi->param('address2_on') && $cgi->param('address2_text');
+% push @cust_main, @{&phonesearch}
+% if $cgi->param('phone_on') && $cgi->param('phone_text');
+% push @cust_main, @{&referralsearch}
+% if $cgi->param('referral_custnum');
+%
+% if ( $cgi->param('company_on') && $cgi->param('company_text') ) {
+% $sortby = \*company_sort;
+% push @cust_main, @{&companysearch};
+% }
+%
+% if ( $cgi->param('search_cust') ) {
+% $sortby = \*company_sort;
+% $orderby = "ORDER BY LOWER(company || ' ' || last || ' ' || first )";
+% push @cust_main, smart_search( 'search' => $cgi->param('search_cust') );
+% }
+%
+% @cust_main = grep { $_->ncancelled_pkgs || ! $_->all_pkgs } @cust_main
+% if ! $cgi->param('cancelled')
+% && (
+% $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
+% || ( $conf->exists('hidecancelledcustomers')
+% && ! $cgi->param('showcancelledcustomers') )
+% );
+%
+% my %saw = ();
+% @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
+%}
+%
+%my %all_pkgs;
+%if ( $conf->exists('hidecancelledpackages' ) ) {
+% %all_pkgs = map { $_->custnum => [ $_->ncancelled_pkgs ] } @cust_main;
+%} else {
+% %all_pkgs = map { $_->custnum => [ $_->all_pkgs ] } @cust_main;
+%}
+%#%all_pkgs = ();
+%
+%if ( scalar(@cust_main) == 1 && ! $cgi->param('referral_custnum') ) {
+% if ( $cgi->param('quickpay') eq 'yes' ) {
+% print $cgi->redirect(popurl(2). "edit/cust_pay.cgi?quickpay=yes;custnum=". $cust_main[0]->custnum);
+% } else {
+% print $cgi->redirect(popurl(2). "view/cust_main.cgi?". $cust_main[0]->custnum);
+% }
+% #exit;
+%} elsif ( scalar(@cust_main) == 0 ) {
+%
+
+<!-- mason kludge -->
+%
+% errorpage("No matching customers found!");
+%} else {
+%
+
+<% include('/elements/header.html', "Customer Search Results", '' ) %>
+% $total ||= scalar(@cust_main);
+
+
+ <% $total %> matching customers found
+
+% my $pager = include( '/elements/pager.html',
+% 'offset' => $offset,
+% 'num_rows' => scalar(@cust_main),
+% 'total' => $total,
+% 'maxrecords' => $maxrecords,
+% );
+%
+% unless ( $cgi->param('cancelled') ) {
+% if ( $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
+% || ( $conf->exists('hidecancelledcustomers')
+% && ! $cgi->param('showcancelledcustomers')
+% )
+% ) {
+% $cgi->param('showcancelledcustomers', 1);
+% $cgi->param('offset', 0);
+% print qq!( <a href="!. $cgi->self_url. qq!">show!;
+% } else {
+% $cgi->param('showcancelledcustomers', 0);
+% $cgi->param('offset', 0);
+% print qq!( <a href="!. $cgi->self_url. qq!">hide!;
+% }
+% print ' cancelled customers</a> )';
+% }
+%
+% if ( $cgi->param('referral_custnum') ) {
+% $cgi->param('referral_custnum') =~ /^(\d+)$/
+% or errorpage("Illegal referral_custnum");
+% my $referral_custnum = $1;
+% my $cust_main = qsearchs('cust_main', { custnum => $referral_custnum } );
+% print '<FORM METHOD="GET">'.
+% qq!<INPUT TYPE="hidden" NAME="referral_custnum" VALUE="$referral_custnum">!.
+% 'referrals of <A HREF="'. popurl(2).
+% "view/cust_main.cgi?$referral_custnum\">$referral_custnum: ".
+% ( $cust_main->company
+% || $cust_main->last. ', '. $cust_main->first ).
+% '</A>';
+% print "\n",<<END;
+% <SCRIPT>
+% function changed(what) {
+% what.form.submit();
+% }
+% </SCRIPT>
+%END
+% print ' <SELECT NAME="referral_depth" SIZE="1" onChange="changed(this)">';
+% my $max = 8; #config file
+% $cgi->param('referral_depth') =~ /^(\d*)$/
+% or errorpage("Illegal referral_depth");
+% my $referral_depth = $1;
+%
+% foreach my $depth ( 1 .. $max ) {
+% print '<OPTION',
+% ' SELECTED'x($depth == $referral_depth),
+% ">$depth";
+% }
+% print "</SELECT> levels deep".
+% '<NOSCRIPT> <INPUT TYPE="submit" VALUE="change"></NOSCRIPT>'.
+% '</FORM>';
+% }
+%
+% my @custom_priorities = ();
+% if ( $conf->config('ticket_system-custom_priority_field')
+% && @{[ $conf->config('ticket_system-custom_priority_field-values') ]} ) {
+% @custom_priorities =
+% $conf->config('ticket_system-custom_priority_field-values');
+% }
+%
+% print "<BR><BR>". $pager. include('/elements/table-grid.html'). <<END;
+% <TR>
+% <TH CLASS="grid" BGCOLOR="#cccccc">#</TH>
+% <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
+% <TH CLASS="grid" BGCOLOR="#cccccc">(bill) name</TH>
+% <TH CLASS="grid" BGCOLOR="#cccccc">company</TH>
+%END
+%
+%if ( defined dbdef->table('cust_main')->column('ship_last') ) {
+% print <<END;
+% <TH CLASS="grid" BGCOLOR="#cccccc">(service) name</TH>
+% <TH CLASS="grid" BGCOLOR="#cccccc">company</TH>
+%END
+%}
+%
+%foreach my $addl_header ( @addl_headers ) {
+% print '<TH CLASS="grid" BGCOLOR="#cccccc">'. "$addl_header</TH>";
+%}
+%
+%print <<END;
+% <TH CLASS="grid" BGCOLOR="#cccccc">Packages</TH>
+% <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2>Services</TH>
+% </TR>
+%END
+%
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% my(%saw,$cust_main);
+% foreach $cust_main (
+% sort $sortby grep(!$saw{$_->custnum}++, @cust_main)
+% ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my($custnum,$last,$first,$company)=(
+% $cust_main->custnum,
+% $cust_main->getfield('last'),
+% $cust_main->getfield('first'),
+% $cust_main->company,
+% );
+%
+% my(@lol_cust_svc);
+% my($rowspan)=0;#scalar( @{$all_pkgs{$custnum}} );
+% foreach ( @{$all_pkgs{$custnum}} ) {
+% #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
+% my @cust_svc = $_->cust_svc;
+% push @lol_cust_svc, \@cust_svc;
+% $rowspan += scalar(@cust_svc) || 1;
+% }
+%
+% #my($rowspan) = scalar(@{$all_pkgs{$custnum}});
+% my $view;
+% if ( defined $cgi->param('quickpay') && $cgi->param('quickpay') eq 'yes' ) {
+% $view = $p. 'edit/cust_pay.cgi?quickpay=yes;custnum='. $custnum;
+% } else {
+% $view = $p. 'view/cust_main.cgi?'. $custnum;
+% }
+% my $pcompany = $company
+% ? qq!<A HREF="$view"><FONT SIZE=-1>$company</FONT></A>!
+% : '<FONT SIZE=-1>&nbsp;</FONT>';
+%
+% my $status = $cust_main->status;
+% my $statuscol = $cust_main->statuscolor;
+
+ <TR>
+ <TD CLASS="grid" ALIGN="right" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><A HREF="<% $view %>"><FONT SIZE=-1><% $cust_main->display_custnum %></FONT></A></TD>
+ <TD CLASS="grid" ALIGN="center" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><FONT SIZE="-1" COLOR="#<% $statuscol %>"><B><% ucfirst($status) %></B></FONT></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><A HREF="<% $view %>"><FONT SIZE=-1><% "$last, $first" %></FONT></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><% $pcompany %></TD>
+%
+% if ( defined dbdef->table('cust_main')->column('ship_last') ) {
+% my($ship_last,$ship_first,$ship_company)=(
+% $cust_main->ship_last || $cust_main->getfield('last'),
+% $cust_main->ship_last ? $cust_main->ship_first : $cust_main->first,
+% $cust_main->ship_last ? $cust_main->ship_company : $cust_main->company,
+% );
+% my $pship_company = $ship_company
+% ? qq!<A HREF="$view"><FONT SIZE=-1>$ship_company</FONT></A>!
+% : '<FONT SIZE=-1>&nbsp;</FONT>';
+%
+
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><A HREF="<% $view %>"><FONT SIZE=-1><% "$ship_last, $ship_first" %></FONT></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %>><% $pship_company %></A></TD>
+% }
+%
+% foreach my $addl_col ( @addl_cols ) {
+% if ( $addl_col eq 'tickets' ) {
+% if ( @custom_priorities ) {
+
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %> ALIGN=right><FONT SIZE=-1>
+
+ <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>
+% foreach my $priority ( @custom_priorities, '' ) {
+%
+% my $num =
+% FS::TicketSystem->num_customer_tickets($custnum,$priority);
+% my $ahref = '';
+% $ahref= '<A HREF="'.
+% FS::TicketSystem->href_customer_tickets($custnum,$priority).
+% '">'
+% if $num;
+%
+
+
+ <TR>
+ <TD ALIGN=right>
+ <FONT SIZE=-1><% $ahref.$num %></A></FONT>
+ </TD>
+ <TD ALIGN=left>
+ <FONT SIZE=-1><% $ahref %><% $priority || '<i>(none)</i>' %></A></FONT>
+ </TD>
+ </TR>
+% }
+
+
+ <TR>
+ <TH ALIGN=right STYLE="border-top: dashed 1px black">
+ <FONT SIZE=-1>
+% } else {
+
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %> ALIGN=right><FONT SIZE=-1>
+% }
+%
+% my $ahref = '';
+% $ahref = '<A HREF="'.
+% FS::TicketSystem->href_customer_tickets($custnum).
+% '">'
+% if $cust_main->get($addl_col);
+%
+
+
+ <% $ahref %><% $cust_main->get($addl_col) %></A>
+% if ( @custom_priorities ) {
+
+
+ </FONT></TH>
+ <TH ALIGN=left STYLE="border-top: dashed 1px black">
+ <FONT SIZE=-1><% ${ahref} %>Total</A><FONT>
+ </TH>
+ </TR>
+ </TABLE>
+% }
+
+
+ </FONT></TD>
+% } else {
+
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ROWSPAN=<% $rowspan || 1 %> ALIGN=right><FONT SIZE=-1>
+ <% $cust_main->get($addl_col) %>
+ </FONT></TD>
+%
+% }
+% }
+%
+% my($n1)='';
+% foreach ( @{$all_pkgs{$custnum}} ) {
+% my $pkgnum = $_->pkgnum;
+%# my $part_pkg = qsearchs( 'part_pkg', { pkgpart => $_->pkgpart } );
+% my $part_pkg = $_->part_pkg;
+%
+% my $pkg = $part_pkg->pkg;
+% my $comment = $part_pkg->comment;
+% my $pkgview = "${p}view/cust_main.cgi?$custnum#cust_pkg$pkgnum";
+% my @cust_svc = @{shift @lol_cust_svc};
+% #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
+% my $rowspan = scalar(@cust_svc) || 1;
+%
+% print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!;
+%
+% my($n2)='';
+% foreach my $cust_svc ( @cust_svc ) {
+% my($label, $value, $svcdb) = $cust_svc->label;
+% my($svcnum) = $cust_svc->svcnum;
+% my($sview) = $p.'view';
+% print $n2,
+% qq!<TD CLASS="grid" BGCOLOR="$bgcolor" >!. FS::UI::Web::svc_link($m, $cust_svc->part_svc, $cust_svc) . qq!</TD> !.
+% qq!<TD CLASS="grid" BGCOLOR="$bgcolor" >!. FS::UI::Web::svc_label_link($m, $cust_svc->part_svc, $cust_svc) . qq!</TD> !;
+% $n2="</TR><TR>";
+% }
+%
+% unless ( @cust_svc ) {
+% print qq!<TD CLASS="grid" BGCOLOR="$bgcolor" COLSPAN=2>&nbsp;</TD>!;
+% }
+%
+% #print qq!</TR><TR>\n!;
+% $n1="</TR><TR>";
+% }
+%
+% unless ( @{$all_pkgs{$custnum}} ) {
+% print qq!<TD CLASS="grid" BGCOLOR="$bgcolor" COLSPAN=3>&nbsp;</TD>!;
+% }
+%
+% print "</TR>";
+% }
+%
+%
+
+
+ </TABLE><% $pager %>
+
+ <% include('/elements/footer.html') %>
+% }
+%
+%#undef $cache; #does this help?
+%
+%#
+%
+%sub last_sort {
+% lc($a->getfield('last')) cmp lc($b->getfield('last'))
+% || lc($a->first) cmp lc($b->first);
+%}
+%
+%sub company_sort {
+% return -1 if $a->company && ! $b->company;
+% return 1 if ! $a->company && $b->company;
+% lc($a->company) cmp lc($b->company)
+% || lc($a->getfield('last')) cmp lc($b->getfield('last'))
+% || lc($a->first) cmp lc($b->first);;
+%}
+%
+%sub display_custnum_sort {
+% $a->display_custnum <=> $b->display_custnum;
+%}
+%
+%sub custnum_sort {
+% $a->getfield('custnum') <=> $b->getfield('custnum');
+%}
+%
+%sub tickets_sort {
+% $b->getfield('tickets') <=> $a->getfield('tickets');
+%}
+%
+%sub custnumsearch {
+%
+% my $custnum = $cgi->param('custnum_text');
+% $custnum =~ s/\D//g;
+% $custnum =~ /^(\d{1,23})$/ or errorpage("Illegal customer number");
+% $custnum = $1;
+%
+% [ qsearchs('cust_main', { 'custnum' => $custnum } ) ];
+%}
+%
+%sub cardsearch {
+%
+% my($card)=$cgi->param('card');
+% $card =~ s/\D//g;
+% $card =~ /^(\d{13,16})$/ or errorpage("Illegal card number");
+% my($payinfo)=$1;
+%
+% [ qsearch('cust_main',{'payinfo'=>$payinfo, 'payby'=>'CARD'}),
+% qsearch('cust_main',{'payinfo'=>$payinfo, 'payby'=>'DCRD'})
+% ];
+%}
+%
+%sub referralsearch {
+% $cgi->param('referral_custnum') =~ /^(\d+)$/
+% or errorpage("Illegal referral_custnum");
+% my $cust_main = qsearchs('cust_main', { 'custnum' => $1 } )
+% or errorpage("Customer $1 not found");
+% my $depth;
+% if ( $cgi->param('referral_depth') ) {
+% $cgi->param('referral_depth') =~ /^(\d+)$/
+% or errorpage("Illegal referral_depth");
+% $depth = $1;
+% } else {
+% $depth = 1;
+% }
+% [ $cust_main->referral_cust_main($depth) ];
+%}
+%
+%sub lastsearch {
+% my(%last_type);
+% my @cust_main;
+% foreach ( $cgi->param('last_type') ) {
+% $last_type{$_}++;
+% }
+%
+% $cgi->param('last_text') =~ /^([\w \,\.\-\']*)$/
+% or errorpage("Illegal last name");
+% my($last)=$1;
+%
+% if ( $last_type{'Exact'} || $last_type{'Fuzzy'} ) {
+% push @cust_main, qsearch( 'cust_main',
+% { 'last' => { 'op' => 'ILIKE',
+% 'value' => $last } } );
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'ship_last' => { 'op' => 'ILIKE',
+% 'value' => $last } } )
+% if defined dbdef->table('cust_main')->column('ship_last');
+% }
+%
+% if ( $last_type{'Substring'} || $last_type{'All'} ) {
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'last' => { 'op' => 'ILIKE',
+% 'value' => "%$last%" } } );
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'ship_last' => { 'op' => 'ILIKE',
+% 'value' => "%$last%" } } )
+% if defined dbdef->table('cust_main')->column('ship_last');
+%
+% }
+%
+% if ( $last_type{'Fuzzy'} || $last_type{'All'} ) {
+% push @cust_main, FS::cust_main->fuzzy_search( { 'last' => $last } );
+% }
+%
+% #if ($last_type{'Sound-alike'}) {
+% #}
+%
+% \@cust_main;
+%}
+%
+%sub companysearch {
+%
+% my(%company_type);
+% my @cust_main;
+% foreach ( $cgi->param('company_type') ) {
+% $company_type{$_}++
+% };
+%
+% $cgi->param('company_text') =~
+% /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/
+% or errorpage("Illegal company");
+% my $company = $1;
+%
+% if ( $company_type{'Exact'} || $company_type{'Fuzzy'} ) {
+% push @cust_main, qsearch( 'cust_main',
+% { 'company' => { 'op' => 'ILIKE',
+% 'value' => $company } } );
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'ship_company' => { 'op' => 'ILIKE',
+% 'value' => $company } } )
+% if defined dbdef->table('cust_main')->column('ship_last');
+% }
+%
+% if ( $company_type{'Substring'} || $company_type{'All'} ) {
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'company' => { 'op' => 'ILIKE',
+% 'value' => "%$company%" } } );
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'ship_company' => { 'op' => 'ILIKE',
+% 'value' => "%$company%" } })
+% if defined dbdef->table('cust_main')->column('ship_last');
+%
+% }
+%
+% if ( $company_type{'Fuzzy'} || $company_type{'All'} ) {
+% push @cust_main, FS::cust_main->fuzzy_search( { 'company' => $company } );
+% }
+%
+% if ($company_type{'Sound-alike'}) {
+% }
+%
+% \@cust_main;
+%}
+%
+%sub address2search {
+% my @cust_main;
+%
+% $cgi->param('address2_text') =~
+% /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/
+% or errorpage("Illegal address2");
+% my $address2 = $1;
+%
+% push @cust_main, qsearch( 'cust_main',
+% { 'address2' => { 'op' => 'ILIKE',
+% 'value' => $address2 } } );
+% push @cust_main, qsearch( 'cust_main',
+% { 'ship_address2' => { 'op' => 'ILIKE',
+% 'value' => $address2 } } );
+%
+% \@cust_main;
+%}
+%
+%sub phonesearch {
+% my @cust_main;
+%
+% my $phone = $cgi->param('phone_text');
+%
+% #(no longer really) false laziness with Record::ut_phonen
+% #only works with US/CA numbers...
+% $phone =~ s/\D//g;
+% if ( $phone =~ /^(\d{3})(\d{3})(\d{4})(\d*)$/ ) {
+% $phone = "$1-$2-$3";
+% $phone .= " x$4" if $4;
+% } elsif ( $phone =~ /^(\d{3})(\d{4})$/ ) {
+% $phone = "$1-$2";
+% } elsif ( $phone =~ /^(\d{3,4})$/ ) {
+% $phone = $1;
+% } else {
+% errorpage(gettext('illegal_phone'). ": $phone");
+% }
+%
+% my @fields = qw(daytime night fax);
+% push @fields, qw(ship_daytime ship_night ship_fax)
+% if defined dbdef->table('cust_main')->column('ship_last');
+%
+% for my $field ( @fields ) {
+% push @cust_main, qsearch ( 'cust_main',
+% { $field => { 'op' => 'LIKE',
+% 'value' => "%$phone%" } } );
+% }
+%
+% \@cust_main;
+%}
diff --git a/httemplate/search/cust_main.html b/httemplate/search/cust_main.html
new file mode 100755
index 000000000..3282f0f31
--- /dev/null
+++ b/httemplate/search/cust_main.html
@@ -0,0 +1,109 @@
+<% include( 'elements/search.html',
+ 'title' => 'Customer Search Results',
+ 'menubar' => $menubar,
+ 'name' => 'customers',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'header' => [ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ ),
+ @extra_headers,
+ ],
+ 'fields' => [
+ \&FS::UI::Web::cust_fields,
+ @extra_fields,
+ ],
+ 'color' => [ FS::UI::Web::cust_colors(),
+ map '', @extra_fields
+ ],
+ 'style' => [ FS::UI::Web::cust_styles(),
+ map '', @extra_fields
+ ],
+ 'align' => [ FS::UI::Web::cust_aligns(),
+ map '', @extra_fields
+ ],
+ 'links' => [ ( map { $_ ne 'Cust. Status' ? $link : '' }
+ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ )
+ ),
+ map '', @extra_fields
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless ( $FS::CurrentUser::CurrentUser->access_right('List customers') &&
+ $FS::CurrentUser::CurrentUser->access_right('List packages')
+ );
+
+my %search_hash = ();
+
+#$search_hash{'query'} = $cgi->keywords;
+
+#scalars
+for my $param (qw(
+ agentnum status cancelled_pkgs cust_fields flattened_pkgs custbatch
+)) {
+ $search_hash{$param} = scalar( $cgi->param($param) )
+ if $cgi->param($param);
+}
+
+#lists
+for my $param (qw( payby )) {
+ $search_hash{$param} = [ $cgi->param($param) ]
+ if $cgi->param($param);
+}
+
+###
+# parse dates
+###
+
+foreach my $field (qw( signupdate )) {
+
+ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
+
+ next if $beginning == 0 && $ending == 4294967295;
+ #or $disable{$cgi->param('status')}->{$field};
+
+ $search_hash{$field} = [ $beginning, $ending ];
+
+}
+
+##
+# amounts
+##
+
+$search_hash{'current_balance'} =
+ [ FS::UI::Web::parse_lt_gt($cgi, 'current_balance') ];
+
+###
+# etc
+###
+
+my $sql_query = FS::cust_main->search_sql(\%search_hash);
+my $count_query = delete($sql_query->{'count_query'});
+my @extra_headers = @{ delete($sql_query->{'extra_headers'}) };
+my @extra_fields = @{ delete($sql_query->{'extra_fields'}) };
+
+my $link = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+###
+# email links
+###
+
+my $menubar = [];
+
+if ( $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices') ) {
+
+ my $uri = new URI::URL;
+ $uri->query_form( \%search_hash );
+ my $query = $uri->query;
+
+ push @$menubar, 'Email a notice to these customers' =>
+ "${p}misc/email-customers.html?$query",
+
+}
+
+</%init>
diff --git a/httemplate/search/cust_pay.cgi b/httemplate/search/cust_pay.cgi
new file mode 100755
index 000000000..65bd39e19
--- /dev/null
+++ b/httemplate/search/cust_pay.cgi
@@ -0,0 +1,7 @@
+<% include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'payment',
+ 'name_verb' => 'paid',
+ )
+%>
diff --git a/httemplate/search/cust_pay_batch.cgi b/httemplate/search/cust_pay_batch.cgi
new file mode 100755
index 000000000..157696366
--- /dev/null
+++ b/httemplate/search/cust_pay_batch.cgi
@@ -0,0 +1,193 @@
+<% include('elements/search.html',
+ 'title' => 'Batch payment details',
+ 'name' => 'batch details',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'html_init' => $pay_batch ? $html_init : '',
+ 'header' => [ '#',
+ 'Inv #',
+ 'Customer',
+ 'Customer',
+ 'Card Name',
+ 'Card',
+ 'Exp',
+ 'Amount',
+ 'Status',
+ ],
+ 'fields' => [ sub {
+ shift->[0];
+ },
+ sub {
+ shift->[1];
+ },
+ sub {
+ shift->[2];
+ },
+ sub {
+ my $cpb = shift;
+ $cpb->[3] . ', ' . $cpb->[4];
+ },
+ sub {
+ shift->[5];
+ },
+ sub {
+ my $cardnum = shift->[6];
+ 'x'x(length($cardnum)-4). substr($cardnum,(length($cardnum)-4));
+ },
+ sub {
+ shift->[7] =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ my( $mon, $year ) = ( $2, $1 );
+ $mon = "0$mon" if length($mon) == 1;
+ "$mon/$year";
+ },
+ sub {
+ shift->[8];
+ },
+ sub {
+ shift->[9];
+ },
+ ],
+ 'align' => 'lllllllrl',
+ 'links' => [ ['', sub{'#';}],
+ ["${p}view/cust_bill.cgi?", sub{shift->[1];},],
+ ["${p}view/cust_main.cgi?", sub{shift->[2];},],
+ ["${p}view/cust_main.cgi?", sub{shift->[2];},],
+ ],
+ )
+%>
+<%init>
+
+my $conf = new FS::Conf;
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports')
+ || $FS::CurrentUser::CurrentUser->access_right('Process batches')
+ || ( $cgi->param('custnum')
+ && ( $conf->exists('batch-enable')
+ || $conf->config('batch-enable_payby')
+ )
+ #&& $FS::CurrentUser::CurrentUser->access_right('View customer batched payments')
+ );
+
+my( $count_query, $sql_query );
+my $hashref = {};
+my @search = ();
+my $orderby = 'paybatchnum';
+
+my( $pay_batch, $batchnum ) = ( '', '');
+if ( $cgi->param('batchnum') && $cgi->param('batchnum') =~ /^(\d+)$/ ) {
+ push @search, "batchnum = $1";
+ $pay_batch = qsearchs('pay_batch', { 'batchnum' => $1 } );
+ die "Batch $1 not found!" unless $pay_batch;
+ $batchnum = $pay_batch->batchnum;
+}
+
+if ( $cgi->param('custnum') && $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @search, "custnum = $1";
+}
+
+if ( $cgi->param('status') && $cgi->param('status') =~ /^(\w)$/ ) {
+ push @search, "pay_batch.status = '$1'";
+}
+
+if ( $cgi->param('payby') ) {
+ $cgi->param('payby') =~ /^(CARD|CHEK)$/
+ or die "illegal payby " . $cgi->param('payby');
+
+ push @search, "cust_pay_batch.payby = '$1'";
+}
+
+if ( not $cgi->param('dcln') ) {
+ push @search, "cpb.status IS DISTINCT FROM 'Approved'";
+}
+
+my ($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+unless ($pay_batch){
+ push @search, "pay_batch.upload >= $beginning" if ($beginning);
+ push @search, "pay_batch.upload <= $ending" if ($ending < 4294967295);#2^32-1
+ $orderby = "pay_batch.download,paybatchnum";
+}
+
+push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+my $search = ' WHERE ' . join(' AND ', @search);
+
+$count_query = 'SELECT COUNT(*) FROM cust_pay_batch AS cpb ' .
+ 'LEFT JOIN cust_main USING ( custnum ) ' .
+ 'LEFT JOIN pay_batch USING ( batchnum )' .
+ $search;
+
+#grr
+$sql_query = "SELECT paybatchnum,invnum,custnum,cpb.last,cpb.first," .
+ "cpb.payname,cpb.payinfo,cpb.exp,amount,cpb.status " .
+ "FROM cust_pay_batch AS cpb " .
+ 'LEFT JOIN cust_main USING ( custnum ) ' .
+ 'LEFT JOIN pay_batch USING ( batchnum ) ' .
+ "$search ORDER BY $orderby";
+
+my $html_init = '';
+if ( $pay_batch ) {
+ my $fixed = $conf->config('batch-fixed_format-'. $pay_batch->payby);
+ if (
+ $pay_batch->status eq 'O'
+ || ( $pay_batch->status eq 'I'
+ && $FS::CurrentUser::CurrentUser->access_right('Reprocess batches')
+ )
+ ) {
+ $html_init .= qq!<FORM ACTION="$p/misc/download-batch.cgi" METHOD="POST">!;
+ if ( $fixed ) {
+ $html_init .= qq!<INPUT TYPE="hidden" NAME="format" VALUE="$fixed">!;
+ } else {
+ $html_init .= qq!Download batch in format <SELECT NAME="format">!.
+ qq!<OPTION VALUE="">Default batch mode</OPTION>!.
+ qq!<OPTION VALUE="csv-td_canada_trust-merchant_pc_batch">CSV file for TD Canada Trust Merchant PC Batch</OPTION>!.
+ qq!<OPTION VALUE="csv-chase_canada-E-xactBatch">CSV file for Chase Canada E-xactBatch</OPTION>!.
+ qq!<OPTION VALUE="PAP">80 byte file for TD Canada Trust PAP Batch</OPTION>!.
+ qq!<OPTION VALUE="BoM">Bank of Montreal ECA batch</OPTION>!.
+ qq!<OPTION VALUE="ach-spiritone">Spiritone ACH batch</OPTION>!.
+ qq!</SELECT>!;
+ }
+ $html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum"><INPUT TYPE="submit" VALUE="Download"></FORM><BR>!;
+ }
+
+ if (
+ $pay_batch->status eq 'I'
+ || ( $pay_batch->status eq 'R'
+ && $FS::CurrentUser::CurrentUser->access_right('Reprocess batches')
+ )
+ ) {
+ $html_init .= qq!<FORM ACTION="$p/misc/upload-batch.cgi" METHOD="POST" ENCTYPE="multipart/form-data">!.
+ qq!Upload results<BR>!.
+ qq!Filename <INPUT TYPE="file" NAME="batch_results"><BR>!;
+ if ( $fixed ) {
+ $html_init .= qq!<INPUT TYPE="hidden" NAME="format" VALUE="$fixed">!;
+ } else {
+ $html_init .= qq!Format <SELECT NAME="format">!.
+ qq!<OPTION VALUE="">Default batch mode</OPTION>!.
+ qq!<OPTION VALUE="csv-td_canada_trust-merchant_pc_batch">CSV results from TD Canada Trust Merchant PC Batch</OPTION>!.
+ qq!<OPTION VALUE="csv-chase_canada-E-xactBatch">CSV file for Chase Canada E-xactBatch</OPTION>!.
+ qq!<OPTION VALUE="PAP">264 byte results for TD Canada Trust PAP Batch</OPTION>!.
+ qq!<OPTION VALUE="BoM">Bank of Montreal ECA results</OPTION>!.
+ qq!<OPTION VALUE="ach-spiritone">Spiritone ACH batch</OPTION>!.
+ qq!</SELECT><BR>!;
+ }
+ $html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum">!;
+ $html_init .= '<INPUT TYPE="submit" VALUE="Upload"></FORM><BR>';
+ }
+
+}
+
+if ($pay_batch) {
+ my $sth = dbh->prepare($count_query) or die dbh->errstr. "doing $count_query";
+ $sth->execute or die "Error executing \"$count_query\": ". $sth->errstr;
+ my $cards = $sth->fetchrow_arrayref->[0];
+
+ my $st = "SELECT SUM(amount) from cust_pay_batch WHERE batchnum=". $batchnum;
+ $sth = dbh->prepare($st) or die dbh->errstr. "doing $st";
+ $sth->execute or die "Error executing \"$st\": ". $sth->errstr;
+ my $total = $sth->fetchrow_arrayref->[0];
+
+ $html_init .= "$cards credit card payments batched<BR>\$" .
+ sprintf("%.2f", $total) ." total in batch<BR>";
+}
+
+</%init>
diff --git a/httemplate/search/cust_pay_pending.html b/httemplate/search/cust_pay_pending.html
new file mode 100755
index 000000000..f46e08ab1
--- /dev/null
+++ b/httemplate/search/cust_pay_pending.html
@@ -0,0 +1,57 @@
+<% include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay_pending',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'pending payment',
+ 'name_verb' => 'pending',
+ 'disable_link' => 1,
+ 'disable_by' => 1, #add otaker to cust_pay_pending?
+ 'html_init' => include('/elements/init_overlib.html'),
+ 'addl_header' => [ 'Time', 'Payment Status', ],
+ 'addl_fields' => [ sub { time2str('%r', shift->_date ) },
+ $status_sub,
+ ],
+ 'redirect_empty' => $redirect_empty,
+ )
+%>
+<%init>
+
+my %statusaction = (
+ 'new' => 'delete',
+ 'pending' => 'complete',
+ #'authorized' => '',
+ #'captured' => '',
+ #'declined' => '',
+ #wouldn't need to take action on a done state#'done'
+);
+
+my $edit_pending =
+ $FS::CurrentUser::CurrentUser->access_right('Edit customer pending payments');
+
+my $status_sub = sub {
+ my $pending = shift;
+ my $return = $pending->status;
+ my $action = $statusaction{$pending->status};
+ return $return unless $action && $edit_pending;
+ my $link = include('/elements/popup_link.html',
+ 'action' => $p. 'edit/cust_pay_pending.html'.
+ '?paypendingnum='. $pending->paypendingnum.
+ ";action=$action",
+ 'label' => $action,
+ 'color' => '#ff0000',
+ 'width' => 655,
+ 'height' => ( $action eq 'delete' ? 480 : 575 ),
+ 'actionlabel' => ucfirst($action). ' pending payment',
+ );
+ $return. qq! <FONT SIZE="-1">($link)</FONT>!;
+};
+
+my $redirect_empty = sub {
+ my $cgi = shift;
+ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ $p. "view/cust_main.cgi?$1";
+ } else {
+ '';
+ }
+};
+
+</%init>
diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi
new file mode 100755
index 000000000..bd4a9466f
--- /dev/null
+++ b/httemplate/search/cust_pkg.cgi
@@ -0,0 +1,233 @@
+<% include( 'elements/search.html',
+ 'html_init' => $html_init,
+ 'title' => 'Package Search Results',
+ 'name' => 'packages',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ #'redirect' => $link,
+ 'header' => [ '#',
+ 'Quan.',
+ 'Package',
+ 'Class',
+ 'Status',
+ 'Freq.',
+ 'Setup',
+ 'Last bill',
+ 'Next bill',
+ 'Adjourn',
+ 'Susp.',
+ 'Expire',
+ 'Cancel',
+ 'Reason',
+ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ ),
+ 'Services',
+ ],
+ 'fields' => [
+ 'pkgnum',
+ 'quantity',
+ sub { #my $part_pkg = $part_pkg{shift->pkgpart};
+ #$part_pkg->pkg; # ' - '. $part_pkg->comment;
+ $_[0]->pkg; # ' - '. $_[0]->comment;
+ },
+ 'classname',
+ sub { ucfirst(shift->status); },
+ sub { #shift->part_pkg->freq_pretty;
+
+ #my $part_pkg = $part_pkg{shift->pkgpart};
+ #$part_pkg->freq_pretty;
+
+ FS::part_pkg::freq_pretty(shift);
+ },
+
+ #sub { time2str('%b %d %Y', shift->setup); },
+ #sub { time2str('%b %d %Y', shift->last_bill); },
+ #sub { time2str('%b %d %Y', shift->bill); },
+ #sub { time2str('%b %d %Y', shift->susp); },
+ #sub { time2str('%b %d %Y', shift->expire); },
+ #sub { time2str('%b %d %Y', shift->get('cancel')); },
+ ( map { time_or_blank($_) }
+ qw( setup last_bill bill adjourn susp expire cancel ) ),
+
+ sub { my $self = shift;
+ my $return = '';
+ foreach my $action ( qw ( cancel susp ) ) {
+ my $reason = $self->last_reason($action);
+ $return = $reason->reason if $reason;
+ last if $return;
+ }
+ $return;
+ },
+
+ \&FS::UI::Web::cust_fields,
+ #sub { '<table border=0 cellspacing=0 cellpadding=0 STYLE="border:none">'.
+ # join('', map { '<tr><td align="right" style="border:none">'. $_->[0].
+ # ':</td><td style="border:none">'. $_->[1]. '</td></tr>' }
+ # shift->labels
+ # ).
+ # '</table>';
+ # },
+ sub {
+ [ map {
+ [
+ { 'data' => $_->[0]. ':',
+ 'align'=> 'right',
+ },
+ { 'data' => $_->[1],
+ 'align'=> 'left',
+ 'link' => $p. 'view/' .
+ $_->[2]. '.cgi?'. $_->[3],
+ },
+ ];
+ } shift->labels
+ ];
+ },
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ sub { shift->statuscolor; },
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ '',
+ ],
+ 'style' => [ '', '', '', '', 'b', '', '', '', '', '', '', '', '', '',
+ FS::UI::Web::cust_styles() ],
+ 'size' => [ '', '', '', '', '-1' ],
+ 'align' => 'rrlcclrrrrrrrl'. FS::UI::Web::cust_aligns(). 'r',
+ 'links' => [
+ $link,
+ $link,
+ $link,
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ )
+ ),
+ '',
+ ],
+ 'extra_choices_callback'=> $extra_choices,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages');
+
+# my %part_pkg = map { $_->pkgpart => $_ } qsearch('part_pkg', {});
+
+ my %search_hash = ();
+
+ $search_hash{'query'} = $cgi->keywords;
+
+ for my $param (qw(agentnum magic status classnum pkgpart)) {
+ $search_hash{$param} = $cgi->param($param)
+ if $cgi->param($param);
+ }
+
+###
+# parse dates
+###
+
+#false laziness w/report_cust_pkg.html
+my %disable = (
+ 'all' => {},
+ 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, },
+ 'active' => { 'susp'=>1, 'cancel'=>1 },
+ 'suspended' => { 'cancel' => 1 },
+ 'cancelled' => {},
+ '' => {},
+);
+
+foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
+
+ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
+
+ next if $beginning == 0 && $ending == 4294967295
+ or $disable{$cgi->param('status')}->{$field};
+
+ $search_hash{$field} = [ $beginning, $ending ];
+
+}
+
+my $sql_query = FS::cust_pkg->search_sql(\%search_hash);
+my $count_query = delete($sql_query->{'count_query'});
+
+my $link = sub {
+ [ "${p}view/cust_main.cgi?".shift->custnum.'#cust_pkg', 'pkgnum' ];
+};
+
+my $clink = sub {
+ my $cust_pkg = shift;
+ $cust_pkg->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+ : '';
+};
+
+#if ( scalar(@cust_pkg) == 1 ) {
+# print $cgi->redirect("${p}view/cust_main.cgi?". $cust_pkg[0]->custnum.
+# "#cust_pkg". $cust_pkg[0]->pkgnum );
+
+# my @cust_svc = qsearch( 'cust_svc', { 'pkgnum' => $pkgnum } );
+# my $rowspan = scalar(@cust_svc) || 1;
+
+# my $n2 = '';
+# foreach my $cust_svc ( @cust_svc ) {
+# my($label, $value, $svcdb) = $cust_svc->label;
+# my $svcnum = $cust_svc->svcnum;
+# my $sview = $p. "view";
+# print $n2,qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$label</FONT></A></TD>!,
+# qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$value</FONT></A></TD>!;
+# $n2="</TR><TR>";
+# }
+
+sub time_or_blank {
+ my $column = shift;
+ return sub {
+ my $record = shift;
+ my $value = $record->get($column); #mmm closures
+ $value ? time2str('%b %d %Y', $value ) : '';
+ };
+}
+
+my $html_init = include('/elements/init_overlib.html');
+
+my $extra_choices = sub {
+ my $query = shift;
+
+ return '' unless
+ $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages');
+
+ '<BR><BR>'.
+ include( '/elements/popup_link.html',
+ 'label' => 'Change these packages',
+ 'action' => "${p}misc/bulk_change_pkg.cgi?$query",
+ 'actionlabel' => 'Change Packages',
+ 'width' => 763,
+ 'height' => 336,
+ );
+};
+
+</%init>
diff --git a/httemplate/search/cust_refund.html b/httemplate/search/cust_refund.html
new file mode 100644
index 000000000..e31e088eb
--- /dev/null
+++ b/httemplate/search/cust_refund.html
@@ -0,0 +1,7 @@
+<% include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'refund',
+ 'amount_field' => 'refund',
+ 'name_singular' => 'refund',
+ 'name_verb' => 'refunded',
+ )
+%>
diff --git a/httemplate/search/cust_svc.html b/httemplate/search/cust_svc.html
new file mode 100644
index 000000000..3beca4d83
--- /dev/null
+++ b/httemplate/search/cust_svc.html
@@ -0,0 +1,138 @@
+<% include( 'elements/search.html',
+ 'title' => 'Service search results',
+ 'name' => 'services',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ # package?
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ sub {
+ #$_[0]->svc. ': '. $_[0]->label;
+ my($label, $value, $svcdb) = $_[0]->label;
+ "$label: $value";
+ },
+ # package?
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ # package?
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rl'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $addl_from = ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+my @extra_sql = ();
+my $orderby = 'ORDER BY svcnum'; #has to be ordered by something
+ #for pagination to work
+if ( length( $cgi->param('search_svc') ) ) {
+
+ my $string = $cgi->param('search_svc');
+ $string =~ s/(^\s+|\s+$)//; #trim leading & trailing whitespace
+
+ # implement fuzzy searching in subclasses too at some point?
+ # service searching maybe shouldn't be fuzzy...
+
+ push @extra_sql,
+ ' ( '. join(' OR ',
+ map { my $table = $_;
+ my $search_sql = "FS::$table"->search_sql($string);
+ " ( svcdb = '$table'
+ AND 0 < ( SELECT COUNT(*) FROM $table
+ WHERE $table.svcnum = cust_svc.svcnum
+ AND $search_sql
+ )
+ ) ";
+ }
+ FS::part_svc->svc_tables
+ ). ' ) ';
+
+} elsif ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ $cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unknown svcdb";
+ push @extra_sql, "svcdb = '$1'";
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+
+ push @extra_sql, "svcpart = $1";
+
+} else {
+ errorpage("No search term specified");
+}
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $extra_sql = ' WHERE '. join(' AND ', @extra_sql );
+
+my $sql_query = {
+ 'select' => join(', ',
+ 'cust_svc.*',
+ 'part_svc.*',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'table' => 'cust_svc',
+ 'addl_from' => $addl_from,
+ 'hashref' => {},
+ 'extra_sql' => "$extra_sql $orderby",
+};
+
+my $count_query = "SELECT COUNT(*) FROM cust_svc $addl_from $extra_sql";
+
+my $link = sub {
+ my $cust_svc = shift;
+ my $url = svc_url(
+ 'm' => $m,
+ 'action' => 'view',
+ #'part_svc' => $cust_svc->part_svc,
+ 'svcdb' => $cust_svc->svcdb, #we have it from the joined search
+ #'svc' => $cust_svc, #redundant
+ 'query' => '',
+ );
+ [ $url, 'svcnum' ];
+};
+
+my $link_cust = sub {
+ my $cust_svc = shift;
+ if ( $cust_svc->custnum ) {
+ [ "${p}view/cust_main.cgi?", 'custnum' ];
+ } else {
+ '';
+ }
+};
+
+</%init>
diff --git a/httemplate/search/cust_tax_exempt.cgi b/httemplate/search/cust_tax_exempt.cgi
new file mode 100644
index 000000000..3704b208a
--- /dev/null
+++ b/httemplate/search/cust_tax_exempt.cgi
@@ -0,0 +1,139 @@
+<% include( 'elements/search.html',
+ 'title' => 'Legacy tax exemptions',
+ 'name' => 'legacy tax exemptions',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ $money_char. '%.2f total', ],
+ 'header' => [
+ '#',
+ 'Month',
+ 'Inserted',
+ 'Amount',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'exemptnum',
+ sub { $_[0]->month. '/'. $_[0]->year; },
+ sub { my $h = $_[0]->h_search('insert');
+ $h ? time2str('%L/%d/%Y', $h->history_date ) : ''
+ },
+ sub { $money_char. $_[0]->amount; },
+
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [
+ '',
+ '',
+ '',
+ '',
+
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rrrr'.FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+my $join_cust = "
+ LEFT JOIN cust_main USING ( custnum )
+";
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer tax exemptions');
+
+my @where = ();
+
+#my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+#if ( $beginning || $ending ) {
+# push @where, "_date >= $beginning",
+# "_date <= $ending";
+# #"payby != 'COMP';
+#}
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @where, "agentnum = $1";
+}
+
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @where, "cust_main.custnum = $1";
+}
+
+#prospect active inactive suspended cancelled
+if ( grep { $cgi->param('status') eq $_ } FS::cust_main->statuses() ) {
+ my $method = $cgi->param('status'). '_sql';
+ #push @where, $class->$method();
+ push @where, FS::cust_main->$method();
+}
+
+if ( $cgi->param('out') ) {
+
+ push @where, "
+ 0 = (
+ SELECT COUNT(*) FROM cust_main_county AS county_out
+ WHERE ( county_out.county = cust_main.county
+ OR ( county_out.county IS NULL AND cust_main.county = '' )
+ OR ( county_out.county = '' AND cust_main.county IS NULL)
+ OR ( county_out.county IS NULL AND cust_main.county IS NULL)
+ )
+ AND ( county_out.state = cust_main.state
+ OR ( county_out.state IS NULL AND cust_main.state = '' )
+ OR ( county_out.state = '' AND cust_main.state IS NULL )
+ OR ( county_out.state IS NULL AND cust_main.state IS NULL )
+ )
+ AND county_out.country = cust_main.country
+ AND county_out.tax > 0
+ )
+ ";
+
+} elsif ( $cgi->param('country' ) ) {
+
+ my $county = dbh->quote( $cgi->param('county') );
+ my $state = dbh->quote( $cgi->param('state') );
+ my $country = dbh->quote( $cgi->param('country') );
+ push @where, "( county = $county OR $county = '' )",
+ "( state = $state OR $state = '' )",
+ " country = $country";
+ push @where, 'taxclass = '. dbh->quote( $cgi->param('taxclass') )
+ if $cgi->param('taxclass');
+
+}
+
+my $where = scalar(@where) ? 'WHERE '.join(' AND ', @where) : '';
+
+my $count_query = "SELECT COUNT(*), SUM(amount)".
+ " FROM cust_tax_exempt $join_cust $where";
+
+my $query = {
+ 'table' => 'cust_tax_exempt',
+ 'addl_from' => $join_cust,
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'cust_tax_exempt.*',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $where,
+};
+
+my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/search/cust_tax_exempt.html b/httemplate/search/cust_tax_exempt.html
new file mode 100644
index 000000000..612ad7e2a
--- /dev/null
+++ b/httemplate/search/cust_tax_exempt.html
@@ -0,0 +1,31 @@
+<% include('/elements/header.html', 'Legacy tax exemption report' ) %>
+
+<FORM ACTION="cust_tax_exempt.cgi" METHOD="GET">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Search options</FONT></TH>
+ </TR>
+
+ <% include( '/elements/tr-select-cust_main-status.html',
+ 'label' => 'Customer Status'
+ )
+ %>
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer tax exemptions');
+
+</%init>
+
diff --git a/httemplate/search/cust_tax_exempt_pkg.cgi b/httemplate/search/cust_tax_exempt_pkg.cgi
new file mode 100644
index 000000000..3a5155ae8
--- /dev/null
+++ b/httemplate/search/cust_tax_exempt_pkg.cgi
@@ -0,0 +1,182 @@
+<% include( 'elements/search.html',
+ 'title' => 'Tax exemptions',
+ 'name' => 'tax exemptions',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ $money_char. '%.2f total', ],
+ 'header' => [
+ '#',
+ 'Month',
+ 'Amount',
+ 'Line item',
+ 'Invoice',
+ 'Date',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'exemptpkgnum',
+ sub { $_[0]->month. '/'. $_[0]->year; },
+ sub { $money_char. $_[0]->amount; },
+
+ sub {
+ $_[0]->billpkgnum. ': '.
+ ( $_[0]->pkgnum > 0
+ ? $_[0]->get('pkg')
+ : $_[0]->get('itemdesc')
+ ).
+ ' ('.
+ ( $_[0]->setup > 0
+ ? $money_char. $_[0]->setup. ' setup'
+ : ''
+ ).
+ ( $_[0]->setup > 0 && $_[0]->recur > 0
+ ? ' / '
+ : ''
+ ).
+ ( $_[0]->recur > 0
+ ? $money_char. $_[0]->recur. ' recur'
+ : ''
+ ).
+ ')';
+ },
+
+ 'invnum',
+ sub { time2str('%b %d %Y', shift->_date ) },
+
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [
+ '',
+ '',
+ '',
+
+ '',
+ $ilink,
+ $ilink,
+
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rrrlrc'.FS::UI::Web::cust_aligns(), # 'rlrrrc',
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%once>
+
+my $join_cust = "
+ JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum )
+";
+
+my $join_pkg = "
+ LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN part_pkg USING ( pkgpart )
+";
+
+my $join = "
+ JOIN cust_bill_pkg USING ( billpkgnum )
+ $join_cust
+ $join_pkg
+";
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer tax exemptions');
+
+my @where = ();
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+if ( $beginning || $ending ) {
+ push @where, "_date >= $beginning",
+ "_date <= $ending";
+ #"payby != 'COMP';
+}
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @where, "cust_main.agentnum = $1";
+}
+
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @where, "cust_main.custnum = $1";
+}
+
+if ( $cgi->param('out') ) {
+
+ push @where, "
+ 0 = (
+ SELECT COUNT(*) FROM cust_main_county AS county_out
+ WHERE ( county_out.county = cust_main.county
+ OR ( county_out.county IS NULL AND cust_main.county = '' )
+ OR ( county_out.county = '' AND cust_main.county IS NULL)
+ OR ( county_out.county IS NULL AND cust_main.county IS NULL)
+ )
+ AND ( county_out.state = cust_main.state
+ OR ( county_out.state IS NULL AND cust_main.state = '' )
+ OR ( county_out.state = '' AND cust_main.state IS NULL )
+ OR ( county_out.state IS NULL AND cust_main.state IS NULL )
+ )
+ AND county_out.country = cust_main.country
+ AND county_out.tax > 0
+ )
+ ";
+
+} elsif ( $cgi->param('country' ) ) {
+
+ my $county = dbh->quote( $cgi->param('county') );
+ my $state = dbh->quote( $cgi->param('state') );
+ my $country = dbh->quote( $cgi->param('country') );
+ push @where, "( county = $county OR $county = '' )",
+ "( state = $state OR $state = '' )",
+ " country = $country";
+ push @where, 'taxclass = '. dbh->quote( $cgi->param('taxclass') )
+ if $cgi->param('taxclass');
+
+}
+
+my $where = scalar(@where) ? 'WHERE '.join(' AND ', @where) : '';
+
+my $count_query = "SELECT COUNT(*), SUM(amount)".
+ " FROM cust_tax_exempt_pkg $join $where";
+
+my $query = {
+ 'table' => 'cust_tax_exempt_pkg',
+ 'addl_from' => $join,
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'cust_tax_exempt_pkg.*',
+ 'cust_bill_pkg.*',
+ 'cust_bill.*',
+ 'part_pkg.pkg',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $where,
+};
+
+my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ];
+my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
new file mode 100755
index 000000000..add8427ca
--- /dev/null
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -0,0 +1,301 @@
+<%doc>
+
+Examples:
+
+ include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'payment',
+ 'name_verb' => 'paid',
+ )
+
+ include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'refund',
+ 'amount_field' => 'refund',
+ 'name_singular' => 'refund',
+ 'name_verb' => 'refunded',
+ )
+
+ include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay_pending',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'pending payment',
+ 'name_verb' => 'pending',
+ 'disable_link' => 1,
+ 'disable_by' => 1,
+ 'html_init' => '',
+ 'addl_header' => [],
+ 'addl_fields' => [],
+ 'redirect_empty' => $redirect_empty,
+ )
+
+</%doc>
+<% include( 'search.html',
+ 'title' => $title,
+ 'name_singular' => $name_singular,
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ '$%.2f total '.$opt{name_verb}, ],
+ 'redirect_empty' => $opt{'redirect_empty'},
+ 'header' => [ "\u$name_singular",
+ 'Amount',
+ 'Date',
+ @header,
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'payby_payinfo_pretty',
+ sub { sprintf('$%.2f', shift->$amount_field() ) },
+ sub { time2str('%b %d %Y', shift->_date ) },
+ @fields,
+ \&FS::UI::Web::cust_fields,
+ ],
+ #'align' => 'lrrrll',
+ 'align' => 'rrr'.
+ join('', map 'c', @fields ).
+ FS::UI::Web::cust_aligns(),
+ 'links' => [
+ $link,
+ $link,
+ $link,
+ ( map '', @fields ),
+ ( map { $_ ne 'Cust. Status' ? $cust_link : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ ( map '', @fields ),
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ ( map '', @fields ),
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+my %opt = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Financial reports');
+
+my $thing = $opt{'thing'};
+my $amount_field = $opt{'amount_field'};
+my $name_singular = $opt{'name_singular'};
+
+my $title = "\u$name_singular Search Results";
+
+my @header = ();
+my @fields = ();
+unless ( $opt{'disable_by'} ) {
+ push @header, 'By';
+ push @fields, sub { my $o = shift->otaker;
+ $o = 'auto billing' if $o eq 'fs_daily';
+ $o = 'customer self-service' if $o eq 'fs_selfservice';
+ $o;
+ };
+}
+
+push @header, @{ $opt{'addl_header'} }
+ if $opt{'addl_header'};
+push @fields, @{ $opt{'addl_fields'} }
+ if $opt{'addl_fields'};
+
+my( $count_query, $sql_query );
+if ( $cgi->param('magic') ) {
+
+ my @search = ();
+ my $orderby;
+ if ( $cgi->param('magic') eq '_date' ) {
+
+
+ if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ push @search, "agentnum = $1"; # $search{'agentnum'} = $1;
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "unknown agentnum $1" unless $agent;
+ $title = $agent->agent. " $title";
+ }
+
+ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @search, "custnum = $1";
+ }
+
+ if ( $cgi->param('payby') ) {
+ $cgi->param('payby') =~
+ /^(CARD|CHEK|BILL|PREP|CASH|WEST|MCRD)(-(VisaMC|Amex|Discover|Maestro))?$/
+ or die "illegal payby ". $cgi->param('payby');
+ push @search, "cust_$thing.payby = '$1'";
+ if ( $3 ) {
+
+ my $cardtype = $3;
+
+ my $search;
+ if ( $cardtype eq 'VisaMC' ) {
+ #avoid posix regexes for portability
+ $search =
+ " ( ( substring(cust_$thing.payinfo from 1 for 1) = '4' ".
+ " AND substring(cust_$thing.payinfo from 1 for 4) != '4936' ".
+ " AND substring(cust_$thing.payinfo from 1 for 6) ".
+ " NOT SIMILAR TO '49030[2-9]' ".
+ " AND substring(cust_$thing.payinfo from 1 for 6) ".
+ " NOT SIMILAR TO '49033[5-9]' ".
+ " AND substring(cust_$thing.payinfo from 1 for 6) ".
+ " NOT SIMILAR TO '49110[1-2]' ".
+ " AND substring(cust_$thing.payinfo from 1 for 6) ".
+ " NOT SIMILAR TO '49117[4-9]' ".
+ " AND substring(cust_$thing.payinfo from 1 for 6) ".
+ " NOT SIMILAR TO '49118[1-2]' ".
+ " )".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '51' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '52' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '53' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '54' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '54' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '55' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2) = '36' ". #Diner's int'l processed as Visa/MC inside US
+ " ) ";
+ } elsif ( $cardtype eq 'Amex' ) {
+ $search =
+ " ( substring(cust_$thing.payinfo from 1 for 2 ) = '34' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2 ) = '37' ".
+ " ) ";
+ } elsif ( $cardtype eq 'Discover' ) {
+ $search =
+ " ( substring(cust_$thing.payinfo from 1 for 4 ) = '6011' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2 ) = '65' ".
+ " OR substring(cust_$thing.payinfo from 1 for 3 ) = '622' ". #China Union Pay processed as Discover outside CN
+ " ) ";
+ } elsif ( $cardtype eq 'Maestro' ) {
+ $search =
+ " ( substring(cust_$thing.payinfo from 1 for 2 ) = '63' ".
+ " OR substring(cust_$thing.payinfo from 1 for 2 ) = '67' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) = '564182' ".
+ " OR substring(cust_$thing.payinfo from 1 for 4 ) = '4936' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) ".
+ " SIMILAR TO '49030[2-9]' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) ".
+ " SIMILAR TO '49033[5-9]' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) ".
+ " SIMILAR TO '49110[1-2]' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) ".
+ " SIMILAR TO '49117[4-9]' ".
+ " OR substring(cust_$thing.payinfo from 1 for 6 ) ".
+ " SIMILAR TO '49118[1-2]' ".
+ " ) ";
+ } else {
+ die "unknown card type $cardtype";
+ }
+
+ my $masksearch = $search;
+ $masksearch =~ s/cust_$thing\.payinfo/cust_$thing.paymask/gi;
+
+ push @search,
+ "( $search OR ( cust_$thing.paymask IS NOT NULL AND $masksearch ) )";
+
+ }
+ }
+
+ if ( $cgi->param('payinfo') ) {
+ $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/
+ or die "illegal payinfo ". $cgi->param('payinfo');
+ push @search, "cust_$thing.payinfo = '$1'";
+ }
+
+ #for cust_pay_pending... statusNOT=done
+ if ( $cgi->param('statusNOT') =~ /^(\w+)$/ ) {
+ push @search, "status != '$1'";
+ }
+
+ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+ push @search, "_date >= $beginning ",
+ "_date <= $ending";
+
+ push @search, FS::UI::Web::parse_lt_gt($cgi, $amount_field );
+
+ $orderby = '_date';
+
+ } elsif ( $cgi->param('magic') eq 'paybatch' ) {
+
+ $cgi->param('paybatch') =~ /^([\w\/\:\-\.]+)$/
+ or die "illegal paybatch: ". $cgi->param('paybatch');
+
+ push @search, "paybatch = '$1'";
+
+ $orderby = "LOWER(company || ' ' || last || ' ' || first )";
+
+ } else {
+ die "unknown search magic: ". $cgi->param('magic');
+ }
+
+ #here is the agent virtualization
+ push @search, $curuser->agentnums_sql;
+
+ my $search = ' WHERE '. join(' AND ', @search);
+
+ $count_query = "SELECT COUNT(*), SUM($amount_field) ".
+ "FROM cust_$thing LEFT JOIN cust_main USING ( custnum )".
+ $search;
+
+ $sql_query = {
+ 'table' => "cust_$thing",
+ 'select' => join(', ',
+ "cust_$thing.*",
+ 'cust_main.custnum as cust_main_custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => "$search ORDER BY $orderby",
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ };
+
+} else {
+
+ #hmm... is this still used?
+
+ $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/ or die "illegal payinfo";
+ my $payinfo = $1;
+
+ $cgi->param('payby') =~ /^(\w+)$/ or die "illegal payby";
+ my $payby = $1;
+
+ $count_query = "SELECT COUNT(*), SUM($amount_field) FROM cust_$thing".
+ " WHERE payinfo = '$payinfo' AND payby = '$payby'".
+ " AND ". $curuser->agentnums_sql;
+
+ $sql_query = {
+ 'table' => "cust_$thing",
+ 'hashref' => { 'payinfo' => $payinfo,
+ 'payby' => $payby },
+ 'extra_sql' => $curuser->agentnums_sql.
+ " ORDER BY _date",
+ };
+
+}
+
+my $link = '';
+if ( ( $curuser->access_right('View invoices') #XXX for now
+ || $curuser->access_right('View customer payments')
+ )
+ && ! $opt{'disable_link'}
+ )
+{
+ $link = [ "${p}view/cust_$thing.html?${thing}num=", $thing.'num' ]
+}
+
+my $cust_link = sub {
+ my $cust_thing = shift;
+ $cust_thing->cust_main_custnum
+ ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+ : '';
+};
+
+</%init>
diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html
new file mode 100644
index 000000000..8835f8cae
--- /dev/null
+++ b/httemplate/search/elements/search.html
@@ -0,0 +1,912 @@
+<%doc>
+
+Example:
+
+ include( 'elements/search.html',
+
+ ###
+ # required
+ ###
+
+ 'title' => 'Page title',
+
+ 'name_singular' => 'item', #singular name for the records returned
+ #OR# # (preferred, will be pluralized automatically)
+ 'name' => 'items', #plural name for the records returned
+ # (deprecated, will be singularlized
+ # simplisticly)
+
+ #literal SQL query string (deprecated?) or qsearch hashref
+ 'query' => {
+ 'table' => 'tablename',
+ #everything else is optional...
+ 'hashref' => { 'field' => 'value',
+ 'field' => { 'op' => '<',
+ 'value' => '54',
+ },
+ },
+ 'select' => '*',
+ 'addl_from' => '', #'LEFT JOIN othertable USING ( key )',
+ 'extra_sql' => '', #'AND otherstuff', #'WHERE onlystuff',
+ 'order_by' => 'ORDER BY something',
+
+ },
+ # "select * from tablename";
+
+ #required unless 'query' is an SQL query string (shouldn't be...)
+ 'count_query' => 'SELECT COUNT(*) FROM tablename',
+
+ ###
+ # recommended / common
+ ###
+
+ #listref of column labels, <TH>
+ #recommended unless 'query' is an SQL query string
+ # (if not specified the database column names will be used)
+ 'header' => [ '#',
+ 'Item',
+ { 'label' => 'Another Item',
+
+ },
+ ],
+
+ #listref - each item is a literal column name (or method) or coderef
+ #if not specified all columns will be shown
+ 'fields' => [
+ 'column',
+ sub { my $row = shift; $row->column; },
+ ],
+
+ #redirect if there's only one item...
+ # listref of URL base and column name (or method)
+ # or a coderef that returns the same
+ 'redirect' => sub { my( $record, $cgi ) = @_;
+ [ popurl(2).'view/item.html', 'primary_key' ];
+ },
+
+ #redirect if there's no items
+ # scalar URL or a coderef that returns a URL
+ 'redirect_empty' => sub { my( $cgi ) = @_;
+ popurl(2).'view/item.html';
+ },
+
+ ###
+ # optional
+ ###
+
+ # some HTML callbacks...
+ 'menubar' => '', #menubar arrayref
+ 'html_init' => '', #after the header/menubar and before the pager
+ 'html_form' => '', #after the pager, right before the results
+ # (only shown if there are results)
+ # (use this for any form-opening tag rather than
+ # html_init, to avoid a nested form)
+ 'html_foot' => '', #at the bottom
+ 'html_posttotal' => '', #at the bottom
+ # (these three can be strings or coderefs)
+
+ 'count_addl' => [], #additional count fields listref of sprintf strings or coderefs
+ # [ $money_char.'%.2f total paid', ],
+
+ #second (smaller) header line, currently only for HTML
+ 'header2 => [ '#',
+ 'Item',
+ { 'label' => 'Another Item',
+
+ },
+ ],
+
+ #listref of column footers
+ 'footer' => [],
+
+ #disabling things
+ 'disable_download' => '', # set true to hide the CSV/Excel download links
+ 'disable_total' => '', # set true to hide the total"
+ 'disable_maxselect' => '', # set true to disable record/page selection
+ 'disable_nonefound' => '', # set true to disable the "No matching Xs found"
+ # message
+
+ #handling "disabled" fields in the records
+ 'disableable' => 1, # set set to 1 (or column position for "disabled"
+ # status col) to enable if this table has a "disabled"
+ # field, to hide disabled records & have
+ # "show disabled/hide disabled" links
+ #(can't be used with a literal query)
+ 'disabled_statuspos' => 3, #optional position (starting from 0) to insert
+ #a Status column when showing disabled records
+ #(query needs to be a qsearch hashref and
+ # header & fields need to be defined)
+
+ #handling agent virtualization
+ 'agent_virt' => 1, # set true if this search should be
+ # agent-virtualized
+ 'agent_null_right' => 'Access Right', # optional right to view global
+ # records
+ 'agent_null_right_link' => 'Access Right' # optional right to link to
+ # global records; defaults to
+ # same as agent_null_right
+ 'agent_pos' => 3, # optional position (starting from 0) to
+ # insert an Agent column (query needs to be a
+ # qsearch hashref and header & fields need to
+ # be defined)
+
+ # link & display properties for fields
+
+ #listref - each item is the empty string,
+ # or a listref of link and method name to append,
+ # or a listref of link and coderef to run and append
+ # or a coderef that returns such a listref
+ 'links' => [],`
+
+ #listref - each item is the empty string,
+ # or a string onClick handler for the corresponding link
+ # or a coderef that returns string onClick handler
+ 'link_onclicks' => [],
+
+ #one letter for each column, left/right/center/none
+ # or pass a listref with full values: [ 'left', 'right', 'center', '' ]
+ 'align' => 'lrc.',
+
+ #listrefs of ( scalars or coderefs )
+ #currently only HTML, maybe eventually Excel too
+ 'color' => [],
+ 'size' => [],
+ 'style' => [], #<B> or <I>, etc.
+ 'cell_style' => [], #STYLE= attribute of TR, very HTML-specific...
+
+ );
+
+</%doc>
+% if ( $type eq 'csv' ) {
+%
+% #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+% http_header('Content-Type' => 'text/plain' );
+%
+% my $csv = new Text::CSV_XS { 'always_quote' => 1,
+% 'eol' => "\n", #"\015\012", #"\012"
+% };
+%
+% $csv->combine(@$header); #or die $csv->status;
+%
+<% $csv->string %>
+%
+%
+% foreach my $row ( @$rows ) {
+%
+% if ( $opt{'fields'} ) {
+%
+% my @line = ();
+%
+% foreach my $field ( @{$opt{'fields'}} ) {
+% if ( ref($field) eq 'CODE' ) {
+% push @line, map {
+% ref($_) eq 'ARRAY'
+% ? '(N/A)' #unimplemented
+% : $_;
+% }
+% &{$field}($row);
+% } else {
+% push @line, $row->$field();
+% }
+% }
+%
+% $csv->combine(@line); #or die $csv->status;
+%
+% } else {
+% $csv->combine(@$row); #or die $csv->status;
+% }
+%
+%
+<% $csv->string %>
+%
+%
+% }
+%
+% #} elsif ( $type eq 'excel' ) {
+% } elsif ( $type =~ /\.xls$/ ) {
+%
+% #http_header('Content-Type' => 'application/excel' ); #eww
+% #http_header('Content-Type' => 'application/msexcel' ); #alas
+% #http_header('Content-Type' => 'application/x-msexcel' ); #?
+%
+% #http://support.microsoft.com/kb/199841
+% http_header('Content-Type' => 'application/vnd.ms-excel' );
+%
+% #http://support.microsoft.com/kb/812935
+% #http://support.microsoft.com/kb/323308
+% $HTML::Mason::Commands::r->headers_out->{'Cache-control'} = 'max-age=0';
+%
+% my $data = '';
+% my $XLS = new IO::Scalar \$data;
+% my $workbook = Spreadsheet::WriteExcel->new($XLS)
+% or die "Error opening .xls file: $!";
+%
+% my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
+%
+% my($r,$c) = (0,0);
+%
+% $worksheet->write($r, $c++, $_) foreach @$header;
+%
+% foreach my $row ( @$rows ) {
+% $r++;
+% $c = 0;
+%
+% if ( $opt{'fields'} ) {
+%
+% #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+% #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+%
+% foreach my $field ( @{$opt{'fields'}} ) {
+% #my $align = $aligns ? shift @$aligns : '';
+% #$align = " ALIGN=$align" if $align;
+% #my $a = '';
+% #if ( $links ) {
+% # my $link = shift @$links;
+% # $link = &{$link}($row) if ref($link) eq 'CODE';
+% # if ( $link ) {
+% # my( $url, $method ) = @{$link};
+% # if ( ref($method) eq 'CODE' ) {
+% # $a = $url. &{$method}($row);
+% # } else {
+% # $a = $url. $row->$method();
+% # }
+% # $a = qq(<A HREF="$a">);
+% # }
+% #}
+% if ( ref($field) eq 'CODE' ) {
+% foreach my $value ( &{$field}($row) ) {
+% if ( ref($value) eq 'ARRAY' ) {
+% $worksheet->write($r, $c++, '(N/A)' ); #unimplemented
+% } else {
+% $worksheet->write($r, $c++, $value );
+% }
+% }
+% } else {
+% $worksheet->write($r, $c++, $row->$field() );
+% }
+% }
+%
+% } else {
+% $worksheet->write($r, $c++, $_) foreach @$row;
+% }
+%
+% }
+%
+% $workbook->close();# or die "Error creating .xls file: $!";
+%
+% http_header('Content-Length' => length($data) );
+%
+<% $data %>
+%
+%
+% } else { # regular HTML
+%
+% if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1
+% && $type ne 'html-print'
+% ) {
+% my $redirect = $opt{'redirect'};
+% $redirect = &{$redirect}($rows->[0], $cgi) if ref($redirect) eq 'CODE';
+% my( $url, $method ) = @$redirect;
+% redirect( $url. $rows->[0]->$method() );
+% } elsif ( exists($opt{'redirect_empty'}) && ! scalar(@$rows) && $total == 0
+% && $type ne 'html-print'
+% && $opt{'redirect_empty'}
+% && ( ref($opt{'redirect_empty'}) ne 'CODE'
+% || &{$opt{'redirect_empty'}}($cgi) )
+% ) {
+% my $redirect = $opt{'redirect_empty'};
+% $redirect = &{$redirect}($cgi) if ref($redirect) eq 'CODE';
+% redirect( $redirect );
+% } else {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = PL($opt{'name_singular'});
+% }
+% ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
+% if ( $total == 1 ) {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = $opt{'name_singular'}
+% } else {
+% #$opt{'name'} =~ s/s$// if $total == 1;
+% $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1;
+% }
+% }
+%
+% if ( $type eq 'html-print' ) {
+
+ <% include( '/elements/header-popup.html', $opt{'title'} ) %>
+
+% } elsif ( $type eq 'select' ) {
+
+ <% include( '/elements/header-popup.html', $opt{'title'} ) %>
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
+
+% } else {
+%
+% my @menubar = ();
+% if ( $opt{'menubar'} ) {
+% @menubar = @{ $opt{'menubar'} };
+% #} else {
+% # @menubar = ( 'Main menu' => $p );
+% }
+
+ <% include( '/elements/header.html', $opt{'title'},
+ include( '/elements/menubar.html', @menubar )
+ )
+ %>
+
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
+
+% }
+
+% unless ( $total ) {
+% unless ( $opt{'disable_nonefound'} ) {
+ No matching <% $opt{'name'} %> found.<BR>
+% }
+% }
+%
+% if ( $total || $opt{'disableable'} ) { #hmm... and there *are* ones to show??
+
+ <TABLE>
+ <TR>
+
+ <TD VALIGN="bottom">
+
+ <FORM>
+
+% if (! $opt{'disable_total'}) {
+ <% $total %> total <% $opt{'name'} %>
+% }
+
+% if ( $confmax && $total > $confmax
+% && ! $opt{'disable_maxselect'}
+% && $type ne 'html-print' )
+% {
+% $cgi->delete('maxrecords');
+% $cgi->param('_dummy', 1);
+
+ ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $cgi->self_url %>;maxrecords=' + this.options[this.selectedIndex].value;">
+
+% foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
+ <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
+% }
+
+ </SELECT> per page )
+
+% $cgi->param('maxrecords', $maxrecords);
+% }
+
+% if ( defined($opt{'html_posttotal'}) && $type ne 'html-print' ) {
+ <% ref($opt{'html_posttotal'})
+ ? &{$opt{'html_posttotal'}}()
+ : $opt{'html_posttotal'}
+ %>
+% }
+ <BR>
+
+% if ( $opt{'count_addl'} ) {
+% my $n=0;
+% foreach my $count ( @{$opt{'count_addl'}} ) {
+% my $data = $count_arrayref->[++$n];
+% if ( ref($count) ) {
+ <% &{ $count }( $data ) %>
+% } else {
+ <% sprintf( $count, $data ) %><BR>
+% }
+% }
+% }
+ </FORM>
+
+ </TD>
+
+% unless ( $opt{'disable_download'} || $type eq 'html-print' ) {
+
+ <TD ALIGN="right">
+
+ Download full results<BR>
+
+% $cgi->param('_type', "$xlsname.xls" );
+ as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
+
+% $cgi->param('_type', 'csv');
+ as <A HREF="<% $cgi->self_url %>">CSV file</A><BR>
+
+% $cgi->param('_type', 'html-print');
+ as <A HREF="<% $cgi->self_url %>">printable copy</A>
+
+ <% $opt{'extra_choices_callback'}
+ ? &{$opt{'extra_choices_callback'}}($cgi->query_string)
+ : ''
+ %>
+
+ </TD>
+% $cgi->param('_type', "html" );
+% }
+
+ </TR>
+ <TR>
+ <TD COLSPAN=2>
+
+% my $pager = '';
+% unless ( $type eq 'html_print' ) {
+
+ <% $pager = include( '/elements/pager.html',
+ 'offset' => $offset,
+ 'num_rows' => scalar(@$rows),
+ 'total' => $total,
+ 'maxrecords' => $maxrecords,
+ )
+ %>
+
+ <% defined($opt{'html_form'})
+ ? ( ref($opt{'html_form'})
+ ? &{$opt{'html_form'}}()
+ : $opt{'html_form'}
+ )
+ : ''
+ %>
+
+% }
+
+ <% include('/elements/table-grid.html') %>
+
+ <TR>
+% my $h2 = 0;
+% foreach my $header ( @{ $opt{header} } ) {
+% my $label = ref($header) ? $header->{label} : $header;
+% my $rowspan = 1;
+% my $style = '';
+% if ( $opt{header2} ) {
+% if ( !length($opt{header2}->[$h2]) ) {
+% $rowspan = 2;
+% splice @{ $opt{header2} }, $h2, 1;
+% } else {
+% $h2++;
+% $style = 'STYLE="border-bottom: none"'
+% }
+% }
+ <TH CLASS = "grid"
+ BGCOLOR = "#cccccc"
+ ROWSPAN = "<% $rowspan %>"
+ <% $style %>
+
+ >
+ <% $label %>
+ </TH>
+% }
+ </TR>
+
+% if ( $opt{header2} ) {
+ <TR>
+% foreach my $header ( @{ $opt{header2} } ) {
+% my $label = ref($header) ? $header->{label} : $header;
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <FONT SIZE="-1"><% $label %></FONT>
+ </TH>
+% }
+ </TR>
+% }
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% foreach my $row ( @$rows ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+% if ( $opt{'fields'} ) {
+%
+% my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+% my $onclicks = $opt{'link_onclicks'} ? [ @{$opt{'link_onclicks'}} ] : [];
+% my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+% my $colors = $opt{'color'} ? [ @{$opt{'color'}} ] : [];
+% my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
+% my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : [];
+% my $cstyles = $opt{'cell_style'} ? [ @{$opt{'cell_style'}} ] : [];
+%
+% foreach my $field (
+%
+% map {
+% if ( ref($_) eq 'ARRAY' ) {
+%
+% my $tableref = $_;
+%
+% '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0 WIDTH="100%">'.
+%
+% join('', map {
+%
+% my $rowref = $_;
+%
+% '<tr>'.
+%
+% join('', map {
+%
+% my $e = $_;
+%
+% '<TD '.
+% join(' ', map {
+% uc($_).'="'. $e->{$_}. '"';
+% }
+% grep exists($e->{$_}),
+% qw( align bgcolor colspan rowspan
+% style valign width )
+% ).
+% '>'.
+%
+% ( $e->{'link'}
+% ? '<A HREF="'. $e->{'link'}. '">'
+% : ''
+% ).
+% ( $e->{'size'}
+% ? '<FONT SIZE="'.uc($e->{'size'}).'">'
+% : ''
+% ).
+% ( $e->{'data_style'}
+% ? '<'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% $e->{'data'}.
+% ( $e->{'data_style'}
+% ? '</'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% ( $e->{'size'} ? '</FONT>' : '' ).
+% ( $e->{'link'} ? '</A>' : '' ).
+% '</td>';
+%
+% } @$rowref ).
+%
+% '</tr>';
+% } @$tableref ).
+%
+% '</table>';
+%
+% } else {
+% $_;
+% }
+% }
+%
+% map {
+% if ( ref($_) eq 'CODE' ) {
+% &{$_}($row);
+% } else {
+% $row->$_();
+% }
+% }
+% @{$opt{'fields'}}
+%
+% ) {
+%
+% my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid';
+%
+% my $align = $aligns ? shift @$aligns : '';
+% $align = " ALIGN=$align" if $align;
+%
+% my $a = '';
+% if ( $links ) {
+% my $link = shift @$links;
+% my $onclick = shift @$onclicks;
+%
+% if ( ! $opt{'agent_virt'}
+% || ( $null_link && ! $row->agentnum )
+% || grep { $row->agentnum == $_ }
+% @link_agentnums
+% ) {
+%
+% $link = &{$link}($row)
+% if ref($link) eq 'CODE';
+%
+% $onclick = &{$onclick}($row)
+% if ref($onclick) eq 'CODE';
+% $onclick = qq( onClick="$onclick") if $onclick;
+%
+% if ( $link ) {
+% my( $url, $method ) = @{$link};
+% if ( ref($method) eq 'CODE' ) {
+% $a = $url. &{$method}($row);
+% } else {
+% $a = $url. $row->$method();
+% }
+% $a = qq(<A HREF="$a"$onclick>);
+% }
+%
+% }
+%
+% }
+%
+% my $font = '';
+% my $color = shift @$colors;
+% $color = &{$color}($row) if ref($color) eq 'CODE';
+% my $size = shift @$sizes;
+% $size = &{$size}($row) if ref($size) eq 'CODE';
+% if ( $color || $size ) {
+% $font = '<FONT '.
+% ( $color ? "COLOR=#$color " : '' ).
+% ( $size ? qq(SIZE="$size" ) : '' ).
+% '>';
+% }
+%
+% my($s, $es) = ( '', '' );
+% my $style = shift @$styles;
+% $style = &{$style}($row) if ref($style) eq 'CODE';
+% if ( $style ) {
+% $s = join( '', map "<$_>", split('', $style) );
+% $es = join( '', map "</$_>", split('', $style) );
+% }
+%
+% my $cstyle = shift @$cstyles;
+% $cstyle = &{$cstyle}($row) if ref($cstyle) eq 'CODE';
+% $cstyle = qq(STYLE="$cstyle")
+% if $cstyle;
+
+ <TD CLASS="<% $class %>" BGCOLOR="<% $bgcolor %>" <% $align %> <% $cstyle %>><% $font %><% $a %><% $s %><% $field %><% $es %><% $a ? '</A>' : '' %><% $font ? '</FONT>' : '' %></TD>
+
+% }
+%
+% } else {
+%
+% foreach ( @$row ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $_ %></TD>
+% }
+%
+% }
+
+ </TR>
+
+% }
+
+% if ( $opt{'footer'} ) {
+
+ <TR>
+
+% foreach my $footer ( @{ $opt{'footer'} } ) {
+ <TD CLASS="grid" BGCOLOR="#dddddd" STYLE="border-top: dashed 1px black;"><i><% $footer %></i></TD>
+% }
+
+ </TR>
+% }
+
+ </TABLE>
+
+ <% $pager %>
+
+ </TD>
+ </TR>
+ </TABLE>
+% }
+
+% if ( $type eq 'html-print' ) {
+
+ </BODY></HTML>
+
+% } else {
+
+ <% defined($opt{'html_foot'})
+ ? ( ref($opt{'html_foot'})
+ ? &{$opt{'html_foot'}}()
+ : $opt{'html_foot'}
+ )
+ : ''
+ %>
+
+ <% include( '/elements/footer.html' ) %>
+
+% }
+
+% }
+%
+% }
+<%init>
+
+my(%opt) = @_;
+#warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my %align = (
+ 'l' => 'left',
+ 'r' => 'right',
+ 'c' => 'center',
+ ' ' => '',
+ '.' => '',
+);
+$opt{align} = [ map $align{$_}, split(//, $opt{align}) ],
+ unless !$opt{align} || ref($opt{align});
+
+$opt{disable_download} = 0
+ if $opt{disable_download} && $curuser->access_right('Configuration download');
+
+my @link_agentnums = ();
+my $null_link = '';
+if ( $opt{'agent_virt'} ) {
+
+ @link_agentnums = $curuser->agentnums;
+ $null_link = $curuser->access_right( $opt{'agent_null_right_link'}
+ || $opt{'agent_null_right'} );
+
+ my $agentnums_sql = $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ );
+
+ $opt{'query'}{'extra_sql'} .=
+ ( $opt{'query'}{'extra_sql'} =~ /WHERE/i || keys %{$opt{'query'}{'hashref'}}
+ ? ' AND '
+ : ' WHERE ' ). $agentnums_sql;
+
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ). $agentnums_sql;
+
+ if ( $opt{'agent_pos'} || $opt{'agent_pos'} eq '0'
+ and scalar($curuser->agentnums) > 1 ) {
+ #false laziness w/statuspos above
+ my $pos = $opt{'agent_pos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Agent';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, '';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { $_[0]->agentnum ? $_[0]->agent->agent : '(global)'; };
+ splice @{ $opt{'color'} }, $pos, 0, '';
+ splice @{ $opt{'links'} }, $pos, 0, '' #[ 'agent link?', 'agentnum' ]
+ if $opt{'links'};
+ splice @{ $opt{'link_onclicks'} }, $pos, 0, ''
+ if $opt{'link_onclicks'};
+
+ }
+
+}
+
+if ( $opt{'disableable'} ) {
+
+ unless ( $cgi->param('showdisabled') ) { #modify searches
+
+ $opt{'query'}{'hashref'}{'disabled'} = '';
+ $opt{'query'}{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+
+ } elsif ( $opt{'disabled_statuspos'}
+ || $opt{'disabled_statuspos'} eq '0' ) { #add status column
+
+ my $pos = $opt{'disabled_statuspos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Status';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, 'b';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { shift->disabled ? 'DISABLED' : 'Active'; };
+ splice @{ $opt{'color'} }, $pos, 0,
+ sub { shift->disabled ? 'FF0000' : '00CC00'; };
+ splice @{ $opt{'links'} }, $pos, 0, ''
+ if $opt{'links'};
+ splice @{ $opt{'link_onlicks'} }, $pos, 0, ''
+ if $opt{'link_onlicks'};
+ }
+
+ #add show/hide disabled links
+ my $items = $opt{'name'} || PL($opt{'name_singular'});
+ if ( $cgi->param('showdisabled') ) {
+ $cgi->param('showdisabled', 0);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">hide disabled $items</a> )!;
+ $cgi->param('showdisabled', 1);
+ } else {
+ $cgi->param('showdisabled', 1);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">show disabled $items</a> )!;
+ $cgi->param('showdisabled', 0);
+ }
+
+}
+
+my $type = $cgi->param('_type') =~ /^(csv|\w*\.xls|select|html(-print)?)$/
+ ? $1 : 'html';
+
+my $limit = '';
+my($confmax, $maxrecords, $total, $offset, $count_arrayref);
+
+unless ( $type =~ /^(csv|\w*\.xls)$/ ) {
+
+ unless (exists($opt{count_query}) && length($opt{count_query})) {
+ ( $opt{count_query} = $opt{query} ) =~
+ s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i; #silly vim:/
+ }
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ $opt{count_query} .=
+ ( ( $opt{count_query} =~ /WHERE/i ) ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+ }
+
+ unless ( $type eq 'html-print' ) {
+
+ #setup some pagination things if we're in html mode
+
+ my $conf = new FS::Conf;
+ $confmax = $conf->config('maxsearchrecordsperpage');
+ if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
+ $maxrecords = $1;
+ } else {
+ $maxrecords ||= $confmax;
+ }
+
+ $limit = $maxrecords ? "LIMIT $maxrecords" : '';
+
+ $offset = $cgi->param('offset') =~ /^(\d+)$/ ? $1 : 0;
+ $limit .= " OFFSET $offset" if $offset;
+
+ }
+
+ my $count_sth = dbh->prepare($opt{'count_query'})
+ or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
+ $count_sth->execute
+ or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
+ $count_arrayref = $count_sth->fetchrow_arrayref;
+ $total = $count_arrayref->[0];
+
+}
+
+# run the query
+
+my $header = [ map { ref($_) ? $_->{'label'} : $_ } @{$opt{header}} ];
+my $rows;
+if ( ref($opt{query}) ) {
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ #%search = ( 'disabled' => '' );
+ $opt{'query'}->{'hashref'}->{'disabled'} = '';
+ $opt{'query'}->{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+ }
+
+ #eval "use FS::$opt{'query'};";
+ $rows = [ qsearch({
+ 'select' => $opt{'query'}->{'select'},
+ 'table' => $opt{'query'}->{'table'},
+ 'addl_from' => (exists($opt{'query'}->{'addl_from'}) ? $opt{'query'}->{'addl_from'} : ''),
+ 'hashref' => $opt{'query'}->{'hashref'} || {},
+ 'extra_sql' => $opt{'query'}->{'extra_sql'},
+ 'order_by' => $opt{'query'}->{'order_by'}. " $limit",
+ }) ];
+} else {
+ my $sth = dbh->prepare("$opt{'query'} $limit")
+ or die "Error preparing $opt{'query'}: ". dbh->errstr;
+ $sth->execute
+ or die "Error executing $opt{'query'}: ". $sth->errstr;
+
+ #can get # of rows without fetching them all?
+ $rows = $sth->fetchall_arrayref;
+
+ $header ||= $sth->{NAME};
+}
+
+</%init>
diff --git a/httemplate/search/inventory_item.html b/httemplate/search/inventory_item.html
new file mode 100644
index 000000000..cd37e267b
--- /dev/null
+++ b/httemplate/search/inventory_item.html
@@ -0,0 +1,125 @@
+<% include( 'elements/search.html',
+ 'title' => $title,
+
+ #less lame to use Lingua:: something to pluralize
+ 'name' => $inventory_class->classname. 's',
+
+ 'query' => {
+ 'table' => 'inventory_item',
+ 'hashref' => { 'classnum' => $classnum },
+ 'select' => join(', ',
+ 'inventory_item.*',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $extra_sql,
+ 'addl_from' => $addl_from,
+ },
+
+ 'count_query' => $count_query,
+
+ 'header' => [
+ '#',
+ $inventory_class->classname,
+ 'Service',
+ FS::UI::Web::cust_header(),
+ ],
+
+ 'fields' => [
+ 'itemnum',
+ 'item',
+ #'svcnum', #XXX proper full service customer link ala svc_acct
+ # "unallocated" ? "available" ?
+ sub {
+ #this could be way more efficient with a mixin
+ # like cust_main_Mixin that let us all all the methods
+ # on data we already have...
+ my $inventory_item = shift;
+ my $cust_svc = $inventory_item->cust_svc;
+ if ( $cust_svc ) {
+ my($label, $value) = $cust_svc->label;
+ "$label: $value";
+ } else {
+ '(available)';
+ }
+ },
+
+ \&FS::UI::Web::cust_fields,
+
+ ],
+ 'align' => 'rll'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $classnum = $cgi->param('classnum');
+$classnum =~ /^(\d+)$/ or errorpage("illegal classnum $classnum");
+$classnum = $1;
+
+my $inventory_class = qsearchs( {
+ 'table' => 'inventory_class',
+ 'hashref' => { 'classnum' => $classnum },
+} );
+
+my $title = $inventory_class->classname. ' Inventory';
+
+#little false laziness with SQL fragments in inventory_class.pm
+my $extra_sql = '';
+if ( $cgi->param('avail') ) {
+ $extra_sql = 'AND ( svcnum IS NULL OR svcnum = 0 )';
+ $title .= ' - Available';
+} elsif ( $cgi->param('used') ) {
+ $extra_sql = 'AND svcnum IS NOT NULL AND svcnum > 0';
+ $title .= ' - In use';
+}
+
+my $count_query =
+ "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql";
+
+my $link = sub {
+ my $inventory_item = shift;
+ if ( $inventory_item->svcnum ) {
+ [ "${p}view/svc_acct.cgi?", 'svcnum' ];
+ } else {
+ '';
+ }
+};
+my $link_cust = sub {
+ my $inventory_item = shift;
+ if ( $inventory_item->custnum ) {
+ [ "${p}view/cust_main.cgi?", 'custnum' ];
+ } else {
+ '';
+ }
+};
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+</%init>
diff --git a/httemplate/search/pay_batch.cgi b/httemplate/search/pay_batch.cgi
new file mode 100755
index 000000000..fb452870f
--- /dev/null
+++ b/httemplate/search/pay_batch.cgi
@@ -0,0 +1,130 @@
+<% include( 'elements/search.html',
+ 'title' => 'Payment Batches',
+ 'name_singular' => 'batch',
+ 'query' => { 'table' => 'pay_batch',
+ 'hashref' => $hashref,
+ 'extra_sql' => "$extra_sql ORDER BY batchnum DESC",
+ },
+ 'count_query' => "$count_query $extra_sql",
+ 'header' => [ 'Batch',
+ 'Type',
+ 'First Download',
+ 'Last Upload',
+ 'Item Count',
+ 'Amount',
+ 'Status',
+ ],
+ 'align' => 'rcllrrc',
+ 'fields' => [ 'batchnum',
+ sub {
+ FS::payby->shortname(shift->payby);
+ },
+ sub {
+ my $self = shift;
+ my $_date = $self->download;
+ if ( $_date ) {
+ time2str("%a %b %e %T %Y", $_date);
+ } elsif ( $self->status eq 'O' ) {
+ 'Download batch';
+ } else {
+ '';
+ }
+ },
+ sub {
+ my $self = shift;
+ my $_date = $self->upload;
+ if ( $_date ) {
+ time2str("%a %b %e %T %Y", $_date);
+ } elsif ( $self->status eq 'I' ) {
+ 'Upload results';
+ } else {
+ '';
+ }
+ },
+ sub {
+ my $st = "SELECT COUNT(*) from cust_pay_batch WHERE batchnum=" . shift->batchnum;
+ my $sth = dbh->prepare($st)
+ or die dbh->errstr. "doing $st";
+ $sth->execute
+ or die "Error executing \"$st\": ". $sth->errstr;
+ $sth->fetchrow_arrayref->[0];
+ },
+ sub {
+ my $st = "SELECT SUM(amount) from cust_pay_batch WHERE batchnum=" . shift->batchnum;
+ my $sth = dbh->prepare($st)
+ or die dbh->errstr. "doing $st";
+ $sth->execute
+ or die "Error executing \"$st\": ". $sth->errstr;
+ $sth->fetchrow_arrayref->[0];
+ },
+ sub {
+ $statusmap{shift->status};
+ },
+ ],
+ 'links' => [
+ $link,
+ '',
+ sub { shift->status eq 'O' ? $link : '' },
+ sub { shift->status eq 'I' ? $link : '' },
+ ],
+ 'size' => [
+ '',
+ '',
+ sub { shift->status eq 'O' ? "+1" : '' },
+ sub { shift->status eq 'I' ? "+1" : '' },
+ ],
+ 'style' => [
+ '',
+ '',
+ sub { shift->status eq 'O' ? "b" : '' },
+ sub { shift->status eq 'I' ? "b" : '' },
+ ],
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports')
+ || $FS::CurrentUser::CurrentUser->access_right('Process batches');
+
+my %statusmap = ('I'=>'In Transit', 'O'=>'Open', 'R'=>'Resolved');
+my $hashref = {};
+my $count_query = 'SELECT COUNT(*) FROM pay_batch';
+
+my($begin, $end) = ( '', '' );
+
+my @where;
+if ( $cgi->param('beginning')
+ && $cgi->param('beginning') =~ /^([ 0-9\-\/]{0,10})$/ ) {
+ $begin = str2time($1);
+ push @where, "download >= $begin";
+}
+if ( $cgi->param('ending')
+ && $cgi->param('ending') =~ /^([ 0-9\-\/]{0,10})$/ ) {
+ $end = str2time($1) + 86399;
+ push @where, "download < $end";
+}
+
+my @status;
+if ( $cgi->param('open') ) {
+ push @status, "O";
+}
+
+if ( $cgi->param('intransit') ) {
+ push @status, "I";
+}
+
+if ( $cgi->param('resolved') ) {
+ push @status, "R";
+}
+
+push @where,
+ scalar(@status) ? q!(status='! . join(q!' OR status='!, @status) . q!')!
+ : q!status='X'!; # kludgy, X is unused at present
+
+my $extra_sql = scalar(@where) ? 'WHERE ' . join(' AND ', @where) : '';
+
+my $link = [ "${p}search/cust_pay_batch.cgi?dcln=1;batchnum=", 'batchnum' ];
+
+</%init>
diff --git a/httemplate/search/pay_batch.html b/httemplate/search/pay_batch.html
new file mode 100644
index 000000000..5907169d8
--- /dev/null
+++ b/httemplate/search/pay_batch.html
@@ -0,0 +1,33 @@
+<% include('/elements/header.html', 'Batch criteria' ) %>
+
+<FORM ACTION="pay_batch.cgi" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="_date">
+
+<TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="open" VALUE="1" CHECKED></TD>
+ <TD>Show open batches</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="intransit" VALUE="1" CHECKED></TD>
+ <TD>Show in-transit batches</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="resolved" VALUE="1" CHECKED></TD>
+ <TD>Show resolved batches</TD>
+ </TR>
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Batches">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/phone_avail.html b/httemplate/search/phone_avail.html
new file mode 100644
index 000000000..2388d25ff
--- /dev/null
+++ b/httemplate/search/phone_avail.html
@@ -0,0 +1,102 @@
+<% include( 'elements/search.html',
+ 'title' => 'Phone Number (DID) Search Results',
+ 'name_singular' => 'phone number',
+ 'query' => {
+ 'table' => 'phone_avail',
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'phone_avail.*',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $search,
+ 'addl_from' => $addl_from,
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'State',
+ 'Phone Number',
+ 'Export',
+ 'Service',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [
+ 'availnum',
+ 'state',
+ sub { my $pn = shift;
+ '+'. $pn->countrycode. ' '.
+ $pn->npa. ' '. $pn->nxx. '-'. $pn->station;
+ },
+ 'exportnum', #XXX
+ #sub { },
+ 'svcnum', #XXX
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'align' => 'rllll'.FS::UI::Web::cust_aligns(),
+ 'links' => [
+ '',
+ '',
+ '',
+ '', #XXX #$export_link
+ '', #XXX #$svc_link
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my @search = ();
+
+if ( $cgi->param('availbatch') =~ /^([\w\/\:\-\.]+)$/ ) {
+ push @search, "availbatch = '$1'";
+}
+
+# #here is the agent virtualization
+# push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $search = scalar(@search)
+ ? ' WHERE '. join(' AND ', @search)
+ : '';
+
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ #' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+my $count_query = "SELECT COUNT(*) FROM phone_avail $search"; #$addl_from?
+
+my $link_cust = sub {
+ my $phone_avail = shift;
+ if ( $phone_avail->svcnum ) {
+ my $cust_svc = $phone_avail->svc_phone->cust_svc;
+ if ( $cust_svc->pkgnum ) {
+ #my $cust_main = $cust_svc->cust_pkg->cust_main;
+ return [ "${p}view/cust_main.cgi?", 'custnum' ];
+ }
+ }
+ '';
+};
+
+</%init>
diff --git a/httemplate/search/prepay_credit.html b/httemplate/search/prepay_credit.html
new file mode 100644
index 000000000..96391fcbd
--- /dev/null
+++ b/httemplate/search/prepay_credit.html
@@ -0,0 +1,67 @@
+<% include( 'elements/search.html',
+ 'title' => 'Unused Prepaid Cards'.
+ ($agent ? ' for '. $agent->agent : ''),
+ 'menubar' => [
+ 'Generate cards' => $p.'edit/prepay_credit.cgi',
+ ],
+ 'name' => 'prepaid cards',
+ 'query' => { 'table' => 'prepay_credit',
+ 'hashref' => $hashref,
+ },
+ 'count_query' => $count_query,
+ #'redirect' => $link,
+ 'header' => [ '#', qw(Amount Time Upload Download Total Agent) ],
+ 'fields' => [
+ 'identifier',
+ sub { sprintf('$%.2f', shift->amount ) },
+ sub { my $c = shift;
+ $c->seconds ? duration_exact($c->seconds) : ''
+ },
+ sub { my $c = shift;
+ $c->upbytes
+ ? FS::UI::bytecount::bytecount_unexact($c->upbytes)
+ : ''
+ },
+ sub { my $c = shift;
+ $c->downbytes
+ ? FS::UI::bytecount::bytecount_unexact($c->downbytes)
+ : ''
+ },
+ sub { my $c = shift;
+ $c->totalbytes
+ ? FS::UI::bytecount::bytecount_unexact($c->totalbytes)
+ : ''
+ },
+ sub { my $agent = shift->agent;
+ $agent ? $agent->agent : '';
+ },
+ ],
+ 'links' => [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ sub { my $agent = shift->agent;
+ $agent ? [ "${p}view/agent.cgi?", 'agentnum' ] : '';
+ },
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agent = '';
+my $hashref = {};
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+$hashref->{agentnum} = $1;
+$agent = qsearchs('agent', { 'agentnum' => $1 } );
+}
+
+my $count_query = 'SELECT COUNT(*) FROM prepay_credit';
+$count_query .= ' WHERE agentnum = '. $agent->agentnum if $agent;
+
+</%init>
diff --git a/httemplate/search/queue.html b/httemplate/search/queue.html
new file mode 100644
index 000000000..125a6f7f6
--- /dev/null
+++ b/httemplate/search/queue.html
@@ -0,0 +1,138 @@
+<% include( 'elements/search.html',
+ 'title' => 'Job Queue',
+ 'name' => 'jobs',
+ 'html_form' => qq!<FORM NAME="jobForm" ACTION="$p/misc/queue.cgi" METHOD="POST">!,
+ 'query' => { 'table' => 'queue',
+ 'hashref' => $hashref,
+ 'extra_sql' => 'ORDER BY jobnum',
+ },
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Job',
+ 'Args',
+ 'Date',
+ 'Status',
+ 'Account', # unless $hashref->{'svcnum'}
+ '', # checkbox column
+ ],
+ 'fields' => [
+ 'jobnum',
+ 'job',
+ sub {
+ my $queue = shift;
+ if ( $dangerous
+ || $queue->job !~ /^FS::part_export::/
+ || !$noactions
+ )
+ {
+ encode_entities( join(' ', $queue->args) );
+ } else {
+ '';
+ }
+ },
+ sub {
+ time2str( "%a %b %e %T %Y", shift->_date );
+ },
+ sub {
+ my $queue = shift;
+ my $jobnum = $queue->jobnum;
+ my $status = $queue->status;
+ $status .= ': '. $queue->statustext
+ if $queue->statustext;
+ my @queue_depend = $queue->queue_depend;
+ $status .= ' (waiting for '.
+ join(', ', map { $_->depend_jobnum }
+ @queue_depend
+ ).
+ ')'
+ if @queue_depend;
+ my $changable = $dangerous
+ || ( ! $noactions
+ && $status =~ /^failed/
+ || $status =~ /^locked/
+ );
+ if ( $changable ) {
+ $status .=
+ qq! (&nbsp;<A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=new">retry</A>&nbsp;|!.
+ qq!&nbsp;<A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=del">remove</A>&nbsp;)!;
+ }
+ $status;
+ },
+ sub {
+ my $queue = shift;
+ # return '' if $hashref->{'svcnum'}
+ my $cust_svc = $queue->cust_svc;
+ my $account;
+ if ( $cust_svc ) {
+ my $table = $cust_svc->part_svc->svcdb;
+ my $label = ( $cust_svc->label )[1];
+ qq!<A HREF="../view/$table.cgi?!. $queue->svcnum.
+ qq!">$label</A>!;
+ } else {
+ '';
+ }
+ },
+ sub {
+ my $queue = shift;
+ my $jobnum = $queue->jobnum;
+ my $status = $queue->status;
+ my $changable = $dangerous
+ || ( ! $noactions
+ && $status eq 'failed'
+ || $status eq 'locked'
+ );
+ if ( $changable ) {
+ $areboxes = 1;
+ qq!<INPUT NAME="jobnum$jobnum" TYPE="checkbox" VALUE="1">!;
+ } else {
+ '';
+ }
+ },
+ ],
+ #'links' => [
+ # '',
+ # '',
+ # '',
+ # '',
+ # '',
+ # '', #$acct_link,
+ # '',
+ # ],
+ 'html_foot' => sub {
+ if ( $areboxes ) {
+ '<BR><INPUT TYPE="button" VALUE="select all" onClick="setAll(true)">'.
+ '<INPUT TYPE="button" VALUE="unselect all" onClick="setAll(false)">'.
+ '<BR><INPUT TYPE="submit" NAME="action" VALUE="retry selected">'.
+ '<INPUT TYPE="submit" NAME="action" VALUE="remove selected"><BR>'.
+ '<SCRIPT TYPE="text/javascript">'.
+ ' function setAll(setTo) { '.
+ ' theForm = document.jobForm;'.
+ ' for (i=0,n=theForm.elements.length;i<n;i++)'.
+ ' if (theForm.elements[i].name.indexOf("jobnum") != -1)'.
+ ' theForm.elements[i].checked = setTo;'.
+ ' }'.
+ '</SCRIPT>';
+ } else {
+ '';
+ }
+ },
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Job queue');
+
+my $hashref = {};
+
+my $conf = new FS::Conf;
+my $dangerous = $conf->exists('queue_dangerous_controls');
+
+my $noactions = 0;
+
+my $count_query = 'SELECT COUNT(*) FROM queue'; # + $hashref
+
+my $areboxes = 0;
+
+</%init>
diff --git a/httemplate/search/reg_code.html b/httemplate/search/reg_code.html
new file mode 100644
index 000000000..f65b00d05
--- /dev/null
+++ b/httemplate/search/reg_code.html
@@ -0,0 +1,40 @@
+<% include( 'elements/search.html',
+ 'title' => 'Unused Registration Codes for '.
+ $agent->agent,
+ 'name' => 'registration codes',
+ 'query' => { 'table' => 'reg_code',
+ 'hashref' => { 'agentnum' => $agentnum, },
+ },
+ 'count_query' => $count_query,
+ #'redirect' => $link,
+ 'header' => [ qw(Code Packages) ],
+ 'fields' => [
+ 'code',
+ sub {
+ map {
+ qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
+ $_->pkg. ' - '. $_->comment.
+ '</A><BR>'
+ } $_[0]->part_pkg
+ },
+ ],
+ 'links' => [
+ '',
+ #$plink,
+ '',
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $agentnum = $cgi->param('agentnum');
+$agentnum =~ /^(\d+)$/ or errorpage("illegal agentnum $agentnum");
+$agentnum = $1;
+my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
+
+my $count_query = "SELECT COUNT(*) FROM reg_code WHERE agentnum = $agentnum";
+
+</%init>
diff --git a/httemplate/search/report_cdr.html b/httemplate/search/report_cdr.html
new file mode 100644
index 000000000..28516313b
--- /dev/null
+++ b/httemplate/search/report_cdr.html
@@ -0,0 +1,58 @@
+<% include('/elements/header.html', 'Call Detail Record Search' ) %>
+
+<FORM ACTION="cdr.html" METHOD="GET">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+ <TR>
+ <TD ALIGN="right">Status: </TD>
+ <TD>
+ <SELECT NAME="freesidestatus">
+ <OPTION VALUE="">(all)
+ <OPTION VALUE="NULL">unprocessed
+ <OPTION VALUE="done">processed
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include ( '/elements/tr-input-beginning_ending.html' ) %>
+
+ <TR>
+ <TD ALIGN="right">Source #: </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="src">
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Destination #: </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="dst">
+ </TD>
+ </TR>
+
+ <% include( '/elements/tr-input-lessthan_greaterthan.html',
+ 'label' => 'Duration (sec)',
+ 'field' => 'duration',
+ )
+ %>
+
+ <% include( '/elements/tr-input-lessthan_greaterthan.html',
+ 'label' => 'Billable duration (sec)',
+ 'field' => 'billsec',
+ )
+ %>
+
+ <% include( '/elements/tr-select-cdrbatch.html' ) %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Search Call Detail Records">
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+</%init>
diff --git a/httemplate/search/report_cust_bill.html b/httemplate/search/report_cust_bill.html
new file mode 100644
index 000000000..96cf49263
--- /dev/null
+++ b/httemplate/search/report_cust_bill.html
@@ -0,0 +1,36 @@
+<% include('/elements/header.html', 'Invoice Report' ) %>
+
+<FORM ACTION="cust_bill.html" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="_date">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'label' => 'Invoices for agent: ',
+ 'disable_empty' => 0,
+ )
+ %>
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="open" VALUE="1" CHECKED></TD>
+ <TD>Show only open invoices</TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="newest_percust" VALUE="1"></TD>
+ <TD>Show only the single most recent invoice per-customer</TD>
+ </TR>
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List invoices');
+
+</%init>
diff --git a/httemplate/search/report_cust_credit.html b/httemplate/search/report_cust_credit.html
new file mode 100644
index 000000000..9c719b787
--- /dev/null
+++ b/httemplate/search/report_cust_credit.html
@@ -0,0 +1,48 @@
+<% include('/elements/header.html', 'Credit report' ) %>
+
+<FORM ACTION="cust_credit.html" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="_date">
+
+<TABLE>
+
+ <% include( '/elements/tr-select-otaker.html',
+ 'label' => 'Credits by employee: ',
+ 'otakers' => \@otakers,
+ )
+ %>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'label' => 'for agent: ',
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+
+ <% include( '/elements/tr-input-lessthan_greaterthan.html',
+ 'label' => 'Amount',
+ 'field' => 'amount',
+ )
+ %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_credit")
+ or die dbh->errstr;
+$sth->execute or die $sth->errstr;
+my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref};
+
+</%init>
diff --git a/httemplate/search/report_cust_event.html b/httemplate/search/report_cust_event.html
new file mode 100644
index 000000000..e63b6375d
--- /dev/null
+++ b/httemplate/search/report_cust_event.html
@@ -0,0 +1,65 @@
+<% include(
+ '/elements/header.html',
+ ( $cgi->param('failed') ? 'Failed billing events' : 'Billing events' ),
+ )
+%>
+
+ <FORM ACTION="cust_event.html" METHOD="GET">
+ <INPUT TYPE="hidden" NAME="failed" VALUE="<% $cgi->param('failed') ? 1 : 0 %>">
+ <TABLE>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <!--<TR>
+ <TD ALIGN="right">Customer type</TD>
+ <TD><SELECT MULTIPLE NAME="perhaps_payby">
+ <OPTION SELECTED VALUE="CARD">Credit card (automatic)
+ <OPTION SELECTED VALUE="CHEK">E-check (automatic)
+ <OPTION SELECTED VALUE="LECB">Phone bill billing
+ <OPTION SELECTED VALUE="BILL">Billing
+ <OPTION SELECTED VALUE="DCRD">Credit card (on-demand)
+ <OPTION SELECTED VALUE="DCHK">E-check (on-demand)
+ </TD>
+ </TR>
+ -->
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+ <!--
+ <TR>
+ <TD ALIGN="right">Events: </TD>
+ <TD>
+ <SELECT NAME="eventpart">
+ <OPTION SELECTED VALUE=""><% $cgi->param('failed') ? '(all failed events)' : '(all events)' %>
+% #foreach my $part_bill_event ( qsearch( 'part_bill_event', {} ) ) {
+% #}
+
+ </SELECT>
+ </TD>
+ </TR>
+ -->
+<!-- <TR>
+ <TD ALIGN="right">Events for payment type: </TD>
+ <TD>
+ <SELECT NAME="part_bill_event.payby">
+ <OPTION SELECTED VALUE="">(all)
+ <OPTION VALUE="CARD">Credit card (automatic)
+ <OPTION VALUE="BILL">Billing
+ <OPTION VALUE="CHEK">Electronic check (automatic)
+ <OPTION VALUE="DCRD">Credit card (on-demand)
+ <OPTION VALUE="DCHK">Electronic check (on-demand)
+ <OPTION VALUE="LECB">Phone bill billing
+ <OPTION VALUE="COMP">Complimentary
+ </SELECT>
+ </TD>
+ </TR>
+-->
+ </TABLE>
+ <BR><INPUT TYPE="submit" VALUE="Get Report">
+ </FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Billing event reports');
+
+</%init>
diff --git a/httemplate/search/report_cust_main-zip.html b/httemplate/search/report_cust_main-zip.html
new file mode 100644
index 000000000..aa802f302
--- /dev/null
+++ b/httemplate/search/report_cust_main-zip.html
@@ -0,0 +1,53 @@
+<% include('/elements/header.html', 'Zip code report') %>
+
+ <FORM ACTION="cust_main-zip.html" METHOD="GET">
+
+ <TABLE>
+
+ <TR>
+ <TD ALIGN="right">Billing or service zip</TD>
+ <TD>
+ <SELECT NAME="column">
+ <OPTION VALUE="zip">Billing zip
+ <OPTION VALUE="ship_zip">Service zip
+ </SELECT>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Ignore +4 for US zip codes</TD>
+ <TD><INPUT TYPE="checkbox" NAME="ignore_plus4" VALUE="yes" CHECKED> </TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Show customers with status:</TD>
+ <TD>
+ <SELECT NAME="status">
+ <OPTION VALUE="">all
+ <OPTION VALUE="prospect">prospect (no packages ever)
+ <OPTION SELECTED VALUE="uncancel">all except cancelled
+ <OPTION VALUE="active">active recurring packages
+ <OPTION VALUE="susp">suspended
+ <OPTION VALUE="cancel">cancelled
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0,
+ )
+ %>
+
+ </TABLE>
+ <BR><INPUT TYPE="submit" VALUE="Get Report">
+ </FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List zip codes');
+
+</%init>
diff --git a/httemplate/search/report_cust_main.html b/httemplate/search/report_cust_main.html
new file mode 100755
index 000000000..b0c5fde86
--- /dev/null
+++ b/httemplate/search/report_cust_main.html
@@ -0,0 +1,94 @@
+<% include('/elements/header.html', 'Customer Report' ) %>
+
+<FORM ACTION="cust_main.html" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="bill">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Search options</FONT></TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar($cgi->param('agentnum')),
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-select-cust_main-status.html',
+ 'label' => 'Status'
+ )
+ %>
+
+
+% foreach my $field (qw( signupdate )) {
+
+ <TR>
+ <TD ALIGN="right" VALIGN="center"><% $label{$field} %></TD>
+ <TD>
+ <TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html',
+ prefix => $field,
+ layout => 'horiz',
+ )
+ %>
+ </TABLE>
+ </TD>
+ </TR>
+
+% }
+
+ <% include( '/elements/tr-select-payby.html',
+ 'payby_type' => 'cust',
+ 'multiple' => 1,
+ 'curr_value' => { map { $_ => 1 } FS::payby->cust_payby },
+ )
+ %>
+
+ <% include( '/elements/tr-input-lessthan_greaterthan.html',
+ label => 'Current balance',
+ field => 'current_balance',
+ )
+ %>
+
+ <TR>
+ <TD ALIGN="right" VALIGN="center">Include cancelled packages</TD>
+ <TD><INPUT TYPE="checkbox" NAME="cancelled_pkgs"></TD>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TH>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Display options</FONT></TH>
+ </TR>
+ <% include( '/elements/tr-select-cust-fields.html' ) %>
+
+ <TR>
+ <TD ALIGN="right" VALIGN="center">Add package columns</TD>
+ <TD><INPUT TYPE="checkbox" NAME="flattened_pkgs"></TD>
+ </TR>
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless ( $FS::CurrentUser::CurrentUser->access_right('List customers') &&
+ $FS::CurrentUser::CurrentUser->access_right('List packages')
+ );;
+
+</%init>
+<%once>
+
+my %label = (
+ 'signupdate' => 'Signup date',
+);
+
+</%once>
diff --git a/httemplate/search/report_cust_pay.html b/httemplate/search/report_cust_pay.html
new file mode 100644
index 000000000..06271313f
--- /dev/null
+++ b/httemplate/search/report_cust_pay.html
@@ -0,0 +1,79 @@
+<% include('/elements/header.html', 'Payment report' ) %>
+
+<FORM ACTION="cust_pay.cgi" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="_date">
+
+<TABLE>
+
+ <TR>
+ <TD ALIGN="right">Payments of type: </TD>
+ <TD>
+ <SELECT NAME="payby" onChange="payby_changed(this)">
+ <OPTION VALUE="">all</OPTION>
+ <OPTION VALUE="CARD">credit card (all)</OPTION>
+ <OPTION VALUE="CARD-VisaMC">credit card (Visa/MasterCard)</OPTION>
+ <OPTION VALUE="CARD-Amex">credit card (American Express)</OPTION>
+ <OPTION VALUE="CARD-Discover">credit card (Discover)</OPTION>
+ <OPTION VALUE="CARD-Maestro">credit card (Maestro/Switch/Solo)</OPTION>
+ <OPTION VALUE="CHEK">electronic check / ACH</OPTION>
+ <OPTION VALUE="BILL">check</OPTION>
+ <OPTION VALUE="PREP">prepaid card</OPTION>
+ <OPTION VALUE="CASH">cash</OPTION>
+ <OPTION VALUE="WEST">Western Union</OPTION>
+ <OPTION VALUE="MCRD">manual credit card</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function payby_changed(what) {
+ if ( what.options[what.selectedIndex].value == 'BILL' ) {
+ document.getElementById('checkno_caption').style.color = '#000000';
+ what.form.payinfo.disabled = false;
+ what.form.payinfo.style.backgroundColor = '#ffffff';
+ } else {
+ document.getElementById('checkno_caption').style.color = '#bbbbbb';
+ what.form.payinfo.disabled = true;
+ what.form.payinfo.style.backgroundColor = '#dddddd';
+ }
+ }
+
+ </SCRIPT>
+
+ <TR>
+ <TD ALIGN="right"><FONT ID="checkno_caption" COLOR="#bbbbbb">Check #: </FONT></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="payinfo" DISABLED STYLE="background-color: #dddddd">
+ </TD>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar($cgi->param('agentnum')),
+ 'label' => 'for agent: ',
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+
+ <% include( '/elements/tr-input-lessthan_greaterthan.html',
+ 'label' => 'Amount',
+ 'field' => 'paid',
+ )
+ %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/report_cust_pay_batch.html b/httemplate/search/report_cust_pay_batch.html
new file mode 100644
index 000000000..2d3ef068a
--- /dev/null
+++ b/httemplate/search/report_cust_pay_batch.html
@@ -0,0 +1,44 @@
+<% include('/elements/header.html', 'Batch payment report' ) %>
+
+<FORM ACTION="cust_pay_batch.cgi" METHOD="GET">
+
+<TABLE>
+
+ <TR>
+ <TD ALIGN="right">Payments of type: </TD>
+ <TD>
+ <SELECT NAME="payby">
+ <OPTION VALUE="">all</OPTION>
+ <OPTION VALUE="CARD">credit card</OPTION>
+ <OPTION VALUE="CHEK">electronic check / ACH</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'label' => 'For agent: ',
+ 'disable_empty' => 0
+ )
+ %>
+
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="dcln" VALUE="1" CHECKED></TD>
+ <TD>Include approved items</TD>
+ </TR>
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/report_cust_pkg.html b/httemplate/search/report_cust_pkg.html
new file mode 100755
index 000000000..aef1c24e5
--- /dev/null
+++ b/httemplate/search/report_cust_pkg.html
@@ -0,0 +1,149 @@
+<% include('/elements/header.html', 'Package Report' ) %>
+
+<FORM ACTION="cust_pkg.cgi" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="bill">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-select-cust_pkg-status.html',
+ 'onchange' => 'status_changed(this);',
+ )
+ %>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function status_changed(what) {
+
+% foreach my $status ( '', FS::cust_pkg->statuses() ) {
+
+ if ( what.options[what.selectedIndex].value == '<% $status %>' ) {
+
+% foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
+% if ( $disable{$status}->{$field} ) {
+
+ what.form.<% $field %>_beginning_text.disabled = true;
+ what.form.<% $field %>_ending_text.disabled = true;
+ what.form.<% $field %>_beginning_text.style.backgroundColor = '#dddddd';
+ what.form.<% $field %>_ending_text.style.backgroundColor = '#dddddd';
+
+ what.form.<% $field %>_beginning_button.style.display = 'none';
+ what.form.<% $field %>_ending_button.style.display = 'none';
+ what.form.<% $field %>_beginning_disabled.style.display = '';
+ what.form.<% $field %>_ending_disabled.style.display = '';
+
+% } else {
+
+ what.form.<% $field %>_beginning_text.disabled = false;
+ what.form.<% $field %>_ending_text.disabled = false;
+ what.form.<% $field %>_beginning_text.style.backgroundColor = '#ffffff';
+ what.form.<% $field %>_ending_text.style.backgroundColor = '#ffffff';
+
+ what.form.<% $field %>_beginning_button.style.display = '';
+ what.form.<% $field %>_ending_button.style.display = '';
+ what.form.<% $field %>_beginning_disabled.style.display = 'none';
+ what.form.<% $field %>_ending_disabled.style.display = 'none';
+
+% }
+% }
+
+ }
+
+% }
+
+ }
+
+ </SCRIPT>
+
+ <% include( '/elements/tr-select-pkg_class.html',
+ 'pre_options' => [ '0' => 'all' ],
+ 'empty_label' => '(empty class)',
+ )
+ %>
+
+% foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
+
+ <TR>
+ <TD ALIGN="right" VALIGN="center"><% $label{$field} %></TD>
+ <TD>
+ <TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html',
+ prefix => $field,
+ layout => 'horiz',
+ )
+ %>
+ </TABLE>
+ </TD>
+ </TR>
+
+% }
+
+ <% include( '/elements/tr-selectmultiple-part_pkg.html' ) %>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TH>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Display options</FONT></TH>
+ </TR>
+ <% include( '/elements/tr-select-cust-fields.html' ) %>
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages');
+
+</%init>
+<%once>
+
+my %label = (
+ 'setup' => 'Setup',
+ 'last_bill' => 'Last bill',
+ 'bill' => 'Next bill',
+ 'adjourn' => 'Adjourns',
+ 'susp' => 'Suspended',
+ 'expire' => 'Expires',
+ 'cancel' => 'Cancelled',
+);
+
+#false laziness w/cust_pkg.cgi
+my %disable = (
+ 'all' => {},
+ 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, },
+ 'active' => { 'susp'=>1, 'cancel'=>1 },
+ 'suspended' => { 'cancel' => 1 },
+ 'cancelled' => {},
+ '' => {},
+);
+
+#hmm?
+my %checkbox = (
+ 'setup' => 0,
+ 'last_bill' => 0,
+ 'bill' => 0,
+ 'susp' => 1,
+ 'expire' => 1,
+ 'cancel' => 1,
+);
+
+</%once>
diff --git a/httemplate/search/report_newtax.cgi b/httemplate/search/report_newtax.cgi
new file mode 100755
index 000000000..586fddd25
--- /dev/null
+++ b/httemplate/search/report_newtax.cgi
@@ -0,0 +1,158 @@
+<% include("/elements/header.html", "$agentname Tax Report - ".
+ ( $beginning
+ ? time2str('%h %o %Y ', $beginning )
+ : ''
+ ).
+ 'through '.
+ ( $ending == 4294967295
+ ? 'now'
+ : time2str('%h %o %Y', $ending )
+ )
+ )
+%>
+
+<% include('/elements/table-grid.html') %>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Tax collected</TH>
+ </TR>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% foreach my $tax ( @taxes ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $link = '';
+% if ( $tax->{'label'} ne 'Total' ) {
+% $link = ';'. $tax->{'url_param'};
+% }
+%
+
+ <TR>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $tax->{'label'} %></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
+ <A HREF="<% $baselink. $link %>;istax=1"><% $money_char %><% sprintf('%.2f', $tax->{'tax'} ) %></A>
+ </TD>
+ </TR>
+% }
+
+</TABLE>
+
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+
+my $join_cust = "
+ JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum )
+";
+my $from_join_cust = "
+ FROM cust_bill_pkg
+ $join_cust
+";
+
+my $where = "WHERE _date >= $beginning AND _date <= $ending ";
+
+my $agentname = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "agent not found" unless $agent;
+ $agentname = $agent->agent;
+ $where .= ' AND cust_main.agentnum = '. $agent->agentnum;
+}
+
+my $tax = 0;
+my %taxes = ();
+foreach my $t (qsearch({ table => 'cust_bill_pkg',
+ hashref => { pkgpart => 0 },
+ addl_from => $join_cust,
+ extra_sql => $where,
+ })
+ )
+{
+ #warn $t->itemdesc. "\n";
+
+ my $label = $t->itemdesc;
+ $label ||= 'Tax';
+ $taxes{$label}->{'label'} = $label;
+ $taxes{$label}->{'url_param'} = "itemdesc=$label";
+
+ # calculate total for this tax
+ # calculate customer-exemption for this tax
+ # calculate package-exemption for this tax
+ # calculate monthly exemption (texas tax) for this tax
+ # count up all the cust_tax_exempt_pkg records associated with
+ # the actual line items.
+}
+
+
+foreach my $t (qsearch({ table => 'cust_bill_pkg',
+ select => 'DISTINCT itemdesc',
+ hashref => { pkgpart => 0 },
+ addl_from => $join_cust,
+ extra_sql => $where,
+ })
+ )
+{
+
+ my $label = $t->itemdesc;
+ $label ||= 'Tax';
+ my @taxparam = ( 'itemdesc' );
+ my $taxwhere = "$from_join_cust $where AND payby != 'COMP' ".
+ "AND itemdesc = ?" ;
+
+ my $sql = "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) ".
+ " $taxwhere AND pkgnum = 0";
+
+ my $x = scalar_sql($t, \@taxparam, $sql );
+ $tax += $x;
+ $taxes{$label}->{'tax'} += $x;
+
+}
+
+#ordering
+my @taxes =
+ map $taxes{$_},
+ sort { ($b cmp $a) }
+ keys %taxes;
+
+push @taxes, {
+ 'label' => 'Total',
+ 'url_param' => '',
+ 'tax' => $tax,
+};
+
+#--
+
+#false laziness w/FS::Report::Table::Monthly (sub should probably be moved up
+#to FS::Report or FS::Record or who the fuck knows where)
+sub scalar_sql {
+ my( $r, $param, $sql ) = @_;
+ #warn "$sql\n";
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute( map $r->$_(), @$param )
+ or die "Unexpected error executing statement $sql: ". $sth->errstr;
+ $sth->fetchrow_arrayref->[0] || 0;
+}
+
+my $dateagentlink = "begin=$beginning;end=$ending";
+$dateagentlink .= ';agentnum='. $cgi->param('agentnum')
+ if length($agentname);
+my $baselink = $p. "search/cust_bill_pkg.cgi?$dateagentlink";
+
+</%init>
diff --git a/httemplate/search/report_newtax.html b/httemplate/search/report_newtax.html
new file mode 100755
index 000000000..daf2d23b6
--- /dev/null
+++ b/httemplate/search/report_newtax.html
@@ -0,0 +1,23 @@
+<% include('/elements/header.html', 'Tax Report' ) %>
+
+<FORM ACTION="report_newtax.cgi" METHOD="GET">
+
+<TABLE>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/report_prepaid_income.cgi b/httemplate/search/report_prepaid_income.cgi
new file mode 100644
index 000000000..27dbcbf9f
--- /dev/null
+++ b/httemplate/search/report_prepaid_income.cgi
@@ -0,0 +1,87 @@
+<% include("/elements/header.html", 'Prepaid Income (Unearned Revenue) Report') %>
+
+<% table() %>
+ <TR>
+ <TH>Actual Unearned Revenue</TH>
+ <TH>Legacy Unearned Revenue</TH>
+ </TR>
+ <TR>
+ <TD ALIGN="right">$<% $total %>
+ <TD ALIGN="right">
+ <% $now == $time ? "\$$total_legacy" : '<i>N/A</i>'%>
+ </TD>
+ </TR>
+
+</TABLE>
+<BR>
+Actual unearned revenue is the amount of unearned revenue Freeside has
+actually invoiced for packages with longer-than monthly terms.
+<BR><BR>
+Legacy unearned revenue is the amount of unearned revenue represented by
+customer packages. This number may be larger than actual unearned
+revenue if you have imported longer-than monthly customer packages from
+a previous billing system.
+</BODY>
+</HTML>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+#doesn't yet deal with daily/weekly packages
+
+#needs to be re-written in sql for efficiency
+
+my $time = time;
+
+my $now = $cgi->param('date') && str2time($cgi->param('date')) || $time;
+$now =~ /^(\d+)$/ or die "unparsable date?";
+$now = $1;
+
+my( $total, $total_legacy ) = ( 0, 0 );
+
+my @cust_bill_pkg =
+ grep { $_->cust_pkg && $_->cust_pkg->part_pkg->freq !~ /^([01]|\d+[dw])$/ }
+ qsearch( 'cust_bill_pkg', {
+ 'recur' => { op=>'!=', value=>0 },
+ 'edate' => { op=>'>', value=>$now },
+ }, );
+
+my @cust_pkg =
+ grep { $_->part_pkg->recur != 0
+ && $_->part_pkg->freq !~ /^([01]|\d+[dw])$/
+ }
+ qsearch ( 'cust_pkg', {
+ 'bill' => { op=>'>', value=>$now }
+ } );
+
+foreach my $cust_bill_pkg ( @cust_bill_pkg) {
+ my $period = $cust_bill_pkg->edate - $cust_bill_pkg->sdate;
+
+ my $elapsed = $now - $cust_bill_pkg->sdate;
+ $elapsed = 0 if $elapsed < 0;
+
+ my $remaining = 1 - $elapsed/$period;
+
+ my $unearned = $remaining * $cust_bill_pkg->recur;
+ $total += $unearned;
+
+}
+
+foreach my $cust_pkg ( @cust_pkg ) {
+ my $period = $cust_pkg->bill - $cust_pkg->last_bill;
+
+ my $elapsed = $now - $cust_pkg->last_bill;
+ $elapsed = 0 if $elapsed < 0;
+
+ my $remaining = 1 - $elapsed/$period;
+
+ my $unearned = $remaining * $cust_pkg->part_pkg->recur; #!! only works for flat/legacy
+ $total_legacy += $unearned;
+
+}
+
+$total = sprintf('%.2f', $total);
+$total_legacy = sprintf('%.2f', $total_legacy);
+
+</%init>
diff --git a/httemplate/search/report_prepaid_income.html b/httemplate/search/report_prepaid_income.html
new file mode 100644
index 000000000..81adb64ad
--- /dev/null
+++ b/httemplate/search/report_prepaid_income.html
@@ -0,0 +1,43 @@
+<% include('/elements/header.html', 'Prepaid Income (Unearned Revenue) Report',
+ '',
+ '',
+ '<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+ <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+ <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+ '
+) %>
+
+ <FORM ACTION="report_prepaid_income.cgi" METHOD="GET">
+ <TABLE>
+ <TR>
+ <TD>Prepaid income (unearned revenue) as of </TD>
+ <TD>
+ <INPUT TYPE="text" NAME="date" ID="date_text" VALUE="now">
+ <IMG SRC="../images/calendar.png" ID="date_button" STYLE="cursor: pointer" TITLE="Select date">
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ </TD>
+ <TD><i>m/d/y</i></TD>
+ </TR>
+ </TABLE>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "date_text",
+ ifFormat: "%m/%d/%Y",
+ button: "date_button",
+ align: "BR"
+ });
+</SCRIPT>
+
+<INPUT TYPE="submit" VALUE="Generate report">
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi
new file mode 100755
index 000000000..58d87fa53
--- /dev/null
+++ b/httemplate/search/report_receivables.cgi
@@ -0,0 +1,197 @@
+<% include( 'elements/search.html',
+ 'title' => 'Accounts Receivable Aging Summary',
+ 'name' => 'customers',
+ 'query' => $sql_query,
+ 'count_query' => $count_sql,
+ 'header' => [
+ FS::UI::Web::cust_header(),
+ '0-30',
+ '30-60',
+ '60-90',
+ '90+',
+ 'Total',
+ ],
+ 'footer' => [
+ 'Total',
+ ( map '',
+ ( 1 ..
+ scalar(FS::UI::Web::cust_header()-1)
+ )
+ ),
+ sprintf( $money_char.'%.2f',
+ $row->{'balance_0_30'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'balance_30_60'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'balance_60_90'} ),
+ sprintf( $money_char.'%.2f',
+ $row->{'balance_90_0'} ),
+ sprintf( '<b>'. $money_char.'%.2f'. '</b>',
+ $row->{'balance_0_0'} ),
+ ],
+ 'fields' => [
+ \&FS::UI::Web::cust_fields,
+ format_balance('0_30'),
+ format_balance('30_60'),
+ format_balance('60_90'),
+ format_balance('90_0'),
+ format_balance('0_0'),
+ ],
+ 'links' => [
+ ( map { $_ ne 'Cust. Status' ? $clink : '' }
+ FS::UI::Web::cust_header()
+ ),
+ '',
+ '',
+ '',
+ '',
+ '',
+ ],
+ #'align' => 'rlccrrrrr',
+ 'align' => FS::UI::Web::cust_aligns(). 'rrrrr',
+ #'size' => [ '', '', '-1', '-1', '', '', '', '', '', ],
+ #'style' => [ '', '', 'b', 'b', '', '', '', '', 'b', ],
+ 'size' => [ ( map '', FS::UI::Web::cust_header() ),
+ #'-1', '', '', '', '', '', ],
+ '', '', '', '', '', ],
+ 'style' => [ FS::UI::Web::cust_styles(),
+ #'b', '', '', '', '', 'b', ],
+ '', '', '', '', 'b', ],
+ 'color' => [
+ FS::UI::Web::cust_colors(),
+ '',
+ '',
+ '',
+ '',
+ '',
+ ],
+
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my @ranges = (
+ [ 0, 30 ],
+ [ 30, 60 ],
+ [ 60, 90 ],
+ [ 90, 0 ],
+ [ 0, 0 ],
+);
+
+my $owed_cols = join(',', map balance( @$_ ), @ranges );
+
+my $select_count_pkgs = FS::cust_main->select_count_pkgs_sql;
+
+my $active_sql = FS::cust_pkg->active_sql;
+my $inactive_sql = FS::cust_pkg->inactive_sql;
+my $suspended_sql = FS::cust_pkg->suspended_sql;
+my $cancelled_sql = FS::cust_pkg->cancelled_sql;
+
+my $packages_cols = <<END;
+ ( $select_count_pkgs ) AS num_pkgs_sql,
+ ( $select_count_pkgs AND $active_sql ) AS active_pkgs,
+ ( $select_count_pkgs AND $inactive_sql ) AS inactive_pkgs,
+ ( $select_count_pkgs AND $suspended_sql ) AS suspended_pkgs,
+ ( $select_count_pkgs AND $cancelled_sql ) AS cancelled_pkgs
+END
+
+my @where = ();
+
+unless ( $cgi->param('all_customers') ) {
+
+ my $days = 0;
+ if ( $cgi->param('days') =~ /^\s*(\d+)\s*$/ ) {
+ $days = $1;
+ }
+
+ push @where, balance($days, 0, 'no_as'=>1). ' > 0'; # != 0';
+
+}
+
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ my $agentnum = $1;
+ push @where, "agentnum = $agentnum";
+}
+
+#here is the agent virtualization
+push @where, $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+my $where = join(' AND ', @where);
+$where = "WHERE $where" if $where;
+
+my $count_sql = "select count(*) from cust_main $where";
+
+my $sql_query = {
+ 'table' => 'cust_main',
+ 'hashref' => {},
+ 'select' => join(',',
+ #'cust_main.*',
+ 'custnum',
+ $owed_cols,
+ $packages_cols,
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $where,
+ 'order_by' => "order by coalesce(lower(company), ''), lower(last)",
+};
+
+my $total_sql = "SELECT ". join(',', map balance( @$_, 'sum'=>1 ), @ranges).
+ " FROM cust_main $where";
+
+my $total_sth = dbh->prepare($total_sql) or die dbh->errstr;
+$total_sth->execute or die "error executing $total_sql: ". $total_sth->errstr;
+my $row = $total_sth->fetchrow_hashref();
+
+my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+</%init>
+<%once>
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+#Example:
+#
+# my $balance = balance(
+# $start, $end,
+# 'no_as' => 1, #set to true when using in a WHERE clause (supress AS clause)
+# #or 0 / omit when using in a SELECT clause as a column
+# # ("AS balance_$start_$end")
+# 'sum' => 1, #set to true to get a SUM() of the values, for totals
+#
+# #obsolete? options for totals (passed to cust_main::balance_date_sql)
+# 'total' => 1, #set to true to remove all customer comparison clauses
+# 'join' => $join, #JOIN clause
+# 'where' => \@where, #WHERE clause hashref (elements "AND"ed together)
+# )
+
+sub balance {
+ my($start, $end, %opt) = @_;
+
+ my $as = $opt{'no_as'} ? '' : " AS balance_${start}_$end";
+
+ #handle start and end ranges (86400 = 24h * 60m * 60s)
+ my $str2time = str2time_sql;
+ my $closing = str2time_sql_closing;
+ $start = $start ? "( $str2time now() $closing - ".($start * 86400). ' )' : '';
+ $end = $end ? "( $str2time now() $closing - ".($end * 86400). ' )' : '';
+
+ $opt{'unapplied_date'} = 1;
+
+ ( $opt{sum} ? 'SUM( ' : '' ).
+ FS::cust_main->balance_date_sql( $start, $end, %opt ).
+ ( $opt{sum} ? ' )' : '' ).
+ $as;
+
+}
+
+sub format_balance { #closures help alot
+ my $range = shift;
+ sub { sprintf( $money_char.'%.2f', shift->get("balance_$range") ) };
+}
+
+</%once>
diff --git a/httemplate/search/report_receivables.html b/httemplate/search/report_receivables.html
new file mode 100755
index 000000000..19b1ee7cc
--- /dev/null
+++ b/httemplate/search/report_receivables.html
@@ -0,0 +1,35 @@
+<% include('/elements/header.html', 'Accounts Receivable Aging Summary' ) %>
+
+<FORM NAME="OneTrueForm" ACTION="report_receivables.cgi" METHOD="GET">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left">
+ <FONT SIZE="+1">Search options</FONT>
+ </TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <TR>
+ <TD ALIGN="right">Customers</TD>
+ <TD>
+ <INPUT TYPE="radio" NAME="all_customers" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.days.disabled=true; document.OneTrueForm.days.style.backgroundColor = '#dddddd'; } else { document.OneTrueForm.days.disabled=false; document.OneTrueForm.days.style.backgroundColor = '#ffffff'; }">All customers (even those without an outstanding balance)<BR>
+ <INPUT TYPE="radio" NAME="all_customers" VALUE="0" CHECKED onClick="if ( ! this.checked ) { document.OneTrueForm.days.disabled=true; document.OneTrueForm.days.style.backgroundColor = '#dddddd'; } else { document.OneTrueForm.days.disabled=false; document.OneTrueForm.days.style.backgroundColor = '#ffffff'; }">Customers with a balance over <INPUT NAME="days" TYPE="text" SIZE=4 MAXLENGTH=3 VALUE="0"> days old
+ </TD>
+ </TR>
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Get Report">
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/report_rt_transaction.html b/httemplate/search/report_rt_transaction.html
new file mode 100644
index 000000000..9b7b7cbbb
--- /dev/null
+++ b/httemplate/search/report_rt_transaction.html
@@ -0,0 +1,24 @@
+<% include('/elements/header.html', 'Time worked report criteria' ) %>
+
+<FORM ACTION="rt_transaction.html" METHOD="GET">
+
+<TABLE>
+
+ <% include ( '/elements/tr-input-beginning_ending.html' ) %>
+
+ <% include ( '/elements/tr-select-otaker.html' ) %>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Search">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+</%init>
diff --git a/httemplate/search/report_sql.html b/httemplate/search/report_sql.html
new file mode 100644
index 000000000..995330894
--- /dev/null
+++ b/httemplate/search/report_sql.html
@@ -0,0 +1,23 @@
+<% include('/elements/header.html', 'SQL Query' ) %>
+
+<FORM ACTION="sql.html" METHOD="GET">
+
+<TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+ <TR>
+ <TD ALIGN="right" VALIGN="top">SELECT </TD>
+ <TD><TEXTAREA NAME="sql"></TEXTAREA></TD>
+ </TR>
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Query">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Raw SQL');
+
+</%init>
diff --git a/httemplate/search/report_svc_acct.html b/httemplate/search/report_svc_acct.html
new file mode 100755
index 000000000..59fd1f8b3
--- /dev/null
+++ b/httemplate/search/report_svc_acct.html
@@ -0,0 +1,105 @@
+<% include('/elements/header.html', 'Account Report' ) %>
+
+<FORM ACTION="svc_acct.cgi" METHOD="GET">
+<INPUT TYPE="hidden" NAME="magic" VALUE="advanced">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Search options</FONT></TH>
+ </TR>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'curr_value' => scalar( $cgi->param('agentnum') ),
+ 'disable_empty' => 0,
+ )
+ %>
+
+ <% include( '/elements/tr-select-domain.html',
+ 'element_name' => 'domsvc',
+ 'curr_value' => scalar( $cgi->param('domsvc') ),
+ 'disable_empty' => 0,
+ )
+ %>
+
+
+ <SCRIPT type="text/javascript">
+ function toggle(what) {
+ label = document.getElementById (what + '_label');
+ field = document.getElementById ( what + '_invert');
+ if (field.value == 1) {
+ field.value = 0;
+ } else {
+ field.value = 1;
+ }
+ if (field.value == 1) {
+ label.firstChild.nodeValue = 'Did not ' + label.firstChild.nodeValue;
+ }else{
+ text = label.firstChild.nodeValue;
+ label.firstChild.nodeValue = text.replace(/Did not /, '');
+ }
+ }
+ </SCRIPT>
+% foreach my $field (qw( last_login last_logout )) {
+% my $invert = $field."_invert";
+
+ <TR>
+ <TD>
+ <TABLE>
+ <TR>
+ <TD ALIGN="right" VALIGN="center" ID="<% $field."_label" %>">
+ <% $label{$field} %>
+ </TD>
+ <TD>
+ <INPUT NAME="<% $invert %>" ID="<% $invert %>" TYPE="hidden">
+ <A HREF="javascript:void(0)" onClick="toggle('<% $field %>'); return false;">Invert</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ <TD>
+ <TABLE>
+ <% include( '/elements/tr-input-beginning_ending.html',
+ prefix => $field,
+ layout => 'horiz',
+ )
+ %>
+ </TABLE>
+ </TD>
+ </TR>
+
+% }
+
+ <% include( '/elements/tr-selectmultiple-part_pkg.html' ) %>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2>&nbsp;</TH>
+ </TR>
+
+ <TR>
+ <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Display options</FONT></TH>
+ </TR>
+ <% include( '/elements/tr-select-cust-fields.html' ) %>
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages');
+
+</%init>
+<%once>
+
+my %label = (
+ 'last_login' => 'Last login',
+ 'last_logout' => 'Last logout',
+);
+
+</%once>
diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi
new file mode 100755
index 000000000..a7630dd2d
--- /dev/null
+++ b/httemplate/search/report_tax.cgi
@@ -0,0 +1,612 @@
+<% include("/elements/header.html", "$agentname Sales Tax Report - ".
+ ( $beginning
+ ? time2str('%h %o %Y ', $beginning )
+ : ''
+ ).
+ 'through '.
+ ( $ending == 4294967295
+ ? 'now'
+ : time2str('%h %o %Y', $ending )
+ )
+ )
+%>
+
+<% include('/elements/table-grid.html') %>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=9>Sales</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2>Rate</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2>Tax owed</TH>
+% unless ( $cgi->param('show_taxclasses') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2>Tax invoiced</TH>
+% }
+ </TR>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Total</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Non-taxable<BR><FONT SIZE=-1>(tax-exempt customer)</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Non-taxable<BR><FONT SIZE=-1>(tax-exempt package)</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Non-taxable<BR><FONT SIZE=-1>(monthly exemption)</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Taxable</TH>
+ </TR>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% foreach my $region ( @regions ) {
+%
+% my $link = '';
+% if ( $region->{'label'} ne 'Total' ) {
+% if ( $region->{'label'} eq $out ) {
+% $link = ';out=1';
+% } else {
+% $link = ';'. $region->{'url_param'};
+% }
+% }
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% #my $diff = 0;
+% my $hicolor = $bgcolor;
+% unless ( $cgi->param('show_taxclasses') ) {
+% my $diff = abs( sprintf( '%.2f', $region->{'owed'} )
+% - sprintf( '%.2f', $region->{'tax'} )
+% );
+% if ( $diff > 0.02 ) {
+% # $hicolor = $hicolor eq '#eeeeee' ? '#eeee66' : '#ffff99';
+% #} elsif ( $diff ) {
+% $hicolor = $hicolor eq '#eeeeee' ? '#eeee99' : '#ffffcc';
+% }
+% }
+%
+%
+% my $td = qq(TD CLASS="grid" BGCOLOR="$bgcolor");
+% my $tdh = qq(TD CLASS="grid" BGCOLOR="$hicolor");
+% my $bigmath = '<FONT FACE="sans-serif" SIZE="+1"><B>';
+% my $bme = '</B></FONT>';
+
+ <TR>
+ <<%$td%>><% $region->{'label'} %></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;nottax=1"
+ ><% &$money_sprintf( $region->{'total'} ) %></A>
+ </TD>
+ <<%$td%>><FONT SIZE="+1"><B> - </B></FONT></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;nottax=1;cust_tax=Y"
+ ><% &$money_sprintf( $region->{'exempt_cust'} ) %></A>
+ </TD>
+ <<%$td%>><FONT SIZE="+1"><B> - </B></FONT></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;nottax=1;pkg_tax=Y"
+ ><% &$money_sprintf( $region->{'exempt_pkg'} ) %></A>
+ </TD>
+ <<%$td%>><FONT SIZE="+1"><B> - </B></FONT></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $exemptlink. $link %>"
+ ><% &$money_sprintf( $region->{'exempt_monthly'} ) %></A>
+ </TD>
+ <<%$td%>><FONT SIZE="+1"><B> = </B></FONT></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;nottax=1;taxable=1"
+ ><% &$money_sprintf( $region->{'taxable'} ) %></A>
+ </TD>
+ <<%$td%>><% $region->{'label'} eq 'Total' ? '' : "$bigmath X $bme" %></TD>
+ <<%$td%> ALIGN="right"><% $region->{'rate'} %></TD>
+ <<%$td%>><% $region->{'label'} eq 'Total' ? '' : "$bigmath = $bme" %></TD>
+ <<%$tdh%> ALIGN="right">
+ <% &$money_sprintf( $region->{'owed'} ) %>
+ </TD>
+
+% unless ( $cgi->param('show_taxclasses') ) {
+ <<%$tdh%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;istax=1"
+ ><% &$money_sprintf( $region->{'tax'} ) %></A>
+ </TD>
+% }
+
+ </TR>
+% }
+
+</TABLE>
+
+% if ( $cgi->param('show_taxclasses') ) {
+
+ <BR>
+ <% include('/elements/table-grid.html') %>
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Tax invoiced</TH>
+ </TR>
+
+% #some false laziness w/above
+% $bgcolor1 = '#eeeeee';
+% $bgcolor2 = '#ffffff';
+%
+% foreach my $region ( @base_regions ) {
+%
+% my $link = '';
+% #if ( $region->{'label'} ne 'Total' ) {
+% if ( $region->{'label'} eq $out ) {
+% $link = ';out=1';
+% } else {
+% $link = ';'. $region->{'url_param'};
+% }
+% #}
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+% my $td = qq(TD CLASS="grid" BGCOLOR="$bgcolor");
+
+ <TR>
+ <<%$td%>><% $region->{'label'} %></TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink. $link %>;istax=1"
+ ><% &$money_sprintf( $region->{'tax'} ) %></A>
+ </TD>
+ </TR>
+
+% }
+
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+% my $td = qq(TD CLASS="grid" BGCOLOR="$bgcolor");
+
+ <TR>
+ <<%$td%>>Total</TD>
+ <<%$td%> ALIGN="right">
+ <A HREF="<% $baselink %>;istax=1"
+ ><% &$money_sprintf( $tax ) %></A>
+ </TD>
+ </TR>
+
+ </TABLE>
+
+% }
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $conf = new FS::Conf;
+
+my $user = getotaker;
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+
+my $join_cust = ' JOIN cust_bill USING ( invnum )
+ LEFT JOIN cust_main USING ( custnum ) ';
+my $join_cust_pkg = $join_cust.
+ ' LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN part_pkg USING ( pkgpart ) ';
+$join_cust_pkg .= ' LEFT JOIN cust_location USING ( locationnum )'
+ if $conf->exists('tax-pkg_address');
+
+my $from_join_cust_pkg = " FROM cust_bill_pkg $join_cust_pkg ";
+
+my $where = "WHERE _date >= $beginning AND _date <= $ending ";
+
+my( $location_sql, @base_param ) = FS::cust_pkg->location_sql;
+$where .= " AND $location_sql ";
+
+my $agentname = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ my $agent = qsearchs('agent', { 'agentnum' => $1 } );
+ die "agent not found" unless $agent;
+ $agentname = $agent->agent;
+ $where .= ' AND cust_main.agentnum = '. $agent->agentnum;
+}
+
+sub gotcust {
+ my $table = shift;
+ my $prefix = @_ ? shift : '';
+ "
+ ( $table.${prefix}county = cust_main_county.county
+ OR cust_main_county.county = ''
+ OR cust_main_county.county IS NULL )
+ AND ( $table.${prefix}state = cust_main_county.state
+ OR cust_main_county.state = ''
+ OR cust_main_county.state IS NULL )
+ AND ( $table.${prefix}country = cust_main_county.country )
+ ";
+}
+
+my $gotcust;
+if ( $conf->exists('tax-ship_address') ) {
+
+ $gotcust = "
+ ( cust_main_county.country = cust_main.country
+ OR cust_main_county.country = cust_main.ship_country
+ )
+
+ AND
+
+ (
+ ( ( ship_last IS NULL OR ship_last = '' )
+ AND ". gotcust('cust_main'). "
+ )
+ OR
+ ( ship_last IS NOT NULL AND ship_last != ''
+ AND ". gotcust('cust_main', 'ship_'). "
+ )
+ )
+ ";
+
+} else {
+
+ $gotcust = gotcust('cust_main');
+
+}
+if ( $conf->exists('tax-pkg_address') ) {
+ $gotcust = "
+ ( cust_pkg.locationnum IS NULL AND $gotcust)
+ OR ( cust_pkg.locationnum IS NOT NULL AND ". gotcust('cust_location'). " )";
+ $gotcust =
+ "WHERE 0 < ( SELECT COUNT(*) FROM cust_pkg
+ LEFT JOIN cust_main USING ( custnum )
+ LEFT JOIN cust_location USING ( locationnum )
+ WHERE $gotcust
+ LIMIT 1
+ )
+ ";
+} else {
+ $gotcust =
+ "WHERE 0 < ( SELECT COUNT(*) FROM cust_main WHERE $gotcust LIMIT 1 )";
+}
+
+my($total, $tot_taxable, $owed, $tax) = ( 0, 0, 0, 0 );
+my( $exempt_cust, $exempt_pkg, $exempt_monthly ) = ( 0, 0, 0 );
+my $out = 'Out of taxable region(s)';
+my %regions = ();
+
+foreach my $r ( qsearch({ 'table' => 'cust_main_county',
+ 'extra_sql' => $gotcust,
+ })
+ )
+{
+ #warn $r->county. ' '. $r->state. ' '. $r->country. "\n";
+
+ my $label = getlabel($r);
+ $regions{$label}->{'label'} = $label;
+ $regions{$label}->{'url_param'} =
+ join(';', map "$_=".uri_escape($r->$_()),
+ qw( county state country taxname )
+ );
+
+ my @param = @base_param;
+ my $mywhere = $where;
+
+ if ( $r->taxclass ) {
+
+ $mywhere .= " AND taxclass = ? ";
+ push @param, 'taxclass';
+ $regions{$label}->{'url_param'} .= ';taxclass='. uri_escape($r->taxclass);
+ #no, always# if $cgi->param('show_taxclasses');
+
+ } else {
+
+ $regions{$label}->{'url_param'} .= ';taxclassNULL=1'
+ if $cgi->param('show_taxclasses');
+
+ my $same_sql = $r->sql_taxclass_sameregion;
+ $mywhere .= " AND $same_sql" if $same_sql;
+
+ }
+
+ my $fromwhere = "$from_join_cust_pkg $mywhere"; # AND payby != 'COMP' ";
+
+# my $label = getlabel($r);
+# $regions{$label}->{'label'} = $label;
+
+ my $nottax = 'pkgnum != 0';
+
+ ## calculate total for this region
+
+ my $t_sql =
+ "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) $fromwhere AND $nottax";
+ my $t = scalar_sql($r, \@param, $t_sql);
+ $total += $t;
+ $regions{$label}->{'total'} += $t;
+
+ #if ( $label eq $out ) {# && $t ) {
+ # warn "adding $t for ".
+ # join('/', map $r->$_, qw( taxclass county state country ) ). "\n";
+ # #warn $t_sql if $r->state eq 'FL';
+ #}
+
+ ## calculate customer-exemption for this region
+
+## my $taxable = $t;
+
+# my($taxable, $x_cust) = (0, 0);
+# foreach my $e ( grep { $r->get($_.'tax') !~ /^Y/i }
+# qw( cust_bill_pkg.setup cust_bill_pkg.recur ) ) {
+# $taxable += scalar_sql($r, \@param,
+# "SELECT SUM($e) $fromwhere AND $nottax AND ( tax != 'Y' OR tax IS NULL )"
+# );
+#
+# $x_cust += scalar_sql($r, \@param,
+# "SELECT SUM($e) $fromwhere AND $nottax AND tax = 'Y'"
+# );
+# }
+
+ my $x_cust = scalar_sql($r, \@param,
+ "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur)
+ $fromwhere AND $nottax AND tax = 'Y' "
+ );
+
+ $exempt_cust += $x_cust;
+ $regions{$label}->{'exempt_cust'} += $x_cust;
+
+ ## calculate package-exemption for this region
+
+ my $x_pkg = scalar_sql($r, \@param,
+ "SELECT SUM(
+ ( CASE WHEN part_pkg.setuptax = 'Y'
+ THEN cust_bill_pkg.setup
+ ELSE 0
+ END
+ )
+ +
+ ( CASE WHEN part_pkg.recurtax = 'Y'
+ THEN cust_bill_pkg.recur
+ ELSE 0
+ END
+ )
+ )
+ $fromwhere
+ AND $nottax
+ AND (
+ ( part_pkg.setuptax = 'Y' AND cust_bill_pkg.setup > 0 )
+ OR ( part_pkg.recurtax = 'Y' AND cust_bill_pkg.recur > 0 )
+ )
+ AND ( tax != 'Y' OR tax IS NULL )
+ "
+ );
+ $exempt_pkg += $x_pkg;
+ $regions{$label}->{'exempt_pkg'} += $x_pkg;
+
+ ## calculate monthly exemption (texas tax) for this region
+
+ # count up all the cust_tax_exempt_pkg records associated with
+ # the actual line items.
+
+ my $x_monthly = scalar_sql($r, \@param,
+ "SELECT SUM(amount)
+ FROM cust_tax_exempt_pkg
+ JOIN cust_bill_pkg USING ( billpkgnum )
+ $join_cust_pkg
+ $mywhere"
+ );
+# if ( $x_monthly ) {
+# #warn $r->taxnum(). ": $x_monthly\n";
+# $taxable -= $x_monthly;
+# }
+
+ $exempt_monthly += $x_monthly;
+ $regions{$label}->{'exempt_monthly'} += $x_monthly;
+
+ my $taxable = $t - $x_cust - $x_pkg - $x_monthly;
+
+ $tot_taxable += $taxable;
+ $regions{$label}->{'taxable'} += $taxable;
+
+ $owed += $taxable * ($r->tax/100);
+ $regions{$label}->{'owed'} += $taxable * ($r->tax/100);
+
+ if ( defined($regions{$label}->{'rate'})
+ && $regions{$label}->{'rate'} != $r->tax.'%' ) {
+ $regions{$label}->{'rate'} = 'variable';
+ } else {
+ $regions{$label}->{'rate'} = $r->tax.'%';
+ }
+
+}
+
+my $distinct = "country, state, county,
+ CASE WHEN taxname IS NULL THEN '' ELSE taxname END AS taxname";
+my $taxclass_distinct =
+ #a little bit unsure of this part... test?
+ #ah, it looks like it winds up being irrelevant as ->{'tax'}
+ # from $regions is not displayed when show_taxclasses is on
+ ( $cgi->param('show_taxclasses')
+ ? " CASE WHEN taxclass IS NULL THEN '' ELSE taxclass END "
+ : " '' "
+ )." AS taxclass";
+
+
+my %qsearch = (
+ 'select' => "DISTINCT $distinct, $taxclass_distinct",
+ 'table' => 'cust_main_county',
+ 'hashref' => {},
+ 'extra_sql' => $gotcust,
+);
+
+my $taxfromwhere = " FROM cust_bill_pkg $join_cust ";
+my $taxwhere = $where;
+if ( $conf->exists('tax-pkg_address') ) {
+
+ $taxfromwhere .= 'LEFT JOIN cust_bill_pkg_tax_location USING ( billpkgnum )
+ LEFT JOIN cust_location USING ( locationnum ) ';
+
+ #quelle kludge
+ $taxwhere =~ s/cust_pkg\.locationnum/cust_bill_pkg_tax_location.locationnum/g;
+
+}
+$taxfromwhere .= " $taxwhere "; #AND payby != 'COMP' ";
+my @taxparam = @base_param;
+
+#should i be a cust_main_county method or something
+#need to pass in $taxfromwhere & @taxparam???
+my $_taxamount_sub = sub {
+ my $r = shift;
+
+ #match itemdesc if necessary!
+ my $named_tax =
+ $r->taxname
+ ? 'AND itemdesc = '. dbh->quote($r->taxname)
+ : "AND ( itemdesc IS NULL OR itemdesc = '' OR itemdesc = 'Tax' )";
+
+ my $sql = "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) ".
+ " $taxfromwhere AND cust_bill_pkg.pkgnum = 0 $named_tax";
+
+ scalar_sql($r, \@taxparam, $sql );
+};
+
+#foreach my $label ( keys %regions ) {
+foreach my $r ( qsearch(\%qsearch) ) {
+
+ #warn join('-', map { $r->$_() } qw( country state county taxname ) )."\n";
+
+ my $label = getlabel($r);
+
+ #my $fromwhere = $join_pkg. $where. " AND payby != 'COMP' ";
+ #my @param = @base_param;
+
+ my $x = &{$_taxamount_sub}($r);
+
+ $tax += $x unless $cgi->param('show_taxclasses');
+ $regions{$label}->{'tax'} += $x;
+
+}
+
+my %base_regions = ();
+if ( $cgi->param('show_taxclasses') ) {
+
+ $qsearch{'select'} = "DISTINCT $distinct";
+ foreach my $r ( qsearch(\%qsearch) ) {
+
+ my $x = &{$_taxamount_sub}($r);
+
+ my $base_label = getlabel($r, 'no_taxclass'=>1 );
+ $base_regions{$base_label}->{'label'} = $base_label;
+
+ $base_regions{$base_label}->{'url_param'} =
+ join(';', map "$_=". uri_escape($r->$_()),
+ qw( county state country taxname )
+ );
+
+ $base_regions{$base_label}->{'tax'} += $x;
+ $tax += $x;
+ }
+
+}
+
+
+#ordering
+my @regions =
+ map $regions{$_},
+ sort { ( ($a eq $out) cmp ($b eq $out) ) || ($b cmp $a) }
+ keys %regions;
+
+my @base_regions =
+ map $base_regions{$_},
+ sort { ( ($a eq $out) cmp ($b eq $out) ) || ($b cmp $a) }
+ keys %base_regions;
+
+push @regions, {
+ 'label' => 'Total',
+ 'url_param' => '',
+ 'total' => $total,
+ 'exempt_cust' => $exempt_cust,
+ 'exempt_pkg' => $exempt_pkg,
+ 'exempt_monthly' => $exempt_monthly,
+ 'taxable' => $tot_taxable,
+ 'rate' => '',
+ 'owed' => $owed,
+ 'tax' => $tax,
+};
+
+#--
+
+my $money_char = $conf->config('money_char') || '$';
+my $money_sprintf = sub {
+ $money_char. sprintf('%.2f', shift );
+};
+
+sub getlabel {
+ my $r = shift;
+ my %opt = @_;
+
+ my $label;
+ if (
+ $r->tax == 0
+ && ! scalar( qsearch('cust_main_county', { 'state' => $r->state,
+ 'county' => $r->county,
+ 'country' => $r->country,
+ 'tax' => { op=>'>', value=>0 },
+ }
+ )
+ )
+
+ ) {
+ #kludge to avoid "will not stay shared" warning
+ my $out = 'Out of taxable region(s)';
+ $label = $out;
+# } elsif ( $r->taxname && count_taxname($r->taxname) == 1 ) {
+# $label = $r->taxname;
+## $regions{$label}->{'taxname'} = $label;
+## push @{$regions{$label}->{$_}}, $r->$_() foreach qw( county state country );
+ } else {
+ $label = $r->country;
+ $label = $r->state.", $label" if $r->state;
+ $label = $r->county." county, $label" if $r->county;
+ $label = "$label (". $r->taxclass. ")"
+ if $r->taxclass
+ && $cgi->param('show_taxclasses')
+ && ! $opt{'no_taxclass'};
+ $label = $r->taxname. " ($label)" if $r->taxname;
+ }
+ return $label;
+}
+
+#my %count_taxname = (); #cache
+#sub count_taxname {
+# my $taxname = shift;
+# return $count_taxname{$taxname} if exists $count_taxname{$taxname};
+# my $sql = 'SELECT COUNT(*) FROM cust_main_county WHERE taxname = ?';
+# my $sth = dbh->prepare($sql) or die dbh->errstr;
+# $sth->execute( $taxname )
+# or die "Unexpected error executing statement $sql: ". $sth->errstr;
+# $count_taxname{$taxname} = $sth->fetchrow_arrayref->[0];
+#}
+
+#false laziness w/FS::Report::Table::Monthly (sub should probably be moved up
+#to FS::Report or FS::Record or who the fuck knows where)
+sub scalar_sql {
+ my( $r, $param, $sql ) = @_;
+ #warn "$sql\n";
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute( map $r->$_(), @$param )
+ or die "Unexpected error executing statement $sql: ". $sth->errstr;
+ $sth->fetchrow_arrayref->[0] || 0;
+}
+
+my $dateagentlink = "begin=$beginning;end=$ending";
+$dateagentlink .= ';agentnum='. $cgi->param('agentnum')
+ if length($agentname);
+my $baselink = $p. "search/cust_bill_pkg.cgi?$dateagentlink";
+my $exemptlink = $p. "search/cust_tax_exempt_pkg.cgi?$dateagentlink";
+
+</%init>
diff --git a/httemplate/search/report_tax.html b/httemplate/search/report_tax.html
new file mode 100755
index 000000000..e5ffa9a17
--- /dev/null
+++ b/httemplate/search/report_tax.html
@@ -0,0 +1,42 @@
+<% include('/elements/header.html', 'Tax Report' ) %>
+
+<FORM ACTION="report_tax.cgi" METHOD="GET">
+
+<TABLE>
+
+ <% include( '/elements/tr-select-agent.html', 'disable_empty'=>0 ) %>
+
+ <% include( '/elements/tr-input-beginning_ending.html' ) %>
+% my $conf = new FS::Conf;
+% if ( $conf->exists('enable_taxclasses') ) {
+%
+
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_taxclasses" VALUE="1"></TD>
+ <TD>Show tax classes</TD>
+ </TR>
+% }
+% my @pkg_class = qsearch('pkg_class', {});
+% if ( @pkg_class ) {
+%
+
+ <TR>
+ <TD ALIGN="right"><INPUT TYPE="checkbox" NAME="show_pkgclasses" VALUE="1"></TD>
+ <TD>Show package classes</TD>
+ </TR>
+% }
+
+
+</TABLE>
+
+<BR><INPUT TYPE="submit" VALUE="Get Report">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+</%init>
diff --git a/httemplate/search/rt_transaction.html b/httemplate/search/rt_transaction.html
new file mode 100644
index 000000000..651f2896d
--- /dev/null
+++ b/httemplate/search/rt_transaction.html
@@ -0,0 +1,96 @@
+<% include('elements/search.html',
+ 'title' => 'Time worked',
+ 'name_singular' => 'transaction',
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'count_addl' => [ $format_seconds_sub, ],
+ 'header' => [ 'Ticket #',
+ 'Ticket',
+ 'Date',
+ 'Time',
+ ],
+ 'fields' => [ 'ticketid',
+ sub { encode_entities(shift->get('subject')) },
+ 'created',
+ sub { my $seconds = shift->get('transaction_time');
+ &{ $format_seconds_sub }( $seconds );
+ },
+ ],
+ 'links' => [
+ $link,
+ $link,
+ '',
+ '',
+ ],
+ )
+%>
+<%once>
+
+my $format_seconds_sub = sub {
+ my $seconds = shift;
+ (($seconds < 0) ? '-' : '') . concise(duration($seconds));
+};
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+#some amount of false laziness w/timeworked.html...
+
+my $transactiontime = "
+ CASE transactions.type when 'Set'
+ THEN (to_number(newvalue,'999999')-to_number(oldvalue, '999999')) * 60
+ ELSE timetaken*60
+ END
+";
+
+my $join = 'JOIN Tickets ON Transactions.ObjectId = Tickets.Id '.
+ 'JOIN Users ON Transactions.Creator = Users.Id ';
+
+my $where = "
+ WHERE objecttype='RT::Ticket'
+ AND ( ( Transactions.Type = 'Set'
+ AND Transactions.Field = 'TimeWorked'
+ AND Transactions.NewValue != Transactions.OldValue )
+ OR ( ( Transactions.Type='Create' OR Transactions.Type='Comment' OR Transactions.Type='Correspond' )
+ AND Transactions.TimeTaken > 0
+ )
+ )
+";
+#AND transaction_time != 0
+#AND $wheretimeleft
+
+my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
+# TIMESTAMP is Pg-specific... ?
+if ( $beginning > 0 ) {
+ $beginning = "TIMESTAMP '". time2str('%Y-%m-%d %X', $beginning). "'";
+ $where .= " AND Transactions.Created >= $beginning ";
+}
+if ( $ending < 4294967295 ) {
+ $ending = "TIMESTAMP '". time2str('%Y-%m-%d %X', $ending). "'";
+ $where .= " AND Transactions.Created <= $ending ";
+}
+
+if ( $cgi->param('otaker') && $cgi->param('otaker') =~ /^([\w\.\-]+)$/ ) {
+ $where .= " AND Users.name = '$1' ";
+}
+
+my $query = {
+ 'select' => "Transactions.*, Tickets.Id AS ticketid, Tickets.Subject, Users.name as otaker, $transactiontime AS transaction_time",
+ #'table' => 'Transactions',
+ 'table' => 'transactions',
+ 'addl_from' => $join.
+ 'LEFT JOIN acct_rt_transaction '.
+ ' ON Transactions.Id = acct_rt_transaction.transaction_id',
+ 'extra_sql' => $where,
+ 'order by' => 'ORDER BY Created',
+};
+
+my $count_query =
+ "SELECT COUNT(*), SUM($transactiontime) FROM Transactions $join $where";
+
+my $link = [ "${p}rt/Ticket/Display.html?id=", sub { shift->get('id'); } ];
+
+</%init>
diff --git a/httemplate/search/sql.html b/httemplate/search/sql.html
new file mode 100644
index 000000000..df9b8cddb
--- /dev/null
+++ b/httemplate/search/sql.html
@@ -0,0 +1,13 @@
+<% include( 'elements/search.html',
+ 'title' => 'Query Results',
+ 'name' => 'rows',
+ 'query' => 'SELECT '. ( $cgi->param('sql')
+ || errorpage('Empty query') ),
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Raw SQL');
+
+</%init>
diff --git a/httemplate/search/sqlradius.cgi b/httemplate/search/sqlradius.cgi
new file mode 100644
index 000000000..29f360298
--- /dev/null
+++ b/httemplate/search/sqlradius.cgi
@@ -0,0 +1,328 @@
+<% include( '/elements/header.html', 'RADIUS Sessions') %>
+
+% ###
+% # and finally, display the thing
+% ###
+%
+% foreach my $part_export (
+% #grep $_->can('usage_sessions'), qsearch( 'part_export' )
+% qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ),
+% qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } )
+% ) {
+% %user2svc_acct = ();
+%
+% my $efields = tie my %efields, 'Tie::IxHash', %fields;
+% delete $efields{'framedipaddress'} if $part_export->option('hide_ip');
+% if ( $part_export->option('hide_data') ) {
+% delete $efields{$_} foreach qw(acctinputoctets acctoutputoctets);
+% }
+% if ( $part_export->option('show_called_station') ) {
+% $efields->Splice(1, 0,
+% 'calledstationid' => {
+% 'name' => 'Destination',
+% 'attrib' => 'Called-Station-ID',
+% 'fmt' =>
+% sub { length($_[0]) ? shift : '&nbsp'; },
+% 'align' => 'left',
+% },
+% );
+% }
+%
+%
+
+ <% $part_export->exporttype %> to <% $part_export->machine %><BR>
+ <% include( '/elements/table-grid.html' ) %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+
+ <TR>
+% foreach my $field ( keys %efields ) {
+
+ <TH CLASS="grid" BGCOLOR="#cccccc">
+ <% $efields{$field}->{name} %><BR>
+ <FONT SIZE=-2><% $efields{$field}->{attrib} %></FONT>
+ </TH>
+
+% }
+ </TR>
+
+% foreach my $session (
+% @{ $part_export->usage_sessions( {
+% 'stoptime_start' => $beginning,
+% 'stoptime_end' => $ending,
+% 'open_sessions' => $open_sessions,
+% 'starttime_start' => $starttime_beginning,
+% 'starttime_end' => $starttime_ending,
+% 'svc_acct' => $cgi_svc_acct,
+% 'ip' => $ip,
+% 'prefix' => $prefix,
+% } )
+% }
+% ) {
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+% foreach my $field ( keys %efields ) {
+% my $html = &{ $efields{$field}->{fmt} }( $session->{$field},
+% $session,
+% $part_export,
+% );
+% my $class = ( $html =~ /<TABLE/ ? 'inv' : 'grid' );
+
+ <TD CLASS="<%$class%>" BGCOLOR="<% $bgcolor %>" ALIGN="<% $efields{$field}->{align} %>">
+ <% $html %>
+ </TD>
+% }
+ </TR>
+
+% }
+
+</TABLE>
+<BR><BR>
+
+% }
+
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+###
+# parse cgi params
+###
+
+#sort of false laziness w/cust_pay.cgi
+my( $beginning, $ending ) = ( '', '' );
+if ( $cgi->param('stoptime_beginning')
+ && $cgi->param('stoptime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
+ $beginning = str2time($1);
+}
+if ( $cgi->param('stoptime_ending')
+ && $cgi->param('stoptime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
+ $ending = str2time($1); # + 86399;
+}
+if ( $cgi->param('begin') && $cgi->param('begin') =~ /^(\d+)$/ ) {
+ $beginning = $1;
+}
+if ( $cgi->param('end') && $cgi->param('end') =~ /^(\d+)$/ ) {
+ $ending = $1;
+}
+
+my $open_sessions = '';
+if ( $cgi->param('open_sessions') =~ /^(\d*)$/ ) {
+ $open_sessions = $1;
+}
+
+my( $starttime_beginning, $starttime_ending ) = ( '', '' );
+if ( $cgi->param('starttime_beginning')
+ && $cgi->param('starttime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
+ $starttime_beginning = str2time($1);
+}
+if ( $cgi->param('starttime_ending')
+ && $cgi->param('starttime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
+ $starttime_ending = str2time($1); # + 86399;
+}
+
+my $cgi_svc_acct = '';
+if ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
+ $cgi_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $1 } );
+} elsif ( $cgi->param('username') =~ /^([^@]+)\@([^@]+)$/ ) {
+ my %search = { 'username' => $1 };
+ my $svc_domain = qsearchs('svc_domain', { 'domain' => $2 } );
+ if ( $svc_domain ) {
+ $search{'domsvc'} = $svc_domain->svcnum;
+ } else {
+ delete $search{'username'};
+ }
+ $cgi_svc_acct = qsearchs( 'svc_acct', \%search )
+ if keys %search;
+} elsif ( $cgi->param('username') =~ /^(.+)$/ ) {
+ $cgi_svc_acct = qsearchs( 'svc_acct', { 'username' => $1 } );
+}
+
+my $ip = '';
+if ( $cgi->param('ip') =~ /^((\d+\.){3}\d+)$/ ) {
+ $ip = $1;
+}
+
+my $prefix = $cgi->param('prefix');
+$prefix =~ s/\D//g;
+if ( $prefix =~ /^(\d+)$/ ) {
+ $prefix = $1;
+ $prefix = "011$prefix" unless $prefix =~ /^1/;
+} else {
+ $prefix = '';
+}
+
+###
+# field formatting subroutines
+###
+
+my %user2svc_acct = ();
+my $user_format = sub {
+ my ( $user, $session, $part_export ) = @_;
+
+ my $svc_acct = '';
+ if ( exists $user2svc_acct{$user} ) {
+ $svc_acct = $user2svc_acct{$user};
+ } else {
+ my %search = ();
+ if ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
+ my $domain;
+ if ( $user =~ /^([^@]+)\@([^@]+)$/ ) {
+ $search{'username'} = $1;
+ $domain = $2;
+ } else {
+ $search{'username'} = $user;
+ $domain = $session->{'realm'};
+ }
+ my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
+ if ( $svc_domain ) {
+ $search{'domsvc'} = $svc_domain->svcnum;
+ } else {
+ delete $search{'username'};
+ }
+ } elsif ( $part_export->exporttype eq 'sqlradius' ) {
+ $search{'username'} = $user;
+ } else {
+ die 'unknown export type '. $part_export->exporttype.
+ " for $part_export\n";
+ }
+ if ( keys %search ) {
+ my @svc_acct =
+ grep { qsearchs( 'export_svc', {
+ 'exportnum' => $part_export->exportnum,
+ 'svcpart' => $_->cust_svc->svcpart,
+ } )
+ } qsearch( 'svc_acct', \%search );
+ if ( @svc_acct ) {
+ warn 'multiple svc_acct records for user $user found; '.
+ 'using first arbitrarily'
+ if scalar(@svc_acct) > 1;
+ $user2svc_acct{$user} = $svc_acct = shift @svc_acct;
+ }
+ }
+ }
+
+ if ( $svc_acct ) {
+ my $svcnum = $svc_acct->svcnum;
+ qq(<A HREF="${p}view/svc_acct.cgi?$svcnum"><B>$user</B></A>);
+ } else {
+ "<B>$user</B>";
+ }
+
+};
+
+my $customer_format = sub {
+ my( $unused, $session ) = @_;
+ return '&nbsp;' unless exists $user2svc_acct{$session->{'username'}};
+ my $svc_acct = $user2svc_acct{$session->{'username'}};
+ my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
+ return '&nbsp;' unless $cust_pkg;
+ my $cust_main = $cust_pkg->cust_main;
+
+ qq!<A HREF="${p}view/cust_main.cgi?!. $cust_main->custnum. '">'.
+ $cust_pkg->cust_main->name. '</A>';
+};
+
+my $time_format = sub {
+ my $time = shift;
+ return '&nbsp;' if $time == 0;
+ my $pretty = time2str('%T%P %a&nbsp;%b&nbsp;%o&nbsp;%Y', $time );
+ $pretty =~ s/ (\d)(st|dn|rd|th)/$1$2/;
+ $pretty;
+};
+
+my $duration_format = sub {
+ my $seconds = shift;
+ my $hour = int($seconds/3600);
+ my $min = int( ($seconds%3600) / 60 );
+ my $sec = $seconds%60;
+ '<TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0>'.
+ '<TR><TD CLASS="inv" ALIGN="right">'.
+ ( $hour ? "<B>$hour</B>h" : '&nbsp;' ).
+ '</TD><TD CLASS="inv" ALIGN="right">'.
+ ( ( $hour || $min ) ? "<B>$min</B>m" : '&nbsp;' ).
+ '</TD><TD CLASS="inv" ALIGN="right">'.
+ "<B>$sec</B>s".
+ '</TD></TR></TABLE>';
+};
+
+my $octets_format = sub {
+ my $octets = shift;
+ my $megs = $octets / 1048576;
+ sprintf('<B>%.3f</B>&nbsp;megs', $megs);
+ #my $gigs = $octets / 1073741824
+ #sprintf('<B>%.3f</B> gigabytes', $gigs);
+};
+
+###
+# the fields
+###
+
+tie my %fields, 'Tie::IxHash',
+ 'username' => {
+ name => 'User',
+ attrib => 'UserName',
+ fmt => $user_format,
+ align => 'left',
+ },
+ 'realm' => {
+ name => 'Realm',
+ attrib => 'Realm',
+ align => 'left',
+ },
+ 'dummy' => {
+ name => 'Customer',
+ attrib => '',
+ fmt => $customer_format,
+ align => 'left',
+ },
+ 'framedipaddress' => {
+ name => 'IP&nbsp;Address',
+ attrib => 'Framed-IP-Address',
+ fmt => sub { my $ip = shift;
+ length($ip) ? $ip : '&nbsp';
+ },
+ align => 'right',
+ },
+ 'acctstarttime' => {
+ name => 'Start&nbsp;time',
+ attrib => 'Acct-Start-Time',
+ fmt => $time_format,
+ align => 'left',
+ },
+ 'acctstoptime' => {
+ name => 'End&nbsp;time',
+ attrib => 'Acct-Stop-Time',
+ fmt => $time_format,
+ align => 'left',
+ },
+ 'acctsessiontime' => {
+ name => 'Duration',
+ attrib => 'Acct-Session-Time',
+ fmt => $duration_format,
+ align => 'right',
+ },
+ 'acctinputoctets' => {
+ name => 'Upload', # (from user)',
+ attrib => 'Acct-Input-Octets',
+ fmt => $octets_format,
+ align => 'right',
+ },
+ 'acctoutputoctets' => {
+ name => 'Download', # (to user)',
+ attrib => 'Acct-Output-Octets',
+ fmt => $octets_format,
+ align => 'right',
+ },
+;
+$fields{$_}->{fmt} ||= sub { length($_[0]) ? shift : '&nbsp'; }
+ foreach keys %fields;
+
+</%init>
diff --git a/httemplate/search/sqlradius.html b/httemplate/search/sqlradius.html
new file mode 100644
index 000000000..8c405982f
--- /dev/null
+++ b/httemplate/search/sqlradius.html
@@ -0,0 +1,123 @@
+<% include( '/elements/header.html', 'Search RADIUS sessions' ) %>
+
+<FORM NAME="OneTrueForm" ACTION="sqlradius.cgi" METHOD="GET">
+% #include( '/elements/table.html' )
+
+<% ntable('#cccccc') %>
+<TR>
+ <TD ALIGN="right">Username: </TD>
+ <TD><INPUT TYPE="text" NAME="username"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><FONT SIZE="-1"><I>(leave blank to show all users)</I></FONT></TD>
+</TR>
+% my @part_export = qsearch( 'part_export', { 'exporttype' => 'sqlradius' } );
+% push @part_export,
+% qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } );
+%
+% if ( grep { ! $_->option('hide_ip') } @part_export ) {
+
+ <TR>
+ <TD ALIGN="right">IP address: </TD>
+ <TD><INPUT TYPE="text" NAME="ip"></TD>
+ </TR>
+ <TR>
+ <TD></TD>
+ <TD><FONT SIZE="-1"><I>(leave blank to show all IPs)</I></FONT></TD>
+ </TR>
+% }
+% if ( grep { $_->option('show_called_station') } @part_export ) {
+
+ <TR>
+ <TD ALIGN="right">Destination prefix:</TD>
+ <TD><INPUT TYPE="text" NAME="prefix"></TD>
+ </TR>
+ <TR>
+ <TD></TD>
+ <TD><FONT SIZE="-1"><I>(country code or country code and prefix)</I></FONT></TD>
+ </TR>
+ <TR>
+ <TD></TD>
+ <TD><FONT SIZE="-1"><I>(leave blank to show all destinations)</I></FONT></TD>
+ </TR>
+% }
+
+ <TR>
+ <TD>Show:</TD>
+ <TD>
+ <INPUT TYPE="radio" NAME="open_sessions" VALUE="0" onClick="open_changed(this);" CHECKED>Completed sessions<BR>
+ <INPUT TYPE="radio" NAME="open_sessions" VALUE="1" onClick="open_changed(this);">Open sessions
+ </TD>
+ </TR>
+
+ <TR>
+ <TH COLSPAN=2>Session start</TD>
+ </TR>
+
+ <% include( '/elements/tr-input-beginning_ending.html',
+ 'prefix' => 'starttime',
+ 'input_time' => 1,
+ )
+ %>
+
+ <SCRIPT TYPE="text/javascript">
+
+ function open_changed(what) {
+
+ var value=get_open_value(what);
+ if ( value == '1' ) {
+ what.form.stoptime_beginning_text.disabled = true;
+ what.form.stoptime_ending_text.disabled = true;
+ what.form.stoptime_beginning_text.style.backgroundColor = '#dddddd';
+ what.form.stoptime_ending_text.style.backgroundColor = '#dddddd';
+ what.form.stoptime_beginning_button.style.display = 'none';
+ what.form.stoptime_ending_button.style.display = 'none';
+ what.form.stoptime_beginning_disabled.style.display = '';
+ what.form.stoptime_ending_disabled.style.display = '';
+ } else if ( value == '0' ) {
+ what.form.stoptime_beginning_text.disabled = false;
+ what.form.stoptime_ending_text.disabled = false;
+ what.form.stoptime_beginning_text.style.backgroundColor = '#ffffff';
+ what.form.stoptime_ending_text.style.backgroundColor = '#ffffff';
+ what.form.stoptime_beginning_button.style.display = '';
+ what.form.stoptime_ending_button.style.display = '';
+ what.form.stoptime_beginning_disabled.style.display = 'none';
+ what.form.stoptime_ending_disabled.style.display = 'none';
+ }
+
+ }
+
+ function get_open_value(what) {
+ var rad_val = '';
+ for (var i=0; i < what.form.open_sessions.length; i++) {
+ if (what.form.open_sessions[i].checked) {
+ var rad_val = what.form.open_sessions[i].value;
+ }
+ }
+ return rad_val;
+ }
+
+ </SCRIPT>
+
+ <TR>
+ <TH COLSPAN=2>Session end</TD>
+ </TR>
+
+ <% include( '/elements/tr-input-beginning_ending.html',
+ 'prefix' => 'stoptime',
+ 'input_time' => 1,
+ )
+ %>
+
+</TABLE>
+<BR><INPUT TYPE="submit" VALUE="View sessions">
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
+
+</%init>
diff --git a/httemplate/search/svc_acct.cgi b/httemplate/search/svc_acct.cgi
new file mode 100755
index 000000000..232439997
--- /dev/null
+++ b/httemplate/search/svc_acct.cgi
@@ -0,0 +1,296 @@
+<% include( 'elements/search.html',
+ 'title' => 'Account Search Results',
+ 'name' => 'accounts',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => \@header,
+ 'fields' => \@fields,
+ 'links' => \@links,
+ 'align' => $align,
+ 'color' => \@color,
+ 'style' => \@style,
+ )
+%>
+<%once>
+
+#false laziness w/ClientAPI/MyAccount.pm
+sub format_time {
+ my $support = shift;
+ (($support < 0) ? '-' : '' ). int(abs($support)/3600)."h".sprintf("%02d",(abs($support)%3600)/60)."m";
+}
+
+sub timelast {
+ my( $svc_acct, $last, $permonth ) = @_;
+
+ my $sql = "
+ SELECT SUM(support) FROM acct_rt_transaction
+ LEFT JOIN Transactions
+ ON Transactions.Id = acct_rt_transaction.transaction_id
+ WHERE svcnum = ?
+ AND Transactions.Created >= ?
+ ";
+
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute( $svc_acct->svcnum,
+ time2str('%Y-%m-%d %X', time - $last*86400 )
+ )
+ or die $sth->errstr;
+
+ my $seconds = $sth->fetchrow_arrayref->[0];
+
+ my $return = (($seconds < 0) ? '-' : '') . concise(duration($seconds));
+
+ $return .= sprintf(' (%.2fx)', $seconds / $permonth ) if $permonth;
+
+ $return;
+
+}
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $link = [ "${p}view/svc_acct.cgi?", 'svcnum' ];
+my $link_cust = sub {
+ my $svc_acct = shift;
+ if ( $svc_acct->custnum ) {
+ [ "${p}view/cust_main.cgi?", 'custnum' ];
+ } else {
+ '';
+ }
+};
+
+my @extra_sql = ();
+
+my @header = ( '#', 'Service', 'Account', 'UID', 'Last Login' );
+my @fields = ( 'svcnum', 'svc', 'email', 'uid', 'last_login_text' );
+my @links = ( $link, $link, $link, $link, $link );
+my $align = 'rlllr';
+my @color = ( '', '', '', '', '' );
+my @style = ( '', '', '', '', '' );
+
+if ( $cgi->param('domain') ) {
+ my $svc_domain =
+ qsearchs('svc_domain', { 'domain' => $cgi->param('domain') } );
+ unless ( $svc_domain ) {
+ #it would be nice if this looked more like the other "not found"
+ #errors, but this will do for now.
+ errorpage("Domain ". $cgi->param('domain'). " not found at all");
+ } else {
+ push @extra_sql, 'domsvc = '. $svc_domain->svcnum;
+ }
+}
+if ( $cgi->param('domsvc') =~ /^(\d+)$/ ) {
+ push @extra_sql, "domsvc = $1";
+}
+
+my $timepermonth = '';
+
+my $orderby = 'ORDER BY svcnum';
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ my $sortby = '';
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ $sortby = $1;
+ $sortby = "LOWER($sortby)"
+ if $sortby eq 'username';
+ push @extra_sql, "$sortby IS NOT NULL"
+ if $sortby eq 'uid' || $sortby eq 'seconds' || $sortby eq 'last_login';
+ $orderby = "ORDER BY $sortby";
+ }
+
+ if ( $sortby eq 'seconds' ) {
+ #push @header, 'Time remaining';
+ push @header, 'Time';
+ push @fields, sub { my $svc_acct = shift; format_time($svc_acct->seconds) };
+ push @links, '';
+ $align .= 'r';
+ push @color, '';
+ push @style, '';
+
+ my $conf = new FS::Conf;
+ if ( $conf->exists('svc_acct-display_paid_time_remaining') ) {
+ push @header, 'Paid time', 'Last 30', 'Last 60', 'Last 90';
+ push @fields,
+ sub {
+ my $svc_acct = shift;
+ my $seconds = $svc_acct->seconds;
+ my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
+ my $part_pkg = $cust_pkg->part_pkg;
+
+ #my $timepermonth = $part_pkg->option('seconds');
+ $timepermonth = $part_pkg->option('seconds');
+ $timepermonth = $timepermonth / $part_pkg->freq
+ if $part_pkg->freq =~ /^\d+$/ && $part_pkg->freq != 0;
+
+ #my $recur = $part_pkg->calc_recur($cust_pkg);
+ my $recur = $part_pkg->base_recur($cust_pkg);
+
+ return format_time($seconds) unless $timepermonth && $recur;
+
+ my $balance = $cust_pkg->cust_main->balance;
+ my $months_unpaid = $balance / $recur;
+ my $time_unpaid = $months_unpaid * $timepermonth;
+ format_time($seconds-$time_unpaid).
+ sprintf(' (%.2fx monthly)', ( $seconds-$time_unpaid ) / $timepermonth );
+ },
+ sub { timelast( shift, 30, $timepermonth ); },
+ sub { timelast( shift, 60, $timepermonth ); },
+ sub { timelast( shift, 90, $timepermonth ); },
+ ;
+ push @links, '', '', '', '';
+ $align .= 'rrrr';
+ push @color, '', '', '', '';
+ push @style, '', '', '', '';
+ }
+
+ }
+
+} elsif ( $cgi->param('magic') =~ /^nologin$/ ) {
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $sortby = "LOWER($sortby)"
+ if $sortby eq 'username';
+ push @extra_sql, "last_login IS NULL";
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('magic') =~ /^advanced$/ ) {
+ $orderby = "";
+
+ if ( $cgi->param('agentnum') =~ /^(\d+)$/ and $1 ) {
+ push @extra_sql, "agentnum = $1";
+ }
+
+ my $pkgpart = join (' OR cust_pkg.pkgpart=',
+ grep {$_} map { /^(\d+)$/; } ($cgi->param('pkgpart')));
+ push @extra_sql, '(cust_pkg.pkgpart=' . $pkgpart . ')' if $pkgpart;
+
+ foreach my $field (qw( last_login last_logout )) {
+
+ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
+
+ next if $beginning == 0 && $ending == 4294967295;
+
+ if ($cgi->param($field."_invert")) {
+ push @extra_sql,
+ "(svc_acct.$field IS NULL OR ".
+ "svc_acct.$field < $beginning AND ".
+ "svc_acct.$field > $ending)";
+ } else {
+ push @extra_sql,
+ "svc_acct.$field IS NOT NULL",
+ "svc_acct.$field >= $beginning",
+ "svc_acct.$field <= $ending";
+ }
+
+ $orderby ||= "ORDER BY svc_acct.$field" .
+ ($cgi->param($field."_invert") ? ' DESC' : '');
+
+ }
+
+ $orderby ||= "ORDER BY svcnum";
+
+} elsif ( $cgi->param('popnum') =~ /^(\d+)$/ ) {
+ push @extra_sql, "popnum = $1";
+ $orderby = "ORDER BY LOWER(username)";
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+ $orderby = "ORDER BY uid";
+ #$orderby = "ORDER BY svcnum";
+} else {
+ $orderby = "ORDER BY uid";
+
+ my @username_sql;
+
+ my %username_type;
+ foreach ( $cgi->param('username_type') ) {
+ $username_type{$_}++;
+ }
+
+ $cgi->param('username') =~ /^([\w\-\.\&]+)$/; #untaint username_text
+ my $username = $1;
+
+ push @username_sql, "username ILIKE '$username'"
+ if $username_type{'Exact'}
+ || $username_type{'Fuzzy'};
+
+ push @username_sql, "username ILIKE '\%$username\%'"
+ if $username_type{'Substring'}
+ || $username_type{'All'};
+
+ if ( $username_type{'Fuzzy'} || $username_type{'All'} ) {
+ &FS::svc_acct::check_and_rebuild_fuzzyfiles;
+ my $all_username = &FS::svc_acct::all_username;
+
+ my %username;
+ if ( $username_type{'Fuzzy'} || $username_type{'All'} ) {
+ foreach ( amatch($username, [ qw(i) ], @$all_username) ) {
+ $username{$_}++;
+ }
+ }
+
+ #if ($username_type{'Sound-alike'}) {
+ #}
+
+ push @username_sql, "username = '$_'"
+ foreach (keys %username);
+
+ }
+
+ push @extra_sql, '( '. join( ' OR ', @username_sql). ' )';
+
+}
+
+push @header, FS::UI::Web::cust_header($cgi->param('cust_fields'));
+push @fields, \&FS::UI::Web::cust_fields,
+push @links, map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header($cgi->param('cust_fields'));
+$align .= FS::UI::Web::cust_aligns();
+push @color, FS::UI::Web::cust_colors();
+push @style, FS::UI::Web::cust_styles();
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql =
+ scalar(@extra_sql)
+ ? ' WHERE '. join(' AND ', @extra_sql )
+ : '';
+
+my $count_query = "SELECT COUNT(*) FROM svc_acct $addl_from $extra_sql";
+#if ( keys %svc_acct ) {
+# $count_query .= ' WHERE '.
+# join(' AND ', map "$_ = ". dbh->quote($svc_acct{$_}),
+# keys %svc_acct
+# );
+#}
+
+my $sql_query = {
+ 'table' => 'svc_acct',
+ 'hashref' => {}, # \%svc_acct,
+ 'select' => join(', ',
+ 'svc_acct.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+</%init>
diff --git a/httemplate/search/svc_broadband.cgi b/httemplate/search/svc_broadband.cgi
new file mode 100755
index 000000000..2cb0c1eb3
--- /dev/null
+++ b/httemplate/search/svc_broadband.cgi
@@ -0,0 +1,123 @@
+<% include( 'elements/search.html',
+ 'title' => 'Broadband Search Results',
+ 'name' => 'broadband services',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => [ popurl(2). "view/svc_broadband.cgi?", 'svcnum' ],
+ 'header' => [ '#',
+ 'Service',
+ 'Router',
+ 'IP Address',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ sub { $routerbyblock{shift->blocknum}->routername; },
+ 'ip_addr',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link_router,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rllr'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my %svc_broadband = ();
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+} elsif ( $cgi->param('ip_addr') =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/ ) {
+ push @extra_sql, "ip_addr = '$1'";
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql = '';
+if ( @extra_sql ) {
+ $extra_sql = ( keys(%svc_broadband) ? ' AND ' : ' WHERE ' ).
+ join(' AND ', @extra_sql );
+}
+
+my $count_query = "SELECT COUNT(*) FROM svc_broadband $addl_from ";
+#if ( keys %svc_broadband ) {
+# $count_query .= ' WHERE '.
+# join(' AND ', map "$_ = ". dbh->quote($svc_broadband{$_}),
+# keys %svc_broadband
+# );
+#}
+$count_query .= $extra_sql;
+
+my $sql_query = {
+ 'table' => 'svc_broadband',
+ 'hashref' => {}, #\%svc_broadband,
+ 'select' => join(', ',
+ 'svc_broadband.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $extra_sql,
+ 'addl_from' => $addl_from,
+};
+
+my %routerbyblock = ();
+foreach my $router (qsearch('router', {})) {
+ foreach ($router->addr_block) {
+ $routerbyblock{$_->blocknum} = $router;
+ }
+}
+
+my $link = [ $p.'view/svc_broadband.cgi', 'svcnum' ];
+
+#XXX get the router link working
+my $link_router = sub { my $routernum = $routerbyblock{shift->blocknum}->routernum;
+ [ $p.'view/router.cgi?'.$routernum, 'routernum' ];
+ };
+
+my $link_cust = [ $p.'view/cust_main.cgi', 'custnum' ];
+
+</%init>
diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi
new file mode 100755
index 000000000..08ffdba5e
--- /dev/null
+++ b/httemplate/search/svc_domain.cgi
@@ -0,0 +1,112 @@
+<% include( 'elements/search.html',
+ 'title' => "Domain Search Results",
+ 'name' => 'domains',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ 'Domain',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ 'domain',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rll'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my %svc_domain = ();
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+} else {
+ $cgi->param('domain') =~ /^([\w\-\.]+)$/;
+ $svc_domain{'domain'} = $1;
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql = '';
+if ( @extra_sql ) {
+ $extra_sql = ( keys(%svc_domain) ? ' AND ' : ' WHERE ' ).
+ join(' AND ', @extra_sql );
+}
+
+my $count_query = "SELECT COUNT(*) FROM svc_domain $addl_from ";
+if ( keys %svc_domain ) {
+ $count_query .= ' WHERE '.
+ join(' AND ', map "$_ = ". dbh->quote($svc_domain{$_}),
+ keys %svc_domain
+ );
+}
+$count_query .= $extra_sql;
+
+my $sql_query = {
+ 'table' => 'svc_domain',
+ 'hashref' => \%svc_domain,
+ 'select' => join(', ',
+ 'svc_domain.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+my $link = [ "${p}view/svc_domain.cgi?", 'svcnum' ];
+
+#smaller false laziness w/svc_*.cgi here
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+</%init>
diff --git a/httemplate/search/svc_external.cgi b/httemplate/search/svc_external.cgi
new file mode 100755
index 000000000..2710d75bc
--- /dev/null
+++ b/httemplate/search/svc_external.cgi
@@ -0,0 +1,153 @@
+%die "access denied"
+% unless $FS::CurrentUser::CurrentUser->access_right('List services');
+%
+%my $conf = new FS::Conf;
+%
+%my @svc_external = ();
+%my @h_svc_external = ();
+%my $sortby=\*svcnum_sort;
+%if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+%
+% @svc_external=qsearch('svc_external',{});
+%
+% if ( $cgi->param('magic') eq 'unlinked' ) {
+% @svc_external = grep { qsearchs('cust_svc', {
+% 'svcnum' => $_->svcnum,
+% 'pkgnum' => '',
+% }
+% )
+% }
+% @svc_external;
+% }
+%
+% if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+% my $sortby = $1;
+% if ( $sortby eq 'id' ) {
+% $sortby = \*id_sort;
+% }
+% }
+%
+%} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+%
+% @svc_external =
+% qsearch( 'svc_external', {}, '',
+% " WHERE $1 = ( SELECT svcpart FROM cust_svc ".
+% " WHERE cust_svc.svcnum = svc_external.svcnum ) "
+% );
+%
+%} elsif ( $cgi->param('title') =~ /^(.*)$/ ) {
+% $sortby=\*id_sort;
+% @svc_external=qsearch('svc_external',{ title => $1 });
+% if( $cgi->param('history') == 1 ) {
+% @h_svc_external=qsearch('h_svc_external',{ title => $1 });
+% }
+%} elsif ( $cgi->param('id') =~ /^([\w\-\.]+)$/ ) {
+% my $id = $1;
+% @svc_external = qsearchs('svc_external',{'id'=>$id});
+%}
+%
+%if ( scalar(@svc_external) == 1 ) {
+%
+%
+<% $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum) %>
+%
+%
+%} elsif ( scalar(@svc_external) == 0 ) {
+%
+%
+<% include('/elements/header.html', 'External Search Results' ) %>
+
+ No matching external services found
+% } else {
+%
+%
+<% include('/elements/header.html', 'External Search Results', '') %>
+
+ <% scalar(@svc_external) %> matching external services found
+ <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TH>Service #</TH>
+ <TH><% FS::Msgcat::_gettext('svc_external-id') || 'External&nbsp;ID' %></TH>
+ <TH><% FS::Msgcat::_gettext('svc_external-title') || 'Title' %></TH>
+ </TR>
+%
+% foreach my $svc_external (
+% sort $sortby (@svc_external)
+% ) {
+% my($svcnum, $id, $title)=(
+% $svc_external->svcnum,
+% $svc_external->id,
+% $svc_external->title,
+% );
+%
+% my $rowspan = 1;
+%
+% print <<END;
+% <TR>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$svcnum</A></TD>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$id</A></TD>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/svc_external.cgi?$svcnum">$title</A></TD>
+%END
+%
+% #print @rows;
+% print "</TR>";
+%
+% }
+% if( scalar(@h_svc_external) > 0 ) {
+% print <<HTML;
+% </TABLE>
+% <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
+% <TR>
+% <TH>Freeside ID</TH>
+% <TH>Service #</TH>
+% <TH>Title</TH>
+% <TH>Date</TH>
+% </TR>
+%HTML
+%
+% foreach my $h_svc ( @h_svc_external ) {
+% my($svcnum, $id, $title, $user, $date)=(
+% $h_svc->svcnum,
+% $h_svc->id,
+% $h_svc->title,
+% $h_svc->history_user,
+% $h_svc->history_date,
+% );
+% my $rowspan = 1;
+% my ($h_cust_svc) = qsearchs( 'h_cust_svc', {
+% svcnum => $svcnum,
+% });
+% my $cust_pkg = qsearchs( 'cust_pkg', {
+% pkgnum => $h_cust_svc->pkgnum,
+% });
+% my $custnum = $cust_pkg->custnum;
+%
+% print <<END;
+% <TR>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$custnum</A></TD>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$svcnum</A></TD>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$title</A></TD>
+% <TD ROWSPAN=$rowspan><A HREF="${p}view/cust_main.cgi?$custnum">$date</A></TD>
+% </TR>
+%END
+% }
+% }
+%
+% print <<END;
+% </TABLE>
+% </BODY>
+%</HTML>
+%END
+%
+%}
+%
+%sub svcnum_sort {
+% $a->getfield('svcnum') <=> $b->getfield('svcnum');
+%}
+%
+%sub id_sort {
+% $a->getfield('id') <=> $b->getfield('id');
+%}
+%
+%
+
diff --git a/httemplate/search/svc_forward.cgi b/httemplate/search/svc_forward.cgi
new file mode 100755
index 000000000..2bcd0c8c8
--- /dev/null
+++ b/httemplate/search/svc_forward.cgi
@@ -0,0 +1,146 @@
+<% include( 'elements/search.html',
+ 'title' => "Mail forward Search Results",
+ 'name' => 'mail forwards',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ 'Mail to',
+ 'Forwards to',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ $format_src,
+ $format_dst,
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link_src,
+ $link_dst,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rlll'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql =
+ scalar(@extra_sql)
+ ? ' WHERE '. join(' AND ', @extra_sql )
+ : '';
+
+my $count_query = "SELECT COUNT(*) FROM svc_forward $addl_from $extra_sql";
+my $sql_query = {
+ 'table' => 'svc_forward',
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'svc_forward.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+# <TH>Service #<BR><FONT SIZE=-1>(click to view forward)</FONT></TH>
+# <TH>Mail to<BR><FONT SIZE=-1>(click to view account)</FONT></TH>
+# <TH>Forwards to<BR><FONT SIZE=-1>(click to view account)</FONT></TH>
+
+my $link = [ "${p}view/svc_forward.cgi?", 'svcnum' ];
+
+my $format_src = sub {
+ my $svc_forward = shift;
+ if ( $svc_forward->srcsvc_acct ) {
+ $svc_forward->srcsvc_acct->email;
+ } else {
+ my $src = $svc_forward->src;
+ $src = "<I>(anything)</I>$src" if $src =~ /^@/;
+ $src;
+ }
+};
+
+my $link_src = sub {
+ my $svc_forward = shift;
+ if ( $svc_forward->srcsvc_acct ) {
+ [ "${p}view/svc_acct.cgi?", 'srcsvc' ];
+ } else {
+ '';
+ }
+};
+
+my $format_dst = sub {
+ my $svc_forward = shift;
+ if ( $svc_forward->dstsvc_acct ) {
+ $svc_forward->dstsvc_acct->email;
+ } else {
+ $svc_forward->dst;
+ }
+};
+
+my $link_dst = sub {
+ my $svc_forward = shift;
+ if ( $svc_forward->dstsvc_acct ) {
+ [ "${p}view/svc_acct.cgi?", 'dstsvc' ];
+ } else {
+ '';
+ }
+};
+
+#smaller false laziness w/svc_*.cgi here
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+</%init>
diff --git a/httemplate/search/svc_phone.cgi b/httemplate/search/svc_phone.cgi
new file mode 100644
index 000000000..49340c6c3
--- /dev/null
+++ b/httemplate/search/svc_phone.cgi
@@ -0,0 +1,117 @@
+<% include( 'elements/search.html',
+ 'title' => "Phone number search results",
+ 'name' => 'phone numbers',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ 'Country code',
+ 'Phone number',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ 'countrycode',
+ 'phonenum',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rlrr'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my %svc_phone = ();
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+} else {
+ $cgi->param('phonenum') =~ /^([\d\- ]+)$/;
+ ( $svc_phone{'phonenum'} = $1 ) =~ s/\D//g;
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql = '';
+if ( @extra_sql ) {
+ $extra_sql = ( keys(%svc_phone) ? ' AND ' : ' WHERE ' ).
+ join(' AND ', @extra_sql );
+}
+
+my $count_query = "SELECT COUNT(*) FROM svc_phone $addl_from ";
+if ( keys %svc_phone ) {
+ $count_query .= ' WHERE '.
+ join(' AND ', map "$_ = ". dbh->quote($svc_phone{$_}),
+ keys %svc_phone
+ );
+}
+$count_query .= $extra_sql;
+
+my $sql_query = {
+ 'table' => 'svc_phone',
+ 'hashref' => \%svc_phone,
+ 'select' => join(', ',
+ 'svc_phone.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+my $link = [ "${p}view/svc_phone.cgi?", 'svcnum' ];
+
+#smaller false laziness w/svc_*.cgi here
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+</%init>
diff --git a/httemplate/search/svc_www.cgi b/httemplate/search/svc_www.cgi
new file mode 100755
index 000000000..2e3c4615b
--- /dev/null
+++ b/httemplate/search/svc_www.cgi
@@ -0,0 +1,113 @@
+<% include( 'elements/search.html',
+ 'title' => 'Virtual Host Search Results',
+ 'name' => 'virtual hosts',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ 'Zone',
+ 'User',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ sub { $_[0]->domain_record->zone },
+ sub {
+ my $svc_www = shift;
+ my $svc_acct = $svc_www->svc_acct;
+ $svc_acct
+ ? $svc_acct->email
+ : '';
+ },
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ '',
+ $ulink,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rlll'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+#my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql =
+ scalar(@extra_sql)
+ ? ' WHERE '. join(' AND ', @extra_sql )
+ : '';
+
+
+my $count_query = "SELECT COUNT(*) FROM svc_www $addl_from $extra_sql";
+my $sql_query = {
+ 'table' => 'svc_www',
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'svc_www.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => "$extra_sql $orderby",
+ 'addl_from' => $addl_from,
+};
+
+my $link = [ "${p}view/svc_www.cgi?", 'svcnum', ];
+#my $dlink = [ "${p}view/svc_www.cgi?", 'svcnum', ];
+my $ulink = [ "${p}view/svc_acct.cgi?", 'usersvc', ];
+
+#smaller false laziness w/svc_*.cgi here
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+</%init>
diff --git a/httemplate/search/timeworked.html b/httemplate/search/timeworked.html
new file mode 100644
index 000000000..b72dd0ea9
--- /dev/null
+++ b/httemplate/search/timeworked.html
@@ -0,0 +1,117 @@
+<% include( 'elements/search.html',
+ 'title' => 'Time Worked',
+ 'name' => 'time',
+ 'html_form' => qq!<FORM NAME="timeForm" ACTION="${p}misc/timeworked.html" METHOD="POST">!,
+ 'query' => $query,
+ 'count_query' => $count_query,
+ 'header' => [ '#',
+ 'Ticket',
+ 'Date',
+ 'Time',
+ '', # checkbox column
+ ],
+ 'fields' => [ sub { shift->[0] },
+ sub { encode_entities(shift->[1]) },
+ sub { shift->[2] },
+ sub { my $seconds = shift->[3];
+ (($seconds < 0) ? '-' : '') .
+ concise(duration($seconds));
+ },
+ sub {
+ my $row = shift;
+ my $seconds = $row->[3];
+ my $id = $row->[4];
+ qq!<INPUT NAME="transactionid$id" TYPE="checkbox" VALUE="1">!.
+ qq!<INPUT NAME="seconds$id" TYPE="hidden" VALUE="$seconds">!;
+ },
+ ],
+ 'links' => [
+ $link,
+ $link,
+ '',
+ '',
+ '',
+ ],
+ 'html_foot' => sub {
+ '<BR><INPUT TYPE="button" VALUE="select all" onClick="setAll(true)">'.
+ '<INPUT TYPE="button" VALUE="unselect all" onClick="setAll(false)">'.
+ '<BR><INPUT TYPE="submit" NAME="action" VALUE="Assign to accounts"><BR>'.
+ '<SCRIPT TYPE="text/javascript">'.
+ ' function setAll(setTo) { '.
+ ' theForm = document.timeForm;'.
+ ' for (i=0,n=theForm.elements.length;i<n;i++)'.
+ ' if (theForm.elements[i].name.indexOf("transactionid") != -1)'.
+ ' theForm.elements[i].checked = setTo;'.
+ ' }'.
+ '</SCRIPT>';
+ },
+ )
+
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Time queue');
+
+my @groupby = ();
+
+my $transactiontime = "
+ CASE Transactions.Type WHEN 'Set'
+ THEN (TO_NUMBER(NewValue,'999999')-TO_NUMBER(OldValue, '999999')) * 60
+ ELSE TimeTaken*60
+ END
+";
+
+push @groupby, qw( transactions.type newvalue oldvalue timetaken );
+
+my $appliedtimeclause = "COALESCE (SUM(acct_rt_transaction.seconds), 0)";
+
+my $appliedtimeselect = "
+ COALESCE(
+ ( SELECT SUM(seconds) FROM acct_rt_transaction
+ WHERE transaction_id = Transactions.id
+ ),
+ 0
+ )
+";
+
+push @groupby, "Transactions.id";
+
+my $wheretimeleft = "$transactiontime != $appliedtimeselect";
+
+push @groupby, "Tickets.id";
+push @groupby, "Tickets.Subject";
+push @groupby, "Transactions.Created";
+
+my $groupby = join(',', @groupby);
+
+my $where = "
+ WHERE ObjectType='RT::Ticket'
+ AND ( ( Transactions.Type='Set' AND Field='TimeWorked' )
+ OR Transactions.Type='Create'
+ OR Transactions.Type='Comment'
+ OR Transactions.Type='Correspond'
+ )
+ AND $wheretimeleft
+";
+ #AND $wheretimeleft
+
+my $query = "
+ SELECT Tickets.id, Tickets.Subject,
+ TO_CHAR(Transactions.Created, 'Dy Mon DD HH24:MI:SS YYYY'),
+ $transactiontime-$appliedtimeclause,
+ Transactions.id
+ FROM Transactions
+ JOIN Tickets ON Transactions.ObjectId = Tickets.id
+ LEFT JOIN acct_rt_transaction
+ ON Transactions.id = acct_rt_transaction.transaction_id
+ $where
+ GROUP BY $groupby
+ ORDER BY Transactions.Created
+";
+
+my $count_query = "SELECT COUNT(*) FROM Transactions $where";
+
+my $link = [ "${p}rt/Ticket/Display.html?id=", sub { shift->[0]; } ];
+
+</%init>
diff --git a/httemplate/view/REAL_logo.cgi b/httemplate/view/REAL_logo.cgi
new file mode 100755
index 000000000..c269c7d04
--- /dev/null
+++ b/httemplate/view/REAL_logo.cgi
@@ -0,0 +1,14 @@
+<% $conf->config_binary("logo.png", $agentnum) %>
+<%init>
+
+my $conf = new FS::Conf;
+
+my $agentnum = '';
+my @agentnums = $FS::CurrentUser::CurrentUser->agentnums;
+if ( scalar(@agentnums) == 1 ) {
+ $agentnum = $agentnums[0];
+}
+
+http_header('Content-Type' => 'image/png' );
+
+</%init>
diff --git a/httemplate/view/cust_bill-logo.cgi b/httemplate/view/cust_bill-logo.cgi
new file mode 100755
index 000000000..09ac9a717
--- /dev/null
+++ b/httemplate/view/cust_bill-logo.cgi
@@ -0,0 +1,31 @@
+<% $conf->config_binary("logo$templatename.png", $agentnum) %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices')
+ or $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+my $templatename;
+my $agentnum = '';
+if ( $cgi->param('invnum') ) {
+ $templatename = $cgi->param('templatename');
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $cgi->param('invnum') } )
+ or die 'unknown invnum';
+ $agentnum = $cust_bill->cust_main->agentnum;
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^([^\.\/]*)$/ or die 'illegal query';
+ $templatename = $1;
+}
+
+if ( $templatename && $conf->exists("logo_$templatename.png") ) {
+ $templatename = "_$templatename";
+} else {
+ $templatename = '';
+}
+
+http_header('Content-Type' => 'image/png' );
+
+</%init>
diff --git a/httemplate/view/cust_bill-pdf.cgi b/httemplate/view/cust_bill-pdf.cgi
new file mode 100755
index 000000000..f09e1b74d
--- /dev/null
+++ b/httemplate/view/cust_bill-pdf.cgi
@@ -0,0 +1,28 @@
+<% $pdf %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)(.pdf)?$/;
+my $templatename = $2;
+my $invnum = $3;
+
+my $cust_bill = qsearchs({
+ 'select' => 'cust_bill.*',
+ 'table' => 'cust_bill',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'invnum' => $invnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Invoice #$invnum not found!" unless $cust_bill;
+
+my $pdf = $cust_bill->print_pdf( '', $templatename);
+
+http_header('Content-Type' => 'application/pdf' );
+http_header('Content-Length' => length($pdf) );
+http_header('Cache-control' => 'max-age=60' );
+
+</%init>
diff --git a/httemplate/view/cust_bill-ps.cgi b/httemplate/view/cust_bill-ps.cgi
new file mode 100755
index 000000000..5313dbf02
--- /dev/null
+++ b/httemplate/view/cust_bill-ps.cgi
@@ -0,0 +1,24 @@
+<% $cust_bill->print_ps( '', $templatename) %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $templatename = $2;
+my $invnum = $3;
+
+my $cust_bill = qsearchs({
+ 'select' => 'cust_bill.*',
+ 'table' => 'cust_bill',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'invnum' => $invnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Invoice #$invnum not found!" unless $cust_bill;
+
+http_header('Content-Type' => 'application/postscript' );
+
+</%init>
diff --git a/httemplate/view/cust_bill.cgi b/httemplate/view/cust_bill.cgi
new file mode 100755
index 000000000..450c74e61
--- /dev/null
+++ b/httemplate/view/cust_bill.cgi
@@ -0,0 +1,120 @@
+<% include("/elements/header.html",'Invoice View', menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+)) %>
+
+
+% if ( $cust_bill->owed > 0
+% && scalar( grep $payby{$_}, qw(BILL CASH WEST MCRD) )
+% && $FS::CurrentUser::CurrentUser->access_right('Post payment')
+% )
+% {
+% my $s = 0;
+
+ Post
+
+% if ( $payby{'BILL'} ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=BILL;invnum=<% $invnum %>">check</A>
+% }
+
+% if ( $payby{'CASH'} ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=CASH;invnum=<% $invnum %>">cash</A>
+% }
+
+% if ( $payby{'WEST'} ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;invnum=<% $invnum %>">Western Union</A>
+% }
+
+% if ( $payby{'MCRD'} ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;invnum=<% $invnum %>">manual credit card</A>
+% }
+
+ payment against this invoice<BR><BR>
+
+% }
+
+
+% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
+
+ <A HREF="<% $p %>misc/print-invoice.cgi?<% $link %>">Re-print this invoice</A>
+
+% if ( grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ) {
+ | <A HREF="<% $p %>misc/email-invoice.cgi?<% $link %>">Re-email this invoice</A>
+% }
+
+% if ( $conf->exists('hylafax') && length($cust_bill->cust_main->fax) ) {
+ | <A HREF="<% $p %>misc/fax-invoice.cgi?<% $link %>">Re-fax this invoice</A>
+% }
+
+ <BR><BR>
+
+% }
+
+
+% if ( $conf->exists('invoice_latex') ) {
+
+ <A HREF="<% $p %>view/cust_bill-pdf.cgi?<% $link %>.pdf">View typeset invoice</A>
+ <BR><BR>
+% }
+
+% my $br = 0;
+% if ( $cust_bill->num_cust_event ) { $br++;
+<A HREF="<%$p%>search/cust_event.html?invnum=<% $cust_bill->invnum %>">(&nbsp;View invoice events&nbsp;)</A>
+% }
+
+% if ( $cust_bill->num_cust_bill_event ) { $br++;
+<A HREF="<%$p%>search/cust_bill_event.cgi?invnum=<% $cust_bill->invnum %>">(&nbsp;View deprecated, old-style invoice events&nbsp;)</A>
+% }
+
+<% $br ? '<BR><BR>' : '' %>
+
+% if ( $conf->exists('invoice_html') ) {
+
+ <% join('', $cust_bill->print_html('', $templatename) ) %>
+% } else {
+
+ <PRE><% join('', $cust_bill->print_text('', $templatename) ) %></PRE>
+% }
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^((.+)-)?(\d+)$/;
+my $templatename = $2;
+my $invnum = $3;
+
+my $conf = new FS::Conf;
+
+my @payby = grep /\w/, $conf->config('payby');
+#@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
+@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
+ unless @payby;
+my %payby = map { $_=>1 } @payby;
+
+my $cust_bill = qsearchs({
+ 'select' => 'cust_bill.*',
+ 'table' => 'cust_bill',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'invnum' => $invnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Invoice #$invnum not found!" unless $cust_bill;
+
+my $custnum = $cust_bill->custnum;
+my $display_custnum = $cust_bill->cust_main->display_custnum;
+
+#my $printed = $cust_bill->printed;
+
+my $link = $templatename ? "$templatename-$invnum" : $invnum;
+
+</%init>
+
+
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
new file mode 100755
index 000000000..2231d4148
--- /dev/null
+++ b/httemplate/view/cust_main.cgi
@@ -0,0 +1,158 @@
+<% include("/elements/header.html","Customer View: ". $cust_main->name ) %>
+
+% if ( $curuser->access_right('Edit customer') ) {
+ <A HREF="<% $p %>edit/cust_main.cgi?<% $custnum %>">Edit this customer</A> |
+% }
+
+<% include('/elements/init_overlib.html') %>
+
+<SCRIPT TYPE="text/javascript">
+function areyousure(href, message) {
+ if (confirm(message) == true)
+ window.location.href = href;
+}
+</SCRIPT>
+
+% if ( $curuser->access_right('Cancel customer')
+% && $cust_main->ncancelled_pkgs
+% ) {
+
+ <% include( '/elements/popup_link-cust_main.html',
+ { 'action' => $p. 'misc/cancel_cust.html',
+ 'label' => 'Cancel&nbsp;this&nbsp;customer',
+ 'actionlabel' => 'Confirm Cancellation',
+ 'color' => '#ff0000',
+ 'cust_main' => $cust_main,
+ }
+ )
+ %> |
+
+% }
+
+% if ( $conf->exists('deletecustomers')
+% && $curuser->access_right('Delete customer')
+% ) {
+ <A HREF="<% $p %>misc/delete-customer.cgi?<% $custnum%>">Delete this customer</A> |
+% }
+
+% unless ( $conf->exists('disable_customer_referrals') ) {
+ <A HREF="<% $p %>edit/cust_main.cgi?referral_custnum=<% $custnum %>">Refer a new customer</A> |
+ <A HREF="<% $p %>search/cust_main.cgi?referral_custnum=<% $custnum %>">View this customer's referrals</A>
+% }
+
+<BR><BR>
+
+% if ( $curuser->access_right('Billing event reports')
+% || $curuser->access_right('View customer billing events')
+% ) {
+
+ <A HREF="<% $p %>search/cust_event.html?custnum=<% $custnum %>">View billing events for this customer</A>
+ <BR><BR>
+
+% }
+
+%my $signupurl = $conf->config('signupurl');
+%if ( $signupurl ) {
+ This customer's signup URL: <A HREF="<% $signupurl %>?ref=<% $custnum %>"><% $signupurl %>?ref=<% $custnum %></A><BR><BR>
+% }
+
+
+<A NAME="cust_main"></A>
+<TABLE BORDER=0>
+<TR>
+ <TD VALIGN="top">
+ <% include('cust_main/contacts.html', $cust_main ) %>
+ </TD>
+ <TD VALIGN="top" STYLE="padding-left: 54px">
+ <% include('cust_main/misc.html', $cust_main ) %>
+% if ( $conf->config('payby-default') ne 'HIDE' ) {
+
+ <BR>
+ <% include('cust_main/billing.html', $cust_main ) %>
+% }
+
+ </TD>
+</TR>
+</TABLE>
+%
+%if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
+%
+
+<BR>
+Comments
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TR>
+ <TD BGCOLOR="#ffffff">
+ <PRE><% encode_entities($cust_main->comments) %></PRE>
+ </TD>
+</TR>
+</TABLE></TABLE>
+% }
+<BR><BR>
+% my $notecount = scalar($cust_main->notes());
+% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
+
+<A NAME="cust_main_note"><FONT SIZE="+2">Notes</FONT></A><BR>
+% if ( $curuser->access_right('Add customer note') &&
+% ! $conf->exists('cust_main-disable_notes')
+% ) {
+
+ <% include( '/elements/popup_link-cust_main.html',
+ 'label' => 'Add customer note',
+ 'action' => $p. 'edit/cust_main_note.cgi',
+ 'actionlabel' => 'Enter customer note',
+ 'cust_main' => $cust_main,
+ 'width' => 616,
+ 'height' => 408,
+ )
+ %>
+
+% }
+
+<BR>
+
+<% include('cust_main/notes.html', 'custnum' => $cust_main->custnum ) %>
+
+% }
+
+
+% if ( $conf->config('ticket_system') ) {
+
+ <BR><BR>
+ <% include('cust_main/tickets.html', $cust_main ) %>
+% }
+
+
+<BR><BR>
+
+% #XXX enable me# if ( $curuser->access_right('View customer packages') {
+<% include('cust_main/packages.html', $cust_main ) %>
+% #}
+
+% if ( $conf->config('payby-default') ne 'HIDE' ) {
+ <% include('cust_main/payment_history.html', $cust_main ) %>
+% }
+
+
+<% include('/elements/footer.html') %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('View customer');
+
+my $conf = new FS::Conf;
+
+die "No customer specified (bad URL)!" unless $cgi->keywords;
+my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array
+$query =~ /^(\d+)$/;
+my $custnum = $1;
+my $cust_main = qsearchs( {
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+die "Customer not found!" unless $cust_main;
+
+</%init>
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
new file mode 100644
index 000000000..aea90e8b3
--- /dev/null
+++ b/httemplate/view/cust_main/billing.html
@@ -0,0 +1,220 @@
+Billing information
+%# If we can't see the unencrypted card, then bill now is an exercise in
+%# frustration (without some sort of job queue magic to send it to a secure
+%# machine, anyway)
+%if ( $FS::CurrentUser::CurrentUser->access_right('Bill customer now')
+% && ! $cust_main->is_encrypted($cust_main->payinfo)
+% ) {
+ (<A HREF="<% $p %>misc/bill.cgi?<% $cust_main->custnum %>">Bill now</A>)
+% }
+
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+
+%( my $balance = $cust_main->balance )
+% =~ s/^(\-?)(.*)$/<FONT SIZE=+1>$1<\/FONT>$money_char$2/;
+
+<TR>
+ <TD ALIGN="right">Balance due</TD>
+ <TD BGCOLOR="#ffffff"><B><% $balance %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Billing&nbsp;type</TD>
+ <TD BGCOLOR="#ffffff">
+% if ( $cust_main->payby eq 'CARD' || $cust_main->payby eq 'DCRD' ) {
+
+
+ Credit&nbsp;card&nbsp;<% $cust_main->payby eq 'CARD' ? '(automatic)' : '(on-demand)' %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Card number</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->paymask %></TD>
+</TR>
+%
+%#false laziness w/elements/select-month_year.html & edit/cust_main/billing.html
+%my( $mon, $year );
+%my $date = $cust_main->paydate || '12-2037';
+%if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
+% ( $mon, $year ) = ( $2, $1 );
+%} elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+% ( $mon, $year ) = ( $1, $3 );
+%} else {
+% warn "unrecognized expiration date format: $date";
+% ( $mon, $year ) = ( '', '' );
+%}
+%
+
+<TR>
+ <TD ALIGN="right">Expiration</TD>
+ <TD BGCOLOR="#ffffff"><% "$mon/$year" %></TD>
+</TR>
+% if ( $cust_main->paystart_month ) {
+
+ <TR>
+ <TD ALIGN="right">Start date</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->paystart_month. '/'. $cust_main->paystart_year %>
+ </TR>
+% } elsif ( $cust_main->payissue ) {
+
+ <TR>
+ <TD ALIGN="right">Issue #</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payissue %>
+ </TR>
+% }
+
+
+<TR>
+ <TD ALIGN="right">Name on card</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
+</TR>
+% } elsif ( $cust_main->payby eq 'CHEK' || $cust_main->payby eq 'DCHK') {
+% my( $account, $aba ) = split('@', $cust_main->paymask );
+
+
+ Electronic&nbsp;check&nbsp;<% $cust_main->payby eq 'CHEK' ? '(automatic)' : '(on-demand)' %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">ABA/Routing code</TD>
+ <TD BGCOLOR="#ffffff"><% $aba %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Account number</TD>
+ <TD BGCOLOR="#ffffff"><% $account %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Account type</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->paytype %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Bank name</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
+</TR>
+% if ( $conf->exists('show_bankstate') ) {
+<TR>
+ <TD ALIGN="right"><% $paystate_label %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->paystate || '&nbsp;&nbsp;&nbsp;' %></TD>
+</TR>
+% }
+% } elsif ( $cust_main->payby eq 'LECB' ) {
+% $cust_main->payinfo =~ /^(\d{3})(\d{3})(\d{4})$/;
+% my $payinfo = "$1-$2-$3";
+%
+
+
+ Phone&nbsp;bill&nbsp;billing
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Phone number</TD>
+ <TD BGCOLOR="#ffffff"><% $payinfo %></TD>
+</TR>
+% } elsif ( $cust_main->payby eq 'BILL' ) {
+
+
+ Billing
+ </TD>
+</TR>
+% if ( $cust_main->payinfo ) {
+
+<TR>
+ <TD ALIGN="right">P.O. </TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payinfo %></TD>
+</TR>
+% }
+
+
+<TR>
+ <TD ALIGN="right">Attention</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
+</TR>
+% } elsif ( $cust_main->payby eq 'COMP' ) {
+
+
+ Complimentary
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Authorized&nbsp;by</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->payinfo %></TD>
+</TR>
+%
+%#false laziness w/above etc.
+%my( $mon, $year );
+%my $date = $cust_main->paydate || '12-2037';
+%if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
+% ( $mon, $year ) = ( $2, $1 );
+%} elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+% ( $mon, $year ) = ( $1, $3 );
+%} else {
+% warn "unrecognized expiration date format: $date";
+% ( $mon, $year ) = ( '', '' );
+%}
+%
+
+<TR>
+ <TD ALIGN="right">Expiration</TD>
+ <TD BGCOLOR="#ffffff"><% "$mon/$year" %></TD>
+</TR>
+% }
+
+
+<TR>
+ <TD ALIGN="right">Tax&nbsp;exempt</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->tax ? 'yes' : 'no' %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Postal&nbsp;invoices</TD>
+ <TD BGCOLOR="#ffffff">
+ <% ( grep { $_ eq 'POST' } @invoicing_list ) ? 'yes' : 'no' %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">FAX&nbsp;invoices</TD>
+ <TD BGCOLOR="#ffffff">
+ <% ( grep { $_ eq 'FAX' } @invoicing_list ) ? 'yes' : 'no' %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Email&nbsp;invoices</TD>
+ <TD BGCOLOR="#ffffff">
+ <% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || 'no' %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Invoice&nbsp;terms</TD>
+ <TD BGCOLOR="#ffffff">
+ <% $cust_main->invoice_terms || 'Default ('. ( $conf->config('invoice_default_terms') || 'Payable upon receipt' ). ')' %>
+ </TD>
+</TR>
+
+% if ( $conf->exists('voip-cust_cdr_spools') ) {
+ <TR>
+ <TD ALIGN="right">Spool&nbsp;CDRs</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->spool_cdr ? 'yes' : 'no' %></TD>
+ </TR>
+% }
+
+% if ( $conf->exists('voip-cust_cdr_squelch') ) {
+ <TR>
+ <TD ALIGN="right">Print&nbsp;CDRs</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->squelch_cdr ? 'no' : 'yes' %></TD>
+ </TR>
+% }
+
+</TABLE></TD></TR></TABLE>
+<%once>
+
+my $paystate_label = FS::Msgcat::_gettext('paystate');
+$paystate_label = 'Bank state' if $paystate_label =~/^paystate$/;
+
+</%once>
+<%init>
+
+my( $cust_main ) = @_;
+my @invoicing_list = $cust_main->invoicing_list;
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html
new file mode 100644
index 000000000..e88c02ea5
--- /dev/null
+++ b/httemplate/view/cust_main/contacts.html
@@ -0,0 +1,122 @@
+% my %which = (
+% '' => 'Billing',
+% 'ship_' => 'Service',
+% );
+% foreach my $which ( '', 'ship_' ) {
+% my $pre = $cust_main->get("${which}last") ? $which : '';
+
+<% $which{$which} %> address
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TR>
+ <TD ALIGN="right">Contact name</TD>
+ <TD COLSPAN=5 BGCOLOR="#ffffff">
+ <% $cust_main->get("${pre}last"). ', '. $cust_main->get("${pre}first") %>
+ </TD>
+% if ( $which eq '' && $conf->exists('show_ss') ) {
+ <TD ALIGN="right">SS#</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->masked('ss') || '&nbsp' %></TD>
+% }
+</TR>
+<TR>
+ <TD ALIGN="right">Company</TD>
+ <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Address</TD>
+ <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") %></TD>
+</TR>
+
+% if ( $cust_main->get("${pre}address2") ) {
+% my $address2_label =
+% ( $conf->exists('cust_main-require_address2')
+% && ! ( $pre xor $cust_main->has_ship_address )
+% )
+% ? 'Unit&nbsp;#'
+% : '&nbsp;';
+
+ <TR>
+ <TD ALIGN="right"><% $address2_label %></TD>
+ <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address2") %></TD>
+ </TR>
+
+% }
+
+<TR>
+ <TD ALIGN="right">City</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}city") %></TD>
+% if ( $cust_main->get("${pre}county") ) {
+ <TD ALIGN="right">County</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}county") %></TD>
+% }
+ <TD ALIGN="right">State</TD>
+ <TD BGCOLOR="#ffffff"><% state_label( $cust_main->get("${pre}state"), $cust_main->get("${pre}country") ) %></TD>
+ <TD ALIGN="right">Zip</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}zip") %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Country</TD>
+ <TD BGCOLOR="#ffffff"><% code2country( $cust_main->get("${pre}country") ) %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right"><% $daytime_label %></TD>
+ <TD COLSPAN=3 BGCOLOR="#ffffff">
+ <% include('/elements/phonenumber.html',
+ $cust_main->get("${pre}daytime"),
+ 'callable'=>1
+ )
+ %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right"><% $night_label %></TD>
+ <TD COLSPAN=3 BGCOLOR="#ffffff">
+ <% include('/elements/phonenumber.html',
+ $cust_main->get("${pre}night"),
+ 'callable'=>1
+ )
+ %>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Fax</TD>
+ <TD COLSPAN=3 BGCOLOR="#ffffff">
+ <% $cust_main->get("${pre}fax") || '&nbsp' %>
+ </TD>
+</TR>
+% if ( $which eq '' && $conf->exists('show_stateid') ) {
+ <TR>
+ <TD ALIGN="right"><% $stateid_label %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->masked('stateid') || '&nbsp' %></TD>
+ <TD ALIGN="right"><% $stateid_state_label %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->stateid_state || '&nbsp' %></TD>
+ </TR>
+% }
+</TABLE></TD></TR></TABLE>
+% if ( $which ne 'ship_' ) {
+<BR>
+% }
+% }
+
+<%once>
+
+my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
+ ? 'Day&nbsp;Phone'
+ : FS::Msgcat::_gettext('daytime');
+my $night_label = FS::Msgcat::_gettext('night') =~ /^(night)?$/
+ ? 'Night&nbsp;Phone'
+ : FS::Msgcat::_gettext('night');
+my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
+ ? 'Driver&rsquo;s&nbsp;License'
+ : FS::Msgcat::_gettext('stateid');
+my $stateid_state_label = FS::Msgcat::_gettext('stateid_state') =~ /^(stateid_state)?$/
+ ? 'Driver&rsquo;s&nbsp;License State'
+ : FS::Msgcat::_gettext('stateid_state');
+
+</%once>
+<%init>
+
+my( $cust_main ) = @_;
+my $conf = new FS::Conf;
+
+</%init>
+
diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html
new file mode 100644
index 000000000..060da87dd
--- /dev/null
+++ b/httemplate/view/cust_main/misc.html
@@ -0,0 +1,110 @@
+<% ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+
+<TR>
+ <TD ALIGN="right">Customer&nbsp;number</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->display_custnum %></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Status</TD>
+ <TD BGCOLOR="#ffffff"><FONT COLOR="#<% $cust_main->statuscolor %>"><B><% ucfirst($cust_main->status) %></B></FONT></TD>
+</TR>
+
+%my $agent;
+%if ( $num_agents == 1 ) {
+% my @agents = qsearchs( 'agent', {} );
+% $agent = $agents[0];
+%} else {
+% $agent = qsearchs('agent',{ 'agentnum' => $cust_main->agentnum } );
+ <TR>
+ <TD ALIGN="right">Agent</TD>
+ <TD BGCOLOR="#ffffff"><% $agent->agentnum %>: <% $agent->agent %></TD>
+ </TR>
+% }
+
+% if ( $cust_main->agent_custid
+% && ! $conf->exists('cust_main-default_agent_custid') ) {
+
+<TR>
+ <TD ALIGN="right">Agent customer ref#</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->agent_custid %></TD>
+</TR>
+%
+% }
+%
+% unless ( FS::part_referral->num_part_referral == 1 ) {
+% my $referral = qsearchs('part_referral', {
+% 'refnum' => $cust_main->refnum
+% } );
+%
+
+
+<TR>
+ <TD ALIGN="right">Advertising&nbsp;source</TD>
+ <TD BGCOLOR="#ffffff"><% $referral->refnum %>: <% $referral->referral%></TD>
+</TR>
+% }
+
+
+<TR>
+ <TD ALIGN="right">Referring&nbsp;Customer</TD>
+ <TD BGCOLOR="#ffffff">
+%
+% my $referring_cust_main = '';
+% if ( $cust_main->referral_custnum
+% && ( $referring_cust_main =
+% qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
+% )
+% ) {
+%
+
+
+<A HREF="<% popurl(1) %>cust_main.cgi?<% $cust_main->referral_custnum %>"><%$cust_main->referral_custnum %>:
+<%
+ ( $referring_cust_main->company
+ ? $referring_cust_main->company. ' ('.
+ $referring_cust_main->last. ', '. $referring_cust_main->first.
+ ')'
+ : $referring_cust_main->last. ', '. $referring_cust_main->first
+ )
+%></A>
+% }
+
+
+ </TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Order taker</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->otaker %></TD>
+</TR>
+
+ <TR>
+ <TD ALIGN="right">Signup Date</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->signupdate ? time2str($date_format, $cust_main->signupdate) : '' %></TD>
+ </TR>
+
+% if ( $conf->exists('cust_main-enable_birthdate') ) {
+% my $dt = DateTime->from_epoch(epoch => $cust_main->birthdate,
+% time_zone=>'floating',
+% );
+
+ <TR>
+ <TD ALIGN="right">Date of Birth</TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->birthdate ne '' ? $dt->strftime($date_format) : '' %></TD>
+ </TR>
+
+% }
+
+</TABLE></TD></TR></TABLE>
+<%init>
+
+my( $cust_main ) = @_;
+my $conf = new FS::Conf;
+my $date_format = ($conf->config('date_format') || "%m/%d/%Y");
+
+my $sth = dbh->prepare('SELECT COUNT(*) FROM agent') or die dbh->errstr;
+$sth->execute or die $sth->errstr;
+my $num_agents = $sth->fetchrow_arrayref->[0];
+
+</%init>
diff --git a/httemplate/view/cust_main/notes.html b/httemplate/view/cust_main/notes.html
new file mode 100755
index 000000000..833c92e67
--- /dev/null
+++ b/httemplate/view/cust_main/notes.html
@@ -0,0 +1,88 @@
+% if ( scalar(@notes) ) {
+
+ <% include('/elements/init_overlib.html') %>
+
+ <% include("/elements/table-grid.html") %>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH>
+% if ( $conf->exists('cust_main_note-display_times') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">Time</TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc">Person</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Note</TH>
+ </TR>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+%
+% foreach my $note (@notes) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $pop = popurl(3);
+% my $notenum = $note->notenum;
+% my $onclick = include( '/elements/popup_link_onclick.html',
+% 'action' => popurl(2).
+% 'edit/cust_main_note.cgi'.
+% "?custnum=$custnum".
+% ";notenum=$notenum",
+% 'actionlabel' => 'Edit customer note',
+% 'width' => 616,
+% 'height' => 408,
+% 'frame' => 'top',
+% );
+% my $clickjs = qq!onclick="$onclick"!;
+%
+% my $edit = '';
+% if ($curuser->access_right('Edit customer note') ) {
+% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(edit)</A>!;
+% }
+
+ <TR>
+ <% note_datestr($note,$conf,$bgcolor) %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<% $note->otaker%>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ &nbsp;<%$note->comments%><% $edit %>
+ </TD>
+ </TR>
+
+% } #end display notes
+
+</TABLE>
+
+% }
+<%init>
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my(%opt) = @_;
+
+my $custnum = $opt{'custnum'};
+
+my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
+die "Custimer not found!" unless $cust_main;
+
+my (@notes) = $cust_main->notes();
+
+#subroutines
+
+sub note_datestr {
+ my($note, $conf, $bgcolor) = @_ or return '';
+ my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
+ my $format = "$td%b&nbsp;%o,&nbsp;%Y</TD>";
+ $format .= "$td%l:%M%P</TD>"
+ if $conf->exists('cust_main_note-display_times');
+ ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
+ $strip;
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
new file mode 100755
index 000000000..2c258881a
--- /dev/null
+++ b/httemplate/view/cust_main/packages.html
@@ -0,0 +1,241 @@
+<A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A><BR>
+
+% if ( $curuser->access_right('One-time charge') ) {
+
+<SCRIPT TYPE="text/javascript">
+
+function taxproductmagic(which) {
+ var str = '';
+ var elements = which.form.elements;
+ for (var i = 0; i<elements.length; i++) {
+ if (elements[i].name == 'taxproductnum'){
+ document.getElementById('taxproductnum').value = elements[i].value;
+ continue;
+ }
+ if (elements[i].name == 'taxproductnum_description'){
+ continue;
+ }
+ if (str.length){str += ';';}
+ str += elements[i].name + '=' + escape(elements[i].value);
+ }
+ document.getElementById('charge_storage').value = str;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/browse/part_pkg_taxproduct.cgi?_type=select&id=taxproductnum&onclick=taxproductquickchargemagic&taxproductnum='+document.getElementById('taxproductnum').value, 1000, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
+}
+
+function taxproductquickchargemagic() {
+ var str = document.getElementById('charge_storage').value;
+ if (str.length){str += ';';}
+ str += 'magic=taxproductnum;taxproductnum=';
+ str += escape(document.getElementById('taxproductnum').value);
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
+
+}
+
+function taxoverridemagic(which) {
+ var str = '';
+ var elements = which.ownerDocument.QuickChargeForm.elements;
+ for (var i = 0; i<elements.length; i++) {
+ if (elements[i].name == 'tax_override'){
+ document.getElementById('tax_override').value = elements[i].value;
+ continue;
+ }
+ if (str.length){str += ';';}
+ str += elements[i].name + '=' + escape(elements[i].value);
+ }
+ document.getElementById('charge_storage').value = str;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/part_pkg_taxoverride.html?element_name=tax_override;onclick=taxoverridequickchargemagic;selected='+document.getElementById('tax_override').value, 1100, 600, 'tax_product_popup'), CAPTION, 'Edit product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
+}
+
+function taxoverridequickchargemagic() {
+ var str = document.getElementById('charge_storage').value;
+ if (str.length){str += ';';}
+ str += 'magic=taxoverride;tax_override=';
+ str += document.getElementById('tax_override').value;
+ cClick();
+ overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
+
+}
+
+</SCRIPT>
+<FORM NAME='quickcharge'>
+ <INPUT NAME="taxproductnum" ID="taxproductnum" TYPE="hidden">
+ <INPUT NAME="tax_override" ID="tax_override" TYPE="hidden">
+ <INPUT NAME="charge_storage" ID="charge_storage" TYPE="hidden">
+ <INPUT NAME="taxproductnum_description" ID="taxproductnum_description" TYPE="hidden">
+</FORM>
+% }
+
+% my $s = 0;
+% if ( $curuser->access_right('Order customer package') ) {
+ <% $s++ ? ' | ' : '' %>
+ <% order_pkg_link($cust_main) %>
+% }
+
+% if ( $curuser->access_right('One-time charge')
+% && $conf->config('payby-default') ne 'HIDE'
+% ) {
+%
+ <% $s++ ? ' | ' : '' %>
+ <% include('/elements/popup_link.html',
+ {
+ 'action' => $p. 'edit/quick-charge.html?custnum='. $cust_main->custnum,
+ 'label' => 'One-time charge',
+ 'actionlabel' => 'One-time charge',
+ 'color' => '#333399',
+ 'width' => 763,
+ 'height' => 408,
+ })
+ %>
+% }
+
+% if ( $curuser->access_right('Bulk change customer packages') ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>">Bulk order and cancel packages</A> (preserves services)
+% }
+
+
+<BR><BR>
+% if ( @$packages ) {
+
+Current packages
+% }
+% if ( $cust_main->num_cancelled_pkgs ) {
+% if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
+% || ( $conf->exists('hidecancelledpackages')
+% && ! $cgi->param('showcancelledpackages')
+% )
+% )
+% {
+% $cgi->param('showcancelledpackages', 1);
+%
+
+ ( <a href="<% $cgi->self_url %>">show
+% } else {
+% $cgi->param('showcancelledpackages', 0);
+%
+
+ ( <a href="<% $cgi->self_url %>">hide
+% }
+
+ cancelled packages</a> )
+% }
+% if ( @$packages ) {
+
+<% include('/elements/table-grid.html') %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Package</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
+% if ( $show_location ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">Location</TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc">Services</TH>
+</TR>
+
+% foreach my $cust_pkg (@$packages) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
+% my %iopt = (
+% 'bgcolor' => $bgcolor,
+% 'cust_pkg' => $cust_pkg,
+% 'part_pkg' => $cust_pkg->part_pkg,
+%
+% #for services.html and status.html
+% 'cust_pkg-display_times' => $conf->exists('cust_pkg-display_times'),
+%
+% #for location.html
+% 'countrydefault' => $countrydefault,
+% 'statedefault' => ( scalar($conf->config('statedefault'))
+% || ($countrydefault eq 'US' ? 'CA' : '') ),
+%
+% #for services.html
+% 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'),
+% 'legacy_link' => $conf->exists('legacy_link'),
+%
+% );
+
+ <!--pkgnum: <% $cust_pkg->pkgnum %>-->
+ <TR>
+ <% include('packages/package.html', %iopt) %>
+ <% include('packages/status.html', %iopt) %>
+% if ( $show_location ) {
+ <% include('packages/location.html', %iopt) %>
+% }
+ <% include('packages/services.html', %iopt) %>
+ </TR>
+
+% }
+
+</TABLE>
+
+% } else {
+<BR>
+% }
+
+% if ( $cgi->param('fragment') =~ /^cust_pkg(\d+)$/ ) {
+ <SCRIPT>
+ // IE-specific hack. other browsers listen to #fragments
+ // is this even working? or is the #target redirection just working cause
+ // we set the URL params differently?
+ var el = document.getElementById( 'cust_pkg<% $1 %>' );
+ if ( el ) el.scrollIntoView(true);
+ </SCRIPT>
+% }
+<%init>
+
+my( $cust_main ) = @_;
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $packages = get_packages($cust_main, $conf);
+
+my $show_location = $conf->exists('cust_pkg-always_show_location')
+ || ( grep $_->locationnum, @$packages ); # ? '1' : '0';
+
+#subroutines
+
+sub get_packages {
+ my $cust_main = shift or return undef;
+ my $conf = shift;
+
+ my @packages = ();
+ my $method;
+ if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
+ || ( $conf->exists('hidecancelledpackages')
+ && ! $cgi->param('showcancelledpackages') )
+ )
+ {
+ $method = 'ncancelled_pkgs';
+ } else {
+ $method = 'all_pkgs';
+ }
+
+ [ $cust_main->$method() ];
+}
+
+sub order_pkg_link {
+ include( '/elements/popup_link-cust_main.html',
+ 'action' => $p. 'misc/order_pkg.html',
+ 'label' => 'Order&nbsp;new&nbsp;package',
+ 'actionlabel' => 'Order new package',
+ 'color' => '#333399',
+ 'cust_main' => shift,
+ 'closetext' => 'Close',
+ 'width' => 763,
+ )
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html
new file mode 100644
index 000000000..59efce14a
--- /dev/null
+++ b/httemplate/view/cust_main/packages/location.html
@@ -0,0 +1,60 @@
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+
+% unless ( $cust_pkg->locationnum ) {
+ <I><FONT SIZE=-1>(default service address)</FONT><BR>
+% }
+
+ <% $loc->get($prefix.'address1') |h %><BR>
+
+% if ( $loc->get($prefix.'address2') !~ /^\s*$/ ) {
+ <% $loc->get($prefix.'address2') |h %><BR>
+% }
+
+ <% $loc->get($prefix.'city') |h %><% $loc->get($prefix.'county') ? ' ('.$loc->get($prefix.'county').' county)' : '' |h %>,
+ <% $loc->get($prefix.'state') |h %> &nbsp; <% $loc->get($prefix.'zip') |h %><BR>
+
+% if ( $loc->get($prefix.'country') ne $countrydefault ) {
+ <% code2country( $loc->get($prefix.'country') ) %>
+% }
+
+ </I>
+
+% if ( ! $cust_pkg->get('cancel')
+% && $FS::CurrentUser::CurrentUser->access_right('Change customer package')
+% )
+% {
+ <FONT SIZE=-1>
+ (&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
+ </FONT>
+% }
+
+</TD>
+<%init>
+
+my %opt = @_;
+
+my $bgcolor = $opt{'bgcolor'};
+my $cust_pkg = $opt{'cust_pkg'};
+my $part_pkg = $opt{'part_pkg'};
+my $countrydefault = $opt{'countrydefault'} || 'US';
+my $statedefault = $opt{'statedefault'}
+ || ($countrydefault eq 'US' ? 'CA' : '');
+
+my $loc = $cust_pkg->cust_location_or_main;
+my $prefix =
+ ( $loc->table eq 'cust_main' && length($loc->ship_last) ) ? 'ship_' : ''; #doh
+
+sub pkg_change_location_link {
+ my $cust_pkg = shift;
+ my $pkgpart = $cust_pkg->pkgpart;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. "misc/change_pkg.cgi?locationnum=-1;pkgpart=$pkgpart;".
+ "address1=;address2=;city=;county=;state=$statedefault;".
+ "zip=;country=$countrydefault",
+ 'label' => 'Change&nbsp;location',
+ 'actionlabel' => 'Change',
+ 'cust_pkg' => $cust_pkg,
+ );
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/package.html b/httemplate/view/cust_main/packages/package.html
new file mode 100644
index 000000000..b07e1af94
--- /dev/null
+++ b/httemplate/view/cust_main/packages/package.html
@@ -0,0 +1,215 @@
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
+ <TR>
+ <TD COLSPAN=2>
+ <A NAME="cust_pkg<% $cust_pkg->pkgnum %>"
+ ID ="cust_pkg<% $cust_pkg->pkgnum %>"
+ ><% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B></A>
+ -
+ <% $part_pkg->comment |h %>
+ </TD>
+ </TR>
+
+% if ( $cust_pkg->quantity > 1 ) {
+ <TR>
+ <TD COLSPAN=2>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity:
+ <B><% $cust_pkg->quantity %></B>
+ </TD>
+ </TR>
+% }
+
+ <TR>
+ <TD COLSPAN=2>
+ <FONT SIZE=-1>
+
+% unless ( $cust_pkg->get('cancel') ) {
+%
+% my $br = 0;
+% if ( $curuser->access_right('Change customer package') ) {
+% $br=1;
+ (&nbsp;<%pkg_change_link($cust_pkg)%>&nbsp;)
+% }
+%
+% if ( $curuser->access_right('Edit customer package dates') ) {
+% $br=1;
+ (&nbsp;<%pkg_dates_link($cust_pkg)%>&nbsp;)
+% }
+%
+% if ( $curuser->access_right('Customize customer package') ) {
+% $br=1;
+ (&nbsp;<%pkg_customize_link($cust_pkg,$cust_pkg->custnum)%>&nbsp;)
+% }
+%
+ <% $br ? '<BR>' : '' %>
+% }
+
+% if ( $cust_pkg->num_cust_event
+% && ( $curuser->access_right('Billing event reports')
+% || $curuser->access_right('View customer billing events')
+% )
+% ) {
+ (&nbsp;<%pkg_event_link($cust_pkg)%>&nbsp;)
+% }
+
+ </FONT>
+ </TD>
+ </TR>
+
+% my $editi = $curuser->access_right('Edit customer package invoice details');
+% my $editc = $curuser->access_right('Edit customer package comments');
+%
+% if ( $cust_pkg->cust_pkg_detail('I')
+% || $cust_pkg->cust_pkg_detail('C')
+% || $editi
+% || $editc ) {
+%
+% my $editlink = $p. 'edit/cust_pkg_detail?pkgnum='. $cust_pkg->pkgnum.
+% ';detailtype=';
+
+ <TR>
+
+% if ( $cust_pkg->cust_pkg_detail('I') ) {
+ <TD VALIGN="top">
+ <% include('/elements/table-grid.html') %>
+ <TR>
+ <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
+ <FONT SIZE="-1">
+ Invoice details
+% if ( $editi && ! $cust_pkg->get('cancel') ) {
+ (<% include('/elements/popup_link.html', {
+ 'action' => $editlink. 'I',
+ 'label' => 'edit',
+ 'actionlabel' => 'Edit invoice details',
+ 'color' => '#333399',
+ 'width' => 763,
+ })
+ %>)
+% }
+ </FONT>
+ </TH>
+ </TR>
+% foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('I') ) {
+ <TR>
+ <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
+ </TR>
+% }
+ </TABLE>
+ </TD>
+% } else {
+ <TD>
+% if ( $editi && ! $cust_pkg->get('cancel') ) {
+ <FONT SIZE="-1">
+ (&nbsp;<% include('/elements/popup_link.html', {
+ 'action' => $editlink. 'I',
+ 'label' => 'Add&nbsp;invoice&nbsp;details',
+ 'actionlabel' => 'Add invoice details',
+ 'color' => '#333399',
+ 'width' => 763,
+ })
+ %>&nbsp;)
+ </FONT>
+% }
+ </TD>
+% }
+
+% if ( $cust_pkg->cust_pkg_detail('C') ) {
+ <TD VALIGN="top">
+ <% include('/elements/table-grid.html') %>
+ <TR>
+ <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
+ <FONT SIZE="-1">
+ Comments
+% if ( $editc ) {
+ (<% include('/elements/popup_link.html', {
+ 'action' => $editlink. 'C',
+ 'label' => 'edit',
+ 'actionlabel' => 'Edit comments',
+ 'color' => '#333399',
+ 'width' => 763,
+ })
+ %>)
+% }
+ </FONT>
+ </TH>
+ </TR>
+% foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('C') ) {
+ <TR>
+ <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
+ </TR>
+% }
+ </TABLE>
+ </TD>
+% } else {
+ <TD>
+% if ( $editc ) {
+ <FONT SIZE="-1">
+ (&nbsp;<% include('/elements/popup_link.html', {
+ 'action' => $editlink. 'C',
+ 'label' => 'Add&nbsp;comments',
+ 'actionlabel' => 'Add comments',
+ 'color' => '#333399',
+ 'width' => 763,
+ })
+ %>&nbsp;)
+ </FONT>
+% }
+ </TD>
+% }
+
+ </TR>
+% }
+
+ </TABLE>
+
+</TD>
+
+<%init>
+
+my %opt = @_;
+
+my $bgcolor = $opt{'bgcolor'};
+my $cust_pkg = $opt{'cust_pkg'};
+my $part_pkg = $opt{'part_pkg'};
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+#subroutines
+
+#false laziness w/status.html
+sub pkg_link {
+ my($action, $label, $cust_pkg) = @_;
+ return '' unless $cust_pkg;
+ qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
+}
+
+sub pkg_change_link {
+ my $cust_pkg = shift;
+ my $locationnum = $cust_pkg->locationnum;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. "misc/change_pkg.cgi?locationnum=$locationnum",
+ 'label' => 'Change&nbsp;package',
+ 'actionlabel' => 'Change',
+ 'cust_pkg' => $cust_pkg,
+ );
+}
+
+sub pkg_dates_link { pkg_link('edit/REAL_cust_pkg', 'Edit&nbsp;dates', @_ ); }
+
+sub pkg_customize_link {
+ my $cust_pkg = shift or return '';
+ my $custnum = $cust_pkg->custnum;
+ qq!<A HREF="${p}edit/part_pkg.cgi?!.
+ "clone=". $cust_pkg->part_pkg->pkgpart. ';'.
+ "pkgnum=". $cust_pkg->pkgnum.
+ qq!">Customize</A>!;
+}
+
+sub pkg_event_link {
+ my($cust_pkg) = @_;
+ qq!<a href="${p}search/cust_event.html?pkgnum=!. $cust_pkg->pkgnum. qq!">!.
+ 'View package events'.
+ '</a>';
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html
new file mode 100644
index 000000000..1e473736b
--- /dev/null
+++ b/httemplate/view/cust_main/packages/services.html
@@ -0,0 +1,119 @@
+% ###
+% # Services
+% ###
+
+ <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
+
+% #foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) {
+% foreach my $part_svc ( $cust_pkg->part_svc ) {
+
+% #foreach my $service (@{$svcpart->{services}}) {
+% foreach my $cust_svc ( @{ $part_svc->cust_pkg_svc } ) {
+
+ <TR>
+ <TD ALIGN="right" VALIGN="top"><% FS::UI::Web::svc_link($m, $part_svc, $cust_svc) %></TD>
+ <TD STYLE="padding-bottom:0px"><B><% FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc) %></B></TD>
+ <TD><% FS::UI::Web::svc_export_links($m, $part_svc, $cust_svc) %></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right" COLSPAN="3" VALIGN="top" STYLE="padding-bottom:1px;padding-top:0px"><FONT SIZE="-2" COLOR="#FFD000">
+
+ <% $cust_svc->overlimit ? "Overlimit: ". time2str('%b %o %Y' . ($opt{'cust_pkg-display_times'} ? ' %l:%M %P' : ''), $cust_svc->overlimit) : '' %>
+ </FONT></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
+
+% if ( $curuser->access_right('Recharge customer service')
+% && $part_svc->svcdb eq 'svc_acct'
+% && ( $cust_svc->svc_x->seconds ne ''
+% || $cust_svc->svc_x->upbytes ne ''
+% || $cust_svc->svc_x->downbytes ne ''
+% || $cust_svc->svc_x->totalbytes ne ''
+% )
+% ) {
+ (&nbsp;<%svc_recharge_link($cust_svc)%>&nbsp;)
+% }
+ </FONT></TD>
+
+ <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
+
+% if ( $curuser->access_right('Unprovision customer service') ) {
+ (&nbsp;<%svc_unprovision_link($cust_svc)%>&nbsp;)
+% }
+ </FONT></TD>
+ </TR>
+% }
+
+% if ( ! $cust_pkg->get('cancel')
+% && $curuser->access_right('Provision customer service')
+% && $part_svc->num_avail
+% ) {
+
+ <TR>
+ <TD COLSPAN=3 ALIGN="center" STYLE="padding-bottom:4px;padding-top:0px">
+ <B><% svc_provision_link($cust_pkg, $part_svc, \%opt, $curuser) %></B>
+ </TD>
+ </TR>
+
+% }
+
+% }
+
+ </TABLE>
+ </TD>
+
+<%init>
+
+my %opt = @_;
+
+my $bgcolor = $opt{'bgcolor'};
+my $cust_pkg = $opt{'cust_pkg'};
+my $part_pkg = $opt{'part_pkg'};
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+sub svc_provision_link {
+ my ($cust_pkg, $part_svc, $opt, $curuser) = @_;
+ ( my $svc_nbsp = $part_svc->svc ) =~ s/\s+/&nbsp;/g;
+ my $num_avail = $part_svc->num_avail;
+ my $pkgnum_svcpart = "pkgnum=". $cust_pkg->pkgnum. ';'.
+ "svcpart=". $part_svc->svcpart;
+ my $url;
+ if ( $part_svc->svcdb eq 'svc_external' #could be generalized
+ && $opt->{'svc_external-skip_manual'}
+ ) {
+ $url = "${p}edit/process/". $part_svc->svcdb. ".cgi?$pkgnum_svcpart";
+ } else {
+ $url = svc_url(
+ 'm' => $m,
+ 'action' => 'edit',
+ 'part_svc' => $part_svc,
+ 'query' => $pkgnum_svcpart,
+ );
+ #$url = "${p}edit/$svcpart->{svcdb}.cgi?$pkgnum_svcpart";
+ }
+
+ my $link = qq!<A CLASS="provision" HREF="$url">!.
+ "Provision&nbsp;$svc_nbsp&nbsp;($num_avail)</A>";
+ if ( $opt->{'legacy_link'}
+ && $curuser->access_right('View/link unlinked services')
+ )
+ {
+ $link .= '<BR>'.
+ qq!<A CLASS="provision" HREF="${p}misc/link.cgi?!.
+ qq!$pkgnum_svcpart">!.
+ "Link&nbsp;to&nbsp;legacy&nbsp;$svc_nbsp&nbsp;($num_avail)</A>";
+ }
+ $link;
+}
+
+sub svc_unprovision_link {
+ my $cust_svc = shift or return '';
+ qq!<A HREF="javascript:areyousure('${p}misc/unprovision.cgi?!. $cust_svc->svcnum.
+ qq!', 'Permanently unprovision and delete this service?')">Unprovision</A>!;
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
new file mode 100644
index 000000000..106137ba9
--- /dev/null
+++ b/httemplate/view/cust_main/packages/status.html
@@ -0,0 +1,379 @@
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+ <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
+
+%#this should use cust_pkg->status and cust_pkg->statuscolor eventually
+
+% if ( $cust_pkg->get('cancel') ) { #status: cancelled
+% my $cpr = $cust_pkg->last_cust_pkg_reason('cancel');
+
+ <% pkg_status_row($cust_pkg, 'Cancelled', 'cancel', 'color'=>'FF0000', %opt ) %>
+
+ <% pkg_status_row_colspan(
+ ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
+ 'align' => 'right', 'color' => 'ff0000', 'size' => '-2',
+ )
+ %>
+
+% unless ( $cust_pkg->get('setup') ) {
+
+ <% pkg_status_row_colspan('Never billed') %>
+
+% } else {
+
+ <% pkg_status_row( $cust_pkg, 'Setup', 'setup', %opt ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
+ <% pkg_status_row_if( $cust_pkg, 'Suspended', 'susp', %opt, curuser=>$curuser ) %>
+
+% }
+%
+% } else {
+%
+% if ( $cust_pkg->get('susp') ) { #status: suspended
+% my $cpr = $cust_pkg->last_cust_pkg_reason('susp');
+
+ <% pkg_status_row( $cust_pkg, 'Suspended', 'susp', 'color'=>'FF9900', %opt ) %>
+
+ <% pkg_status_row_colspan(
+ ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
+ 'align' => 'right', 'color' => 'FF9900', 'size' => '-2',
+ )
+ %>
+
+% unless ( $cust_pkg->get('setup') ) {
+ <% pkg_status_row_colspan('Never billed') %>
+% } else {
+ <% pkg_status_row($cust_pkg, 'Setup', 'setup', %opt ) %>
+% }
+
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
+% # pkg_status_row($cust_pkg, 'Next bill', 'bill', %opt)
+ <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
+
+ <TR>
+ <TD COLSPAN=<%$colspan%>>
+ <FONT SIZE=-1>
+% if ( $curuser->access_right('Unsuspend customer package') ) {
+ (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Cancel customer package immediately') ) {
+ (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+% }
+ </FONT>
+ </TD>
+ </TR>
+
+% } else { #status: active
+%
+% unless ( $cust_pkg->get('setup') ) { #not setup
+%
+% unless ( $part_pkg->freq ) {
+
+ <% pkg_status_row_colspan('Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)') %>
+
+ <TR>
+ <TD COLSPAN=<%$colspan%>>
+ <FONT SIZE=-1>
+% if ( $curuser->access_right('Cancel customer package immediately') ) {
+ (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+% }
+ </FONT>
+ </TD>
+ </TR>
+
+% } else {
+
+ <% pkg_status_row_colspan("Not&nbsp;yet&nbsp;billed&nbsp;($billed_or_prepaid&nbsp;". myfreq($part_pkg). ')' ) %>
+
+% }
+%
+% } else { #setup
+%
+% unless ( $part_pkg->freq ) {
+
+ <% pkg_status_row_colspan('One-time&nbsp;charge') %>
+
+ <% pkg_status_row($cust_pkg, 'Billed', 'setup', %opt) %>
+
+% } else {
+%
+% if (scalar($cust_pkg->overlimit)) {
+
+ <% pkg_status_row_colspan(
+ 'Overlimit',
+ $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
+ 'color' => 'FFD000',
+ )
+ %>
+
+% } else {
+ <% pkg_status_row_colspan(
+ 'Active',
+ $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
+ 'color' => '00CC00',
+ )
+ %>
+% }
+
+ <% pkg_status_row($cust_pkg, 'Setup', 'setup', %opt) %>
+
+% }
+%
+% }
+%
+% if ( $conf->exists('cust_pkg-show_autosuspend') ) {
+% my $autosuspend = pkg_autosuspend_time( $cust_pkg );
+% $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
+% }
+
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
+ <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
+ <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
+ <% pkg_status_row_if($cust_pkg, 'Will automatically suspend by', 'autosuspend', %opt) %>
+ <% pkg_status_row_if( $cust_pkg, 'Will suspend on', 'adjourn', %opt, curuser=>$curuser ) %>
+ <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
+
+% if ( $part_pkg->freq ) {
+
+ <TR>
+ <TD COLSPAN=<%$colspan%>>
+ <FONT SIZE=-1>
+% if ( $curuser->access_right('Suspend customer package') ) {
+ (&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Suspend customer package later') ) {
+ (&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Delay suspension events') ) {
+ (&nbsp;<% pkg_delay_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Cancel customer package immediately') ) {
+ (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Cancel customer package later') ) {
+ (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
+% }
+
+ <FONT>
+ </TD>
+ </TR>
+% }
+%
+% }
+% }
+
+ </TABLE>
+</TD>
+
+<%init>
+
+my %opt = @_;
+
+my $conf = new FS::Conf;
+
+my $bgcolor = $opt{'bgcolor'};
+my $cust_pkg = $opt{'cust_pkg'};
+my $part_pkg = $opt{'part_pkg'};
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $colspan = $opt{'cust_pkg-display_times'} ? 8 : 4;
+my $width = $opt{'cust_pkg-display_times'} ? '38%' : '56%';
+
+#false laziness w/edit/REAL_cust_pkg.cgi
+my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
+unless ( $part_pkg->is_prepaid ) {
+ $billed_or_prepaid = 'billed';
+ $last_bill_or_renewed = 'Last&nbsp;bill';
+ $next_bill_or_prepaid_until = 'Next&nbsp;bill';
+} else {
+ $billed_or_prepaid = 'prepaid';
+ $last_bill_or_renewed = 'Renewed';
+ $next_bill_or_prepaid_until = 'Prepaid&nbsp;until';
+}
+
+#subroutines
+
+sub myfreq {
+ my $part_pkg = shift;
+ my $freq = $part_pkg->freq_pretty;
+ $freq =~ s/ /&nbsp;/g;
+ $freq;
+}
+
+#false laziness w/package.html
+sub pkg_link {
+ my($action, $label, $cust_pkg) = @_;
+ return '' unless $cust_pkg;
+ qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
+}
+
+sub pkg_status_row {
+ my( $cust_pkg, $title, $field, %opt ) = @_;
+
+ my $color = $opt{'color'};
+
+ my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">);
+ $html .= qq(<FONT COLOR="#$color"><B>) if length($color);
+ $html .= qq($title&nbsp;);
+ $html .= qq(</B></FONT>) if length($color);
+ $html .= qq(</TD>);
+ $html .= pkg_datestr($cust_pkg, $field, %opt).'</TR>';
+
+ $html;
+}
+
+sub pkg_status_row_if {
+ my( $cust_pkg, $title, $field, %opt ) = @_;
+
+ $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unadjourn_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
+ if ( $field eq 'adjourn' &&
+ $opt{curuser}->access_right('Suspend customer package later')
+ );
+
+ $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
+ if ( $field eq 'expire' &&
+ $opt{curuser}->access_right('Cancel customer package later')
+ );
+
+ $cust_pkg->get($field) ? pkg_status_row($cust_pkg, $title, $field, %opt) : '';
+}
+
+sub pkg_status_row_changed {
+ my( $cust_pkg, %opt ) = @_;
+ return '' unless $cust_pkg->change_date;
+ my $html = pkg_status_row( $cust_pkg, 'Package&nbsp;changed', 'change_date', %opt );
+ my $old = $cust_pkg->old_cust_pkg;
+ if ( $old ) {
+ my $part_pkg = $old->part_pkg;
+ my $label = 'Changed from '. $cust_pkg->change_pkgnum. ': '.
+ $part_pkg->pkg. ' - '. $part_pkg->comment;
+ $html .= pkg_status_row_colspan( $label, '', size=>'-1', align=>'right' );
+ }
+ $html;
+}
+
+sub pkg_status_row_colspan {
+ my($title, $addl, %opt) = @_;
+
+ my $align = $opt{'align'} ? 'ALIGN="'. $opt{'align'}.'"' : '';
+ my $color = $opt{'color'} ? 'COLOR="#'.$opt{'color'}.'"' : '';
+ my $size = $opt{'size'} ? 'SIZE="'. $opt{'size'}. '"' : '';
+
+ my $html = qq(<TR><TD COLSPAN=$colspan $align>);
+ $html .= qq(<FONT $color $size>) if length($color) || $size;
+ $html .= qq(<B>) if $color && !$size;
+ $html .= $title;
+ $html .= qq(</B>) if $color && !$size;
+ $html .= qq(</FONT>) if length($color) || $size;
+ $html .= ",&nbsp;$addl" if length($addl);
+ $html .= qq(</TD></TR>);
+
+ $html;
+
+}
+
+sub pkg_datestr {
+ my($cust_pkg, $field, %opt) = @_ or return '';
+ return '&nbsp;' unless $cust_pkg->get($field);
+ my $format = '<TD align="left"><B>%b</B></TD>'.
+ '<TD align="right"><B>&nbsp;%o,</B></TD>'.
+ '<TD align="right"><B>&nbsp;%Y</B></TD>';
+ #$format .= '&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
+ $format .= '<TD ALIGN="right"><B>&nbsp;%l</TD>'.
+ '<TD ALIGN="center"><B>:</B></TD>'.
+ '<TD ALIGN="left"><B>%M</B></TD>'.
+ '<TD ALIGN="left"><B>&nbsp;%P</B></TD>'
+ if $opt{'cust_pkg-display_times'};
+ my $strip = time2str($format, $cust_pkg->get($field) );
+ $strip =~ s/ (\d)/$1/g;
+ $strip;
+}
+
+sub pkg_suspend_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'misc/cancel_pkg.html?method=suspend',
+ 'label' => 'Suspend&nbsp;now',
+ 'actionlabel' => 'Suspend',
+ 'color' => '#FF9900',
+ 'cust_pkg' => shift,
+ )
+}
+
+sub pkg_adjourn_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'misc/cancel_pkg.html?method=adjourn',
+ 'label' => 'Suspend&nbsp;later',
+ 'actionlabel' => 'Adjourn',
+ 'color' => '#CC6600',
+ 'cust_pkg' => shift,
+ )
+}
+
+sub pkg_delay_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'misc/delay_susp_pkg.html',
+ 'label' => 'Delay&nbsp;suspend',
+ 'actionlabel' => 'Delay suspend for',
+ 'cust_pkg' => shift,
+ )
+}
+
+sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg', 'Unsuspend', @_ ); }
+sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', 'Abort', @_ ); }
+sub pkg_unexpire_link { pkg_link('misc/unexpire_pkg', 'Abort', @_ ); }
+
+sub pkg_cancel_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'misc/cancel_pkg.html?method=cancel',
+ 'label' => 'Cancel&nbsp;now',
+ 'actionlabel' => 'Cancel',
+ 'color' => '#ff0000',
+ 'cust_pkg' => shift,
+ )
+}
+
+sub pkg_expire_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'misc/cancel_pkg.html?method=expire',
+ 'label' => 'Cancel&nbsp;later',
+ 'actionlabel' => 'Expire', #"Cancel package $num later"
+ 'color' => '#CC0000',
+ 'cust_pkg' => shift,
+ )
+}
+
+sub svc_recharge_link {
+ include( '/elements/popup_link-cust_svc.html',
+ 'action' => $p. 'misc/recharge_svc.html',
+ 'label' => 'Recharge',
+ 'actionlabel' => 'Recharge',
+ 'color' => '#333399',
+ 'cust_svc' => shift,
+ )
+}
+
+sub pkg_autosuspend_time {
+ my $cust_pkg = shift or return '';
+ my $days = 7;
+ my $time = time;
+ my $pending_suspend = 0;
+ #this seems to be extremely inefficient... and is slowing down all customer
+ #views
+ while ( $days > 0 &&
+ scalar(
+ grep { $_->part_event->action eq 'suspend' }
+ @{$cust_pkg->cust_main->due_cust_event( time => $time + 86400*$days,
+ testonly => 1,
+ ) }
+ )
+ )
+ {
+ $pending_suspend = 1;
+ $days--;
+ }
+
+ $pending_suspend ? time + ($days + 1) * 86400 : '';
+
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
new file mode 100644
index 000000000..335ce2485
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history.html
@@ -0,0 +1,413 @@
+<BR><BR><A NAME="history"><FONT SIZE="+2">Payment History</FONT></A><BR>
+
+%# payment links
+
+% my $s = 0;
+% if ( $payby{'BILL'} && $curuser->access_right('Post payment') ) {
+ <% $s++ ? ' | ' : '' %>
+ <% include('/elements/popup_link-cust_main.html',
+ 'label' => 'Enter check payment',
+ 'action' => "${p}edit/cust_pay.cgi?popup=1;payby=BILL",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => 'Enter check payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ )
+ %>
+% }
+
+% if ( $payby{'CASH'} && $curuser->access_right('Post payment') ) {
+ <% $s++ ? ' | ' : '' %>
+ <% include('/elements/popup_link-cust_main.html',
+ 'label' => 'Enter cash payment',
+ 'action' => "${p}edit/cust_pay.cgi?popup=1;payby=CASH",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => 'Enter cash payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ )
+ %>
+% }
+
+% if ( $payby{'WEST'} && $curuser->access_right('Post payment') ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;custnum=<% $custnum %>">Enter Western Union payment</A>
+% }
+
+% if ( ( $payby{'CARD'} || $payby{'DCRD'} )
+% && $curuser->access_right('Process payment')
+% && ! $cust_main->is_encrypted($cust_main->payinfo)
+% ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>misc/payment.cgi?payby=CARD;custnum=<% $custnum %>">Process credit card payment</A>
+% }
+
+% if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
+% && $curuser->access_right('Process payment')
+% && ! $cust_main->is_encrypted($cust_main->payinfo)
+% ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>misc/payment.cgi?payby=CHEK;custnum=<% $custnum %>">Process electronic check (ACH) payment</A>
+% }
+
+% if ( $payby{'MCRD'} && $curuser->access_right('Post payment') ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<% $custnum %>">Post manual (offline/POS) credit card payment</A>
+% }
+
+<BR>
+
+%# credit link
+
+% if ( $curuser->access_right('Post credit') ) {
+ <% include('/elements/popup_link-cust_main.html',
+ 'label' => 'Enter credit',
+ 'action' => "${p}edit/cust_credit.cgi",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => 'Enter credit',
+ 'width' => 392,
+ #default# 'height' => 336,
+ )
+ %>
+ <BR>
+% }
+
+%# refund links
+
+% $s = 0;
+% if ( $payby{'BILL'} && $curuser->access_right('Post refund') ) {
+ <% $s++ ? ' | ' : '' %>
+ <% include('/elements/popup_link-cust_main.html',
+ 'label' => 'Enter check refund',
+ 'action' => "${p}edit/cust_refund.cgi?popup=1;payby=BILL",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => 'Enter check refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ )
+ %>
+% }
+
+% if ( $payby{'CASH'} && $curuser->access_right('Post refund') ) {
+ <% $s++ ? ' | ' : '' %>
+ <% include('/elements/popup_link-cust_main.html',
+ 'label' => 'Enter cash refund',
+ 'action' => "${p}edit/cust_refund.cgi?popup=1;payby=CASH",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => 'Enter cash refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ )
+ %>
+% }
+
+%# someday, perhaps. very few gateways let you do unlinked refunds at all.
+%# Authorize.net makes you sign a special form
+%#
+%# % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
+%# % && $curuser->access_right('Process refund')
+%# % && ! $cust_main->is_encrypted($cust_main->payinfo)
+%# % ) {
+%# <% $s++ ? ' | ' : '' %>
+%# <A HREF="<% $p %>misc/refund.cgi?payby=CARD;custnum=<% $custnum %>">Process credit card refund</A>
+%# % }
+%#
+%# % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
+%# % && $curuser->access_right('Process refund')
+%# % && ! $cust_main->is_encrypted($cust_main->payinfo)
+%# % ) {
+%# <% $s++ ? ' | ' : '' %>
+%# <A HREF="<% $p %>misc/refund.cgi?payby=CHEK;custnum=<% $custnum %>">Process electronic check (ACH) refund</A>
+%# % }
+
+% if ( $payby{'MCRD'} && $curuser->access_right('Post refund') ) {
+ <% $s++ ? ' | ' : '' %>
+ <A HREF="<% $p %>edit/cust_refund.cgi?payby=MCRD;custnum=<% $custnum %>">Post manual (offline/POS) credit card refund</A>
+% }
+
+<BR>
+
+%# tax exemption link
+
+% if ( $curuser->access_right('View customer tax exemptions') ) {
+ <A HREF="<% $p %>search/cust_tax_exempt_pkg.cgi?custnum=<% $custnum %>">View tax exemptions</A>
+ <BR>
+% }
+
+%# batched payment links
+
+% if ( ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
+% && $curuser->access_right('View customer batched payments')
+% )
+% {
+ View batched payments:
+% foreach my $status (qw( Queued In-transit Complete All )) {
+ <A HREF="<% $p %>search/cust_pay_batch.cgi?status=<% $status{$status} %>;custnum=<% $custnum %>"><% $status %></A>
+ <% $status ne 'All' ? '|' : '' %>
+% }
+ <BR>
+% }
+
+%# pending payment links
+
+% if ( $curuser->access_right('View customer pending payments')
+% && scalar($cust_main->cust_pay_pending)
+% )
+% {
+ <A HREF="<% $p %>search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=<% $custnum %>">View pending payments</A><BR>
+% }
+
+%# and now the table
+
+<% include("/elements/table-grid.html") %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Description</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Invoice</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Payment</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>In-house<BR>Credit</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Refund</FONT></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Balance</FONT></TH>
+</TR>
+
+%#display payment history
+
+%my $money_char = $conf->config('money_char') || '$';
+%
+%sub balance_forward_row {
+% my( $b, $date, $money_char ) = @_;
+% ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/-&nbsp;\$/;
+
+ <TR ID="balance_forward_row">
+ <TD CLASS="grid" BGCOLOR="#dddddd">
+ <% time2str("%D",$date) %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="#dddddd">
+ <I>Starting balance on <% time2str("%D",$date) %></I>
+ (<A HREF="javascript:void(0);" onClick="show_history();">show prior history</A>)
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD>
+
+ </TR>
+%}
+%
+%my $balance = 0;
+%my %target = ();
+%
+%my $years = $conf->config('payment_history-years') || 2;
+%my $older_than = time - $years * 31556736; #60*60*24*365.24
+%my $hidden = 0;
+%my $seen = 0;
+%my $old_history = 0;
+%my $lastdate = 0;
+%
+%foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) {
+%
+% $lastdate = $item->{'date'};
+%
+% my $display;
+% if ( $item->{'date'} < $older_than ) {
+% $display = ' STYLE="display:none" ';
+% $hidden = 1;
+% } else {
+%
+% $display = '';
+%
+% if ( $hidden && ! $seen++ ) {
+% balance_forward_row($balance, $item->{'date'}, $money_char);
+% }
+%
+% }
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $charge = exists($item->{'charge'})
+% ? sprintf("$money_char\%.2f", $item->{'charge'})
+% : '';
+%
+% my $payment = exists($item->{'payment'})
+% ? sprintf("-&nbsp;$money_char\%.2f", $item->{'payment'})
+% : '';
+%
+% $payment ||= sprintf( "<DEL>-&nbsp;$money_char\%.2f</DEL>",
+% $item->{'void_payment'}
+% )
+% if exists($item->{'void_payment'});
+%
+% my $credit = exists($item->{'credit'})
+% ? sprintf("-&nbsp;$money_char\%.2f", $item->{'credit'})
+% : '';
+%
+% my $refund = exists($item->{'refund'})
+% ? sprintf("$money_char\%.2f", $item->{'refund'})
+% : '';
+%
+% my $target = exists($item->{'target'}) ? $item->{'target'} : '';
+%
+% $balance += $item->{'charge'} if exists $item->{'charge'};
+% $balance -= $item->{'payment'} if exists $item->{'payment'};
+% $balance -= $item->{'credit'} if exists $item->{'credit'};
+% $balance += $item->{'refund'} if exists $item->{'refund'};
+% $balance = sprintf("%.2f", $balance);
+% $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp
+% ( my $showbalance = $money_char. $balance ) =~ s/^\$\-/-&nbsp;\$/;
+%
+%
+
+
+ <TR <% $display ? $display.' ID="old_history'.$old_history++.'"' : ''%>>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+% unless ( !$target || $target{$target}++ ) {
+
+ <A NAME="<% $target %>">
+% }
+
+ <% time2str("%D",$item->{'date'}) %>
+% if ( $target && $target{$target} == 1 ) {
+
+ </A>
+% }
+
+ </FONT>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $item->{'desc'} %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $charge %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $payment %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $credit %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $refund %>
+ </TD>
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $showbalance %>
+ </TD>
+ </TR>
+% }
+
+%if ( scalar(@history) && $hidden && ! $seen++ ) {
+% balance_forward_row($balance, $lastdate, $money_char);
+%}
+
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+
+function show_history () {
+ //alert('showing history!');
+
+ var balance_forward_row = document.getElementById('balance_forward_row');
+
+ balance_forward_row.style.display = 'none';
+ for ( var i = 0; i < <% $old_history %>; i++ ) {
+ var oldRow = document.getElementById('old_history'+i);
+ oldRow.style.display = '';
+ }
+
+}
+
+</SCRIPT>
+
+<%init>
+
+my( $cust_main ) = @_;
+my $custnum = $cust_main->custnum;
+
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my @payby = grep /\w/, $conf->config('payby');
+#@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
+@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
+ unless @payby;
+my %payby = map { $_=>1 } @payby;
+
+my %status = (
+ 'Queued' => 'O', #Open
+ 'In-transit' => 'I',
+ 'Complete' => 'R', #Resolved
+ 'All' => '',
+);
+
+#get payment history
+my @history = ();
+
+my %opt =
+ ( map { $_ => scalar($conf->config($_)) }
+ qw( card_refund-days )
+ ),
+ ( map { $_ => $conf->exists($_) }
+ qw( deletepayments deleterefunds )
+ );
+
+#invoices
+foreach my $cust_bill ($cust_main->cust_bill) {
+ push @history, {
+ 'date' => $cust_bill->_date,
+ 'desc' => include('payment_history/invoice.html', $cust_bill, %opt ),
+ 'charge' => $cust_bill->charged,
+ };
+}
+
+#payments (some false laziness w/credits)
+foreach my $cust_pay ($cust_main->cust_pay) {
+ push @history, {
+ 'date' => $cust_pay->_date,
+ 'desc' => include('payment_history/payment.html', $cust_pay, %opt ),
+ 'payment' => $cust_pay->paid,
+ #'target' => $target, #XXX
+ };
+}
+
+#voided payments
+foreach my $cust_pay_void ($cust_main->cust_pay_void) {
+ push @history, {
+ 'date' => $cust_pay_void->_date,
+ 'desc' => include('payment_history/voided_payment.html', $cust_pay_void),
+ 'void_payment' => $cust_pay_void->paid,
+ };
+
+}
+
+#credits (some false laziness w/payments)
+foreach my $cust_credit ($cust_main->cust_credit) {
+ push @history, {
+ 'date' => $cust_credit->_date,
+ 'desc' => include('payment_history/credit.html', $cust_credit),
+ 'credit' => $cust_credit->amount,
+ };
+
+}
+
+#refunds
+foreach my $cust_refund ($cust_main->cust_refund) {
+ push @history, {
+ 'date' => $cust_refund->_date,
+ 'desc' => include('payment_history/refund.html', $cust_refund),
+ 'refund' => $cust_refund->refund,
+ };
+
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/credit.html b/httemplate/view/cust_main/payment_history/credit.html
new file mode 100644
index 000000000..2deb27564
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/credit.html
@@ -0,0 +1,140 @@
+<% $pre %>Credit<% $post %>
+by <% $cust_credit->otaker %><% "$reason$desc$apply$delete$unapply" %>
+<%init>
+
+my( $cust_credit, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my @cust_credit_bill = $cust_credit->cust_credit_bill;
+my @cust_credit_refund = $cust_credit->cust_credit_refund;
+
+my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+if ( scalar(@cust_credit_bill) == 0
+ && scalar(@cust_credit_refund) == 0 ) {
+ #completely unapplied
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ if ( $curuser->access_right('Apply credit') ) {
+ if ( $cust_credit->cust_main->total_owed > 0 ) {
+ $apply = ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_credit_bill.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ if ( $cust_credit->cust_main->total_unapplied_refunds > 0 ) {
+ $apply.= ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply to refund',
+ 'action' => "${p}edit/cust_credit_refund.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit to refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ }
+} elsif ( scalar(@cust_credit_bill) == 1
+ && scalar(@cust_credit_refund) == 0
+ && $cust_credit->credited == 0 ) {
+ #applied to one invoice, the usual situation
+ $desc = ' '. $cust_credit_bill[0]->applied_to_invoice;
+} elsif ( scalar(@cust_credit_bill) == 0
+ && scalar(@cust_credit_refund) == 1
+ && $cust_credit->credited == 0 ) {
+ #applied to one refund
+ $desc = ' refunded on '. time2str("%D", $cust_credit_refund[0]->_date);
+} else {
+ #complicated
+ $desc = '<BR>';
+ foreach my $app ( sort { $a->_date <=> $b->_date }
+ ( @cust_credit_bill, @cust_credit_refund ) ) {
+ if ( $app->isa('FS::cust_credit_bill') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' '. $app->applied_to_invoice.
+ '<BR>';
+ #' on '. time2str("%D", $app->_date).
+ } elsif ( $app->isa('FS::cust_credit_refund') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' refunded on '. time2str("%D", $app->_date).
+ '<BR>';
+ } else {
+ die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund";
+ }
+ }
+ if ( $cust_credit->credited > 0 ) {
+ $desc .= '&nbsp;&nbsp;<B><FONT COLOR="#FF0000">$'.
+ $cust_credit->credited. ' unapplied</FONT></B>';
+ if ( $curuser->access_right('Apply credit') ) {
+ if ( $cust_credit->cust_main->total_owed > 0 ) {
+ $apply = ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_credit_bill.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ if ( $cust_credit->cust_main->total_unapplied_refunds > 0 ) {
+ $apply.= ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply to refund',
+ 'action' => "${p}edit/cust_credit_refund.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit to refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ }
+ $desc .= '<BR>';
+ }
+}
+#
+my $delete = '';
+if ( $cust_credit->closed !~ /^Y/i
+
+ #s'pose deleting a credit isn't bad like deleting a payment
+ # and this needs to be generally available until we have credit voiding..
+ #&& $conf->exists('deletecredits')
+
+ && $curuser->access_right('Delete credit')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_credit.cgi?!. $cust_credit->crednum.
+ qq!', 'Are you sure you want to delete this credit?')">!.
+ qq!delete</A>)!;
+}
+
+my $unapply = '';
+if ( $cust_credit->closed !~ /^Y/i
+ && scalar(@cust_credit_bill)
+ && $curuser->access_right('Unapply credit')
+ )
+{
+ $unapply = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unapply-cust_credit.cgi?!. $cust_credit->crednum.
+ qq!', 'Are you sure you want to unapply this credit?')">!.
+ qq!unapply</A>)!;
+}
+
+my $reason = $cust_credit->reason
+ ? ' ('. $cust_credit->reason. ')'
+ : '';
+
+</%init>
+
diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html
new file mode 100644
index 000000000..39c67396e
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/invoice.html
@@ -0,0 +1,34 @@
+<% $link %><% $pre %>Invoice #<% $invnum %>
+(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $events %>
+<%init>
+
+my( $cust_bill, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my($pre, $post) = ('', '');
+if ( $cust_bill->owed > 0 ) {
+ $pre = '<B><FONT SIZE="+1" COLOR="#FF0000">Open ';
+ $post = '</FONT></B>';
+}
+
+my $invnum = $cust_bill->invnum;
+
+my $link = $curuser->access_right('View invoices')
+ ? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!
+ : '';
+
+my $events = '';
+#1.9
+if ( $cust_bill->num_cust_event
+ && ( $curuser->access_right('Billing event reports')
+ || $curuser->access_right('View customer billing events')
+ )
+ ) {
+ $events =
+ qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?invnum=!.
+ $cust_bill->invnum. '">(&nbsp;View invoice events&nbsp;)</A></FONT>';
+}
+#
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/payment.html b/httemplate/view/cust_main/payment_history/payment.html
new file mode 100644
index 000000000..2e24b1785
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/payment.html
@@ -0,0 +1,209 @@
+<% $pre %>Payment<% $post %> by <% $otaker %>
+<% "$info$desc$view$apply$refund$void$delete$unapply" %>
+<%init>
+
+my( $cust_pay, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_pay->payby;
+
+my $payinfo;
+if ( $payby eq 'CARD' ) {
+ $payinfo = $cust_pay->paymask;
+} elsif ( $payby eq 'CHEK' ) {
+ my( $account, $aba ) = split('@', $cust_pay->paymask );
+ $payinfo = "ABA $aba, Acct #$account";
+} else {
+ $payinfo = $cust_pay->payinfo;
+}
+my @cust_bill_pay = $cust_pay->cust_bill_pay;
+my @cust_pay_refund = $cust_pay->cust_pay_refund;
+
+my $target = "$payby$payinfo";
+$payby =~ s/^BILL$/Check #/ if $payinfo;
+$payby =~ s/^CHEK$/Electronic check /;
+$payby =~ s/^PREP$/Prepaid card /;
+$payby =~ s/^CARD$/Credit card #/;
+$payby =~ s/^COMP$/Complimentary by /;
+$payby =~ s/^CASH$/Cash/;
+$payby =~ s/^WEST$/Western Union/;
+$payby =~ s/^MCRD$/Manual credit card/;
+$payby =~ s/^BILL$//;
+my $info = $payby ? "($payby$payinfo)" : '';
+
+my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+if ( scalar(@cust_bill_pay) == 0
+ && scalar(@cust_pay_refund) == 0 ) {
+ #completely unapplied
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ if ( $curuser->access_right('Apply payment') ) {
+ if ( $cust_pay->cust_main->total_owed > 0 ) {
+ $apply = ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_bill_pay.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ if ( $cust_pay->cust_main->total_unapplied_refunds > 0 ) {
+ $apply.= ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply to refund',
+ 'action' => "${p}edit/cust_pay_refund.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment to refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ }
+} elsif ( scalar(@cust_bill_pay) == 1
+ && scalar(@cust_pay_refund) == 0
+ && $cust_pay->unapplied == 0 ) {
+ #applied to one invoice, the usual situation
+ $desc = ' '. $cust_bill_pay[0]->applied_to_invoice;
+} elsif ( scalar(@cust_bill_pay) == 0
+ && scalar(@cust_pay_refund) == 1
+ && $cust_pay->unapplied == 0 ) {
+ #applied to one refund
+ $desc = ' refunded on '. time2str("%D", $cust_pay_refund[0]->_date);
+} else {
+ #complicated
+ $desc = '<BR>';
+ foreach my $app ( sort { $a->_date <=> $b->_date }
+ ( @cust_bill_pay, @cust_pay_refund ) ) {
+ if ( $app->isa('FS::cust_bill_pay') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' '. $app->applied_to_invoice.
+ '<BR>';
+ #' on '. time2str("%D", $cust_bill_pay->_date).
+ } elsif ( $app->isa('FS::cust_pay_refund') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' refunded on '. time2str("%D", $app->_date).
+ '<BR>';
+ } else {
+ die "$app is not a FS::cust_bill_pay or FS::cust_pay_refund";
+ }
+ }
+ if ( $cust_pay->unapplied > 0 ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '<B><FONT COLOR="#FF0000">$'.
+ $cust_pay->unapplied. ' unapplied</FONT></B>';
+ if ( $curuser->access_right('Apply payment') ) {
+ if ( $cust_pay->cust_main->total_owed > 0 ) {
+ $apply = ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_bill_pay.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ if ( $cust_pay->cust_main->total_unapplied_refunds > 0 ) {
+ $apply.= ' ('.
+ include( '/elements/popup_link.html',
+ 'label' => 'apply to refund',
+ 'action' => "${p}edit/cust_pay_refund.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment to refund',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ }
+ $desc .= '<BR>';
+ }
+}
+
+my $view =
+ ' ('. include('/elements/popup_link.html',
+ 'label' => 'view receipt',
+ 'action' => "${p}view/cust_pay.html?link=popup;paynum=".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Payment Receipt',
+ ).
+ ')';
+
+my $refund = '';
+my $refund_days = $opt{'card_refund-days'} || 120;
+if ( $cust_pay->closed !~ /^Y/i
+ && $cust_pay->payby =~ /^(CARD|CHEK)$/
+ && time-$cust_pay->_date < $refund_days*86400
+ && $cust_pay->unrefunded > 0
+ && $curuser->access_right('Refund payment')
+) {
+ $refund = qq! (<A HREF="${p}edit/cust_refund.cgi?payby=$1;!.
+ qq!paynum=!. $cust_pay->paynum. '"'.
+ qq! TITLE="Send a refund for this payment to the payment gateway"!.
+ qq!>refund</A>)!;
+}
+
+my $void = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && ( ( $cust_pay->payby eq 'CARD'
+ && $curuser->access_right('Credit card void')
+ )
+ || ( $cust_pay->payby eq 'CHEK'
+ && $curuser->access_right('Echeck void')
+ )
+ || ( $cust_pay->payby !~ /^(CARD|CHEK)$/
+ && $curuser->access_right('Regular void')
+ )
+ )
+ )
+{
+ $void = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/void-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to void this payment?')"!.
+ qq! TITLE="Void this payment from the database!.
+ ( $cust_pay->payby =~ /^(CARD|CHEK)$/
+ ? ' (do not send anything to the payment gateway)'
+ : ''
+ ). '"'.
+ qq!>void</A>)!;
+}
+
+my $delete = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && $opt{'deletepayments'}
+ && $curuser->access_right('Delete payment')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to delete this payment?')"!.
+ qq! TITLE="Delete this payment from the database completely - not recommended"!.
+ qq!>delete</A>)!;
+}
+
+my $unapply = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && scalar(@cust_bill_pay)
+ && $curuser->access_right('Unapply payment')
+ )
+{
+ $unapply = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unapply-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to unapply this payment?')"!.
+ qq! TITLE="Keep this payment, but dissociate it from the invoices it is currently applied against"!.
+ qq!>unapply</A>)!;
+}
+
+my $otaker = $cust_pay->otaker;
+$otaker = '<i>auto billing</i>' if $otaker eq 'fs_daily';
+$otaker = '<i>customer self-service</i>' if $otaker eq 'fs_selfservice';
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/refund.html b/httemplate/view/cust_main/payment_history/refund.html
new file mode 100644
index 000000000..4a48fea1e
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/refund.html
@@ -0,0 +1,50 @@
+<% $pre %>Refund<% $post %>
+(<% $payby. $payinfo %>)
+by <% $cust_refund->otaker %><% $view %><% $delete %>
+<%init>
+
+my( $cust_refund, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_refund->payby;
+my $payinfo = $payby eq 'CARD'
+ ? $cust_refund->paymask
+ : $cust_refund->payinfo;
+
+$payby =~ s/^BILL$/Check #/ if $payinfo;
+$payby =~ s/^BILL$/Check/;
+$payby =~ s/^CHEK$/Electronic check /;
+$payby =~ s/^(CARD|COMP)$/$1 /;
+
+my($pre, $post) = ('', '');
+if ( $cust_refund->unapplied > 0 ) {
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+}
+
+my $view =
+ ' ('. include('/elements/popup_link.html',
+ 'label' => 'view receipt',
+ 'action' => "${p}view/cust_refund.html?link=popup;".
+ 'refundnum='. $cust_refund->refundnum,
+ 'actionlabel' => 'Payment Receipt',
+ ).
+ ')';
+
+
+my $delete = '';
+if ( $cust_refund->closed !~ /^Y/i
+ && $opt{'deleterefunds'}
+ && $curuser->access_right('Delete refund')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_refund.cgi?!. $cust_refund->refundnum.
+ qq!', 'Are you sure you want to delete this refund?')"!.
+ qq! TITLE="Delete this refund from the database completely - not recommended"!.
+ qq!>delete</A>)!;
+}
+
+</%init>
+
diff --git a/httemplate/view/cust_main/payment_history/voided_payment.html b/httemplate/view/cust_main/payment_history/voided_payment.html
new file mode 100644
index 000000000..9cbc47b66
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/voided_payment.html
@@ -0,0 +1,37 @@
+<DEL>Payment <% $info %></DEL>
+<I>voided <% time2str("%D", $cust_pay_void->void_date) %>
+by <% $cust_pay_void->otaker %></I><% $unvoid %>
+<%init>
+
+my( $cust_pay_void, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_pay_void->payby;
+my $payinfo = $payby eq 'CARD'
+ ? $cust_pay_void->paymask
+ : $cust_pay_void->payinfo;
+
+$payby =~ s/^BILL$/Check #/ if $payinfo;
+$payby =~ s/^CHEK$/Electronic check /;
+$payby =~ s/^BILL$//;
+$payby =~ s/^(CARD|COMP)$/$1 /;
+my $info = $payby ? " ($payby$payinfo)" : '';
+
+my $unvoid = '';
+if ( $cust_pay_void->closed !~ /^Y/i
+ && $curuser->access_right('Unvoid')
+ )
+{
+ $unvoid = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unvoid-cust_pay_void.cgi?!. $cust_pay_void->paynum.
+ qq!', 'Are you sure you want to unvoid this payment?')"!.
+ qq! TITLE="Unvoid this payment from the database!.
+ ( $cust_pay_void->payby =~ /^(CARD|CHEK)$/
+ ? ' (do not send anything to the payment gateway)'
+ : ''
+ ). '"'.
+ qq!>unvoid</A>)!;
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html
new file mode 100644
index 000000000..b5d581d50
--- /dev/null
+++ b/httemplate/view/cust_main/tickets.html
@@ -0,0 +1,84 @@
+<A NAME="tickets"><FONT SIZE="+2">Tickets</FONT></A>
+<BR>
+
+(<A HREF="<% $open_link %>">View <% $openlabel %> tickets for this customer</A>)
+(<A HREF="<% $res_link %>">View resolved tickets for this customer</A>)
+<BR>
+(<A HREF="<% $new_link %>">Create new ticket for this customer</A>)
+
+<% include("/elements/table-grid.html") %>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc">#</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Subject</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Queue</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Owner</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Priority</TH>
+</TR>
+
+% foreach my $ticket ( @tickets ) {
+% my $href = FS::TicketSystem->href_ticket($ticket->{id});
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF=<%$href%>><% $ticket->{id} %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF=<%$href%>><% $ticket->{subject} %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{status} %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{queue} %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{owner} %>
+ </TD>
+
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{content}
+ ? $ticket->{content}.' ('.$ticket->{priority}.')'
+ : $ticket->{priority}
+ %>
+ </TD>
+
+ </TR>
+
+% }
+
+</TABLE>
+
+<%init>
+
+my( $cust_main ) = @_;
+my( @tickets ) = $cust_main->tickets;
+
+my $open_link = FS::TicketSystem->href_customer_tickets($cust_main->custnum);
+my $openlabel = join('/', FS::TicketSystem->statuses );
+
+my $res_link = FS::TicketSystem->href_customer_tickets(
+ $cust_main->custnum,
+ { 'statuses' => [ 'resolved' ] }
+ );
+
+my $new_link = FS::TicketSystem->href_new_ticket(
+ $cust_main,
+ join(', ', $cust_main->invoicing_list_emailonly )
+ );
+
+</%init>
diff --git a/httemplate/view/cust_pay.html b/httemplate/view/cust_pay.html
new file mode 100644
index 000000000..c36d76904
--- /dev/null
+++ b/httemplate/view/cust_pay.html
@@ -0,0 +1,135 @@
+% if ( $link eq 'popup' ) {
+
+ <% include('/elements/header-popup.html', "Payment Receipt" ) %>
+
+ <CENTER><A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A></CENTER><BR>
+
+% } elsif ( $link eq 'print' ) {
+
+ <% include('/elements/header-popup.html', "Payment Receipt" ) %>
+
+% #it would be nice if the menubar could be hidden for print, but better to
+% # have it available than not, otherwise the user winds up at a dead end
+ <% menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ %>
+ <BR><BR>
+
+% } else {
+
+ <% include('/elements/header.html', "Payment Receipt", menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ 'Print receipt' => $pr_link,
+ ))
+ %>
+
+% }
+
+% unless ($link eq 'popup' ) {
+ <% include('/elements/small_custview.html',
+ $custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #no balance
+ )
+ %>
+ <BR><BR>
+% }
+
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Payment#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->paynum %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_pay->_date %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_pay->paid %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Payment method</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->payby_name %> #<% $cust_pay->paymask %></B></TD>
+</TR>
+
+% if ( $cust_pay->payby =~ /^(CARD|CHEK|LECB)$/ && $cust_pay->paybatch ) {
+
+ <TR>
+ <TD ALIGN="right">Processor</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->processor %></B></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Authorization#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->authorization %></B></TD>
+ </TR>
+
+% if ( $cust_pay->order_number ) {
+ <TR>
+ <TD ALIGN="right">Order#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay->order_number %></B></TD>
+ </TR>
+% }
+
+% }
+
+</TABLE>
+
+% if ( $link eq 'print' ) {
+
+ <SCRIPT TYPE="text/javascript">
+ window.print();
+ </SCRIPT>
+
+% }
+
+% if ( $link =~ /^(popup|print)$/ ) {
+ </BODY>
+ </HTML>
+% } else {
+ <% include('/elements/footer.html') %>
+% }
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('View invoices') #remove this in 1.9 EVENTUALLY
+ || $curuser->access_right('View customer payments');
+
+$cgi->param('paynum') =~ /^(\d+)$/ or die "no paynum";
+my $paynum = $1;
+
+my $link = '';
+if ( $cgi->param('link') =~ /^(\w+)$/ ) {
+ $link = $1;
+}
+
+my $cust_pay = qsearchs({
+ 'select' => 'cust_pay.*',
+ 'table' => 'cust_pay',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'paynum' => $paynum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Payment #$paynum not found!" unless $cust_pay;
+
+my $pr_link = "${p}view/cust_pay.html?link=print;paynum=$paynum";
+
+my $custnum = $cust_pay->custnum;
+my $display_custnum = $cust_pay->cust_main->display_custnum;
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+tie my %payby, 'Tie::IxHash', FS::payby->payby2longname;
+
+</%init>
diff --git a/httemplate/view/cust_refund.html b/httemplate/view/cust_refund.html
new file mode 100644
index 000000000..138c8780d
--- /dev/null
+++ b/httemplate/view/cust_refund.html
@@ -0,0 +1,142 @@
+% if ( $link eq 'popup' ) {
+
+ <% include('/elements/header-popup.html', "Refund Receipt" ) %>
+
+ <CENTER><A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A></CENTER><BR>
+
+% } elsif ( $link eq 'print' ) {
+
+ <% include('/elements/header-popup.html', "Refund Receipt" ) %>
+
+% #it would be nice if the menubar could be hidden for print, but better to
+% # have it available than not, otherwise the user winds up at a dead end
+ <% menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ %>
+ <BR><BR>
+
+% } else {
+
+ <% include('/elements/header.html', "Refund Receipt", menubar(
+ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ 'Print receipt' => $pr_link,
+ ))
+ %>
+
+% }
+
+% unless ($link eq 'popup' ) {
+ <% include('/elements/small_custview.html',
+ $custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #no balance
+ )
+ %>
+ <BR><BR>
+% }
+
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Refund#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->refundnum %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_refund->_date %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_refund->refund %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Reason</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->reason %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Refund method</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->payby_name %><% $cust_refund->paymask ? ' #'.$cust_refund->paymask : '' %></B></TD>
+</TR>
+
+% if ( $cust_refund->payby =~ /^(CARD|CHEK|LECB)$/ && $cust_refund->paybatch ) {
+
+ <TR>
+ <TD ALIGN="right">Processor</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->processor %></B></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Authorization#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->authorization %></B></TD>
+ </TR>
+
+% if ( $cust_refund->order_number ) {
+ <TR>
+ <TD ALIGN="right">Order#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->order_number %></B></TD>
+ </TR>
+% }
+
+% }
+
+</TABLE>
+
+% if ( $link eq 'print' ) {
+
+ <SCRIPT TYPE="text/javascript">
+ window.print();
+ </SCRIPT>
+
+% }
+
+% if ( $link =~ /^(popup|print)$/ ) {
+ </BODY>
+ </HTML>
+% } else {
+ <% include('/elements/footer.html') %>
+% }
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('View invoices') #remove this in 1.9 EVENTUALLY
+ || $curuser->access_right('View customer payments');
+ #'View customer refunds' ???
+
+
+$cgi->param('refundnum') =~ /^(\d+)$/ or die "no refundnum";
+my $refundnum = $1;
+
+my $link = '';
+if ( $cgi->param('link') =~ /^(\w+)$/ ) {
+ $link = $1;
+}
+
+my $cust_refund = qsearchs({
+ 'select' => 'cust_refund.*',
+ 'table' => 'cust_refund',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'refundnum' => $refundnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Refund #$refundnum not found!" unless $cust_refund;
+
+my $pr_link = "${p}view/cust_refund.html?link=print;refundnum=$refundnum";
+
+my $custnum = $cust_refund->custnum;
+my $display_custnum = $cust_refund->cust_main->display_custnum;
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+tie my %payby, 'Tie::IxHash', FS::payby->payby2longname;
+
+</%init>
diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html
new file mode 100644
index 000000000..a0b4e37b2
--- /dev/null
+++ b/httemplate/view/elements/svc_Common.html
@@ -0,0 +1,152 @@
+% # options example...
+% #
+% # 'table' => 'svc_something'
+% #
+% # 'labels' => {
+% # 'column' => 'Label',
+% # },
+% #
+% # listref - each item is a literal column name (or method) or (notyet) coderef
+% # if not specified all columns (except for the primary key) will be viewable
+% # 'fields' => [
+% # ]
+% #
+% # # defaults to "edit/$table.cgi?", will have svcnum appended
+% # 'edit_url' =>
+%
+%
+% if ( $custnum ) {
+
+
+ <% include("/elements/header.html","View $label: $value") %>
+
+ <% include( '/elements/small_custview.html', $custnum, '', 1,
+ "${p}view/cust_main.cgi") %>
+ <BR>
+% } else {
+
+
+ <SCRIPT>
+ function areyousure(href) {
+ if (confirm("Permanently delete this <% $label %>?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+ <% include("/elements/header.html","View $label: $value", menubar(
+ "Cancel this (unaudited) $label" =>
+ "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')"
+ )) %>
+% }
+
+
+Service #<B><% $svcnum %></B>
+% my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
+| <A HREF="<%$url%><%$svcnum%>">Edit this <% $label %></A>
+<BR>
+
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+
+% foreach my $f ( @$fields ) {
+%
+% my($field, $type);
+% if ( ref($f) ) {
+% $field = $f->{'field'},
+% $type = $f->{'type'} || 'text',
+% } else {
+% $field = $f;
+% $type = 'text';
+% }
+%
+% my $columndef = $part_svc->part_svc_column($field);
+% unless ($columndef->columnflag eq 'F' && !length($columndef->columnvalue)) {
+
+ <TR>
+ <TD ALIGN="right">
+ <% ( $opt{labels} && exists $opt{labels}->{$field} )
+ ? $opt{labels}->{$field}
+ : $field
+ %>
+ </TD>
+
+% #eventually more options for <SELECT>, etc. fields
+
+ <TD BGCOLOR="#ffffff"><% $svc_x->$field %><TD>
+
+ </TR>
+
+% }
+%
+% }
+
+% foreach (sort { $a cmp $b } $svc_x->virtual_fields) {
+ <% $svc_x->pvf($_)->widget('HTML', 'view', $svc_x->getfield($_)) %>
+% }
+
+
+</TABLE></TD></TR></TABLE>
+
+<BR>
+
+% if ( defined($opt{'html_foot'}) ) {
+
+ <% ref($opt{'html_foot'})
+ ? &{ $opt{'html_foot'} }($svc_x)
+ : $opt{'html_foot'}
+ %>
+ <BR>
+
+% }
+
+<% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my(%opt) = @_;
+
+my $table = $opt{'table'};
+
+my $fields = $opt{'fields'}
+ #|| [ grep { $_ ne 'svcnum' } dbdef->table($table)->columns ];
+ || [ grep { $_ ne 'svcnum' } fields($table) ];
+
+my $svcnum;
+if ( $cgi->param('svcnum') ) {
+ $cgi->param('svcnum') =~ /^(\d+)$/ or die "unparsable svcnum";
+ $svcnum = $1;
+} else {
+ my($query) = $cgi->keywords;
+ $query =~ /^(\d+)$/ or die "no svcnum";
+ $svcnum = $1;
+}
+my $svc_x = qsearchs({
+ 'select' => $opt{'table'}.'.*',
+ 'table' => $opt{'table'},
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'svcnum' => $svcnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+}) or die "Unknown svcnum $svcnum in ". $opt{'table'}. " table\n";
+
+my $cust_svc = $svc_x->cust_svc;
+my($label, $value, $svcdb) = $cust_svc->label;
+
+my $part_svc = $cust_svc->part_svc;
+
+my $pkgnum = $cust_svc->pkgnum;
+
+my($cust_pkg, $custnum);
+if ($pkgnum) {
+ $cust_pkg = $cust_svc->cust_pkg;
+ $custnum = $cust_pkg->custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+
+</%init>
diff --git a/httemplate/view/logo.cgi b/httemplate/view/logo.cgi
new file mode 100644
index 000000000..aeca0f3b3
--- /dev/null
+++ b/httemplate/view/logo.cgi
@@ -0,0 +1,47 @@
+<% $data %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $conf = new FS::Conf;
+
+my $type;
+if ( $cgi->param('type') eq 'png' ) {
+ $type = 'png';
+} elsif ( $cgi->param('type') eq 'eps' ) {
+ $type = 'eps';
+} else {
+ die "unknown logo type ". $cgi->param('type');
+}
+
+my $data;
+if ( $cgi->param('preview_session') =~ /^(\w+)$/ ) {
+
+ my $session = $1;
+ my $curuser = $FS::CurrentUser::CurrentUser;
+ $data = decode_base64( $curuser->option("logo_preview$session") );
+
+} elsif ( $cgi->param('name') =~ /^([^\.\/]*)$/ ) {
+
+ my $templatename = $1;
+ if ( $templatename && $conf->exists("logo_$templatename.$type") ) {
+ $templatename = "_$templatename";
+ } else {
+ $templatename = '';
+ }
+
+ if ( $type eq 'png' ) {
+ $data = $conf->config_binary("logo$templatename.png");
+ } elsif ( $type eq 'eps' ) {
+ #convert EPS to a png... punting on that for now
+ }
+
+} else {
+ die "neither a valid name nor a valid preview_session specified";
+}
+
+http_header('Content-Type' => 'image/png' );
+
+</%init>
+
diff --git a/httemplate/view/svc_Common.html b/httemplate/view/svc_Common.html
new file mode 100644
index 000000000..bb3a6dd33
--- /dev/null
+++ b/httemplate/view/svc_Common.html
@@ -0,0 +1,29 @@
+<%init>
+
+# false laziness w/edit/svc_Common.html
+
+$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparsable svcdb";
+my $table = $1;
+require "FS/$table.pm";
+
+my %opt;
+if ( UNIVERSAL::can("FS::$table", 'table_info') ) {
+ $opt{'name'} = "FS::$table"->table_info->{'name'};
+
+ my $fields = "FS::$table"->table_info->{'fields'};
+ my %labels = map { $_ => ( ref($fields->{$_})
+ ? $fields->{$_}{'label'}
+ : $fields->{$_}
+ );
+ }
+ keys %$fields;
+ $opt{'labels'} = \%labels;
+}
+
+</%init>
+<% include('elements/svc_Common.html',
+ 'table' => $table,
+ 'edit_url' => $p."edit/svc_Common.html?svcdb=$table;svcnum=",
+ %opt,
+ )
+%>
diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi
new file mode 100755
index 000000000..e87a8ee9a
--- /dev/null
+++ b/httemplate/view/svc_acct.cgi
@@ -0,0 +1,401 @@
+% if ( $custnum ) {
+
+ <% include("/elements/header.html","View $svc account") %>
+ <% include( '/elements/small_custview.html', $custnum, '', 1,
+ "${p}view/cust_main.cgi") %>
+ <BR>
+
+% } else {
+
+ <SCRIPT>
+ function areyousure(href) {
+ if (confirm("Permanently delete this account?") == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+ <% include("/elements/header.html",'Account View', menubar(
+ "Cancel this (unaudited) account" =>
+ "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')",
+ )) %>
+
+% }
+
+% if ( $part_svc->part_export_usage ) {
+%
+% my $last_bill;
+% my %plandata;
+% if ( $cust_pkg ) {
+% #false laziness w/httemplate/edit/part_pkg... this stuff doesn't really
+% #belong in plan data
+% %plandata = map { /^(\w+)=(.*)$/; ( $1 => $2 ); }
+% split("\n", $cust_pkg->part_pkg->plandata );
+%
+% $last_bill = $cust_pkg->last_bill;
+% } else {
+% $last_bill = 0;
+% %plandata = ();
+% }
+%
+% my $seconds = $svc_acct->seconds_since_sqlradacct( $last_bill, time );
+% my $hour = int($seconds/3600);
+% my $min = int( ($seconds%3600) / 60 );
+% my $sec = $seconds%60;
+%
+% my $input = $svc_acct->attribute_since_sqlradacct(
+% $last_bill, time, 'AcctInputOctets'
+% ) / 1048576;
+% my $output = $svc_acct->attribute_since_sqlradacct(
+% $last_bill, time, 'AcctOutputOctets'
+% ) / 1048576;
+%
+%
+
+
+ RADIUS session information<BR>
+ <% ntable('#cccccc',2) %>
+ <TR><TD BGCOLOR="#ffffff">
+% if ( $seconds ) {
+
+ Online <B><% $hour %></B>h <B><% $min %></B>m <B><% $sec %></B>s
+% } else {
+
+ Has not logged on
+% }
+% if ( $cust_pkg ) {
+
+ since last bill (<% time2str('%a %b %o %Y', $last_bill) %>)
+% if ( length($plandata{recur_included_hours}) ) {
+
+ - <% $plandata{recur_included_hours} %> total hours in plan
+% }
+
+ <BR>
+% } else {
+
+ (no billing cycle available for unaudited account)<BR>
+% }
+
+
+ Upload: <B><% sprintf("%.3f", $input) %></B> megabytes<BR>
+ Download: <B><% sprintf("%.3f", $output) %></B> megabytes<BR>
+ Last Login: <B><% $svc_acct->last_login_text %></B><BR>
+% my $href = qq!<A HREF="${p}search/sqlradius.cgi?svcnum=$svcnum!;
+
+ View session detail:
+ <% $href %>;begin=<% $last_bill %>">this billing cycle</A>
+ | <% $href %>;begin=<% time-15552000 %>">past six months</A>
+ | <% $href %>">all sessions</A>
+
+ </TD></TR></TABLE><BR>
+% }
+
+% my @part_svc = ();
+% if ($FS::CurrentUser::CurrentUser->access_right('Change customer service')) {
+
+ <SCRIPT TYPE="text/javascript">
+ function enable_change () {
+ if ( document.OneTrueForm.svcpart.selectedIndex > 1 ) {
+ document.OneTrueForm.submit.disabled = false;
+ } else {
+ document.OneTrueForm.submit.disabled = true;
+ }
+ }
+ </SCRIPT>
+
+ <FORM NAME="OneTrueForm" ACTION="<%$p%>edit/process/cust_svc.cgi">
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
+ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+% #print qq!<BR><A HREF="../misc/sendconfig.cgi?$svcnum">Send account information</A>!;
+%
+% if ( $pkgnum ) {
+% @part_svc = grep { $_->svcdb eq 'svc_acct'
+% && $_->svcpart != $part_svc->svcpart }
+% $cust_pkg->available_part_svc;
+% } else {
+% @part_svc = qsearch('part_svc', {
+% svcdb => 'svc_acct',
+% disabled => '',
+% svcpart => { op=>'!=', value=>$part_svc->svcpart },
+% } );
+% }
+%
+% }
+
+Service #<B><% $svcnum %></B>
+| <A HREF="<%$p%>edit/svc_acct.cgi?<%$svcnum%>">Edit this service</A>
+
+% if ( @part_svc ) {
+
+| <SELECT NAME="svcpart" onChange="enable_change()">
+ <OPTION VALUE="">Change service</OPTION>
+ <OPTION VALUE="">--------------</OPTION>
+% foreach my $opt_part_svc ( @part_svc ) {
+
+ <OPTION VALUE="<% $opt_part_svc->svcpart %>"><% $opt_part_svc->svc %></OPTION>
+% }
+
+ </SELECT>
+ <INPUT NAME="submit" TYPE="submit" VALUE="Change" disabled>
+
+% }
+
+
+<% &ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+
+<TR>
+ <TD ALIGN="right">Service</TD>
+ <TD BGCOLOR="#ffffff"><% $part_svc->svc %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Username</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->username %></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Domain</TD>
+ <TD BGCOLOR="#ffffff"><% $domain %></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Password</TD>
+ <TD BGCOLOR="#ffffff">
+% my $password = $svc_acct->_password;
+% if ( $password =~ /^\*\w+\* (.*)$/ ) {
+% $password = $1;
+%
+
+ <I>(login disabled)</I>
+% }
+% if ( $conf->exists('showpasswords') ) {
+
+ <PRE><% encode_entities($password) %></PRE>
+% } else {
+
+ <I>(hidden)</I>
+% }
+
+
+ </TD>
+</TR>
+% $password = '';
+% if ( $conf->exists('security_phrase') ) {
+% my $sec_phrase = $svc_acct->sec_phrase;
+%
+
+ <TR>
+ <TD ALIGN="right">Security phrase</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->sec_phrase %></TD>
+ </TR>
+% }
+% if ( $svc_acct->popnum ) {
+% my $svc_acct_pop = qsearchs('svc_acct_pop',{'popnum'=>$svc_acct->popnum});
+%
+
+ <TR>
+ <TD ALIGN="right">Access number</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct_pop->text %></TD>
+ </TR>
+% }
+% if ($svc_acct->uid ne '') {
+
+ <TR>
+ <TD ALIGN="right">UID</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->uid %></TD>
+ </TR>
+% }
+% if ($svc_acct->gid ne '') {
+
+ <TR>
+ <TD ALIGN="right">GID</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->gid %></TD>
+ </TR>
+% }
+% if ($svc_acct->finger ne '') {
+
+ <TR>
+ <TD ALIGN="right">GECOS</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->finger %></TD>
+ </TR>
+% }
+% if ($svc_acct->dir ne '') {
+
+ <TR>
+ <TD ALIGN="right">Home directory</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->dir %></TD>
+ </TR>
+% }
+% if ($svc_acct->shell ne '') {
+
+ <TR>
+ <TD ALIGN="right">Shell</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->shell %></TD>
+ </TR>
+% }
+% if ($svc_acct->quota ne '') {
+
+ <TR>
+ <TD ALIGN="right">Quota</TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->quota %></TD>
+ </TR>
+% }
+% if ($svc_acct->slipip) {
+
+ <TR>
+ <TD ALIGN="right">IP address</TD>
+ <TD BGCOLOR="#ffffff">
+ <% ( $svc_acct->slipip eq "0.0.0.0" || $svc_acct->slipip eq '0e0' )
+ ? "<I>(Dynamic)</I>"
+ : $svc_acct->slipip
+ %>
+ </TD>
+ </TR>
+% }
+% my %ulabel = ( seconds => 'Time',
+% upbytes => 'Upload bytes',
+% downbytes => 'Download bytes',
+% totalbytes => 'Total bytes',
+% );
+% foreach my $uf ( keys %ulabel ) {
+% my $tf = $uf . "_threshold";
+% if ( $svc_acct->$uf ne '' ) {
+% my $v = $uf eq 'seconds'
+% #? (($svc_acct->$uf < 0 ? '-' : ''). duration_exact($svc_acct->$uf) )
+% ? ($svc_acct->$uf < 0 ? '-' : '').
+% int(abs($svc_acct->$uf)/3600). "hr ".
+% sprintf("%02d",(abs($svc_acct->$uf)%3600)/60). "min"
+% : FS::UI::bytecount::display_bytecount($svc_acct->$uf);
+ <TR>
+ <TD ALIGN="right"><% $ulabel{$uf} %> remaining</TD>
+ <TD BGCOLOR="#ffffff"><% $v %></TD>
+ </TR>
+
+% }
+% }
+% foreach my $attribute ( grep /^radius_/, $svc_acct->fields ) {
+% $attribute =~ /^radius_(.*)$/;
+% my $pattribute = $FS::raddb::attrib{$1};
+%
+
+ <TR>
+ <TD ALIGN="right">Radius (reply) <% $pattribute %></TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->getfield($attribute) %></TD>
+ </TR>
+% }
+% foreach my $attribute ( grep /^rc_/, $svc_acct->fields ) {
+% $attribute =~ /^rc_(.*)$/;
+% my $pattribute = $FS::raddb::attrib{$1};
+%
+
+ <TR>
+ <TD ALIGN="right">Radius (check) <% $pattribute %></TD>
+ <TD BGCOLOR="#ffffff"><% $svc_acct->getfield($attribute) %></TD>
+ </TR>
+% }
+
+
+<TR>
+ <TD ALIGN="right">RADIUS groups</TD>
+ <TD BGCOLOR="#ffffff"><% join('<BR>', $svc_acct->radius_groups) %></TD>
+</TR>
+%
+%# Can this be abstracted further? Maybe a library function like
+%# widget('HTML', 'view', $svc_acct) ? It would definitely make UI
+%# style management easier.
+%
+% foreach (sort { $a cmp $b } $svc_acct->virtual_fields) {
+
+ <% $svc_acct->pvf($_)->widget('HTML', 'view', $svc_acct->getfield($_)) %>
+% }
+
+
+</TABLE></TD></TR></TABLE>
+</FORM>
+<BR><BR>
+
+% if ( @svc_www ) {
+ Hosting
+ <% &ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+% foreach my $svc_www (@svc_www) {
+% my($label, $value) = $svc_www->cust_svc->label;
+% my $link = $p. 'view/svc_www.cgi?'. $svc_www->svcnum;
+ <TR>
+ <TD BGCOLOR="#ffffff">
+ <A HREF="<% $link %>"><% "$label: $value" %></A>
+ </TD>
+ </TR>
+% }
+ </TABLE></TD></TR></TABLE>
+ <BR><BR>
+% }
+
+<% join("<BR>", $conf->config('svc_acct-notes') ) %>
+<BR><BR>
+
+<% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my $conf = new FS::Conf;
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_acct = qsearchs({
+ 'select' => 'svc_acct.*',
+ 'table' => 'svc_acct',
+ 'addl_from' => $addl_from,
+ 'hashref' => { 'svcnum' => $svcnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ ),
+});
+die "Unknown svcnum" unless $svc_acct;
+
+#false laziness w/all svc_*.cgi
+my $cust_svc = qsearchs( 'cust_svc' , { 'svcnum' => $svcnum } );
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum);
+if ($pkgnum) {
+ $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+ $custnum = $cust_pkg->custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+#eofalse
+
+my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } );
+die "Unknown svcpart" unless $part_svc;
+my $svc = $part_svc->svc;
+
+die 'Empty domsvc for svc_acct.svcnum '. $svc_acct->svcnum
+ unless $svc_acct->domsvc;
+my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $svc_acct->domsvc } );
+die 'Unknown domain (domsvc '. $svc_acct->domsvc.
+ ' for svc_acct.svcnum '. $svc_acct->svcnum. ')'
+ unless $svc_domain;
+my $domain = $svc_domain->domain;
+
+my @svc_www = qsearch({
+ 'select' => 'svc_www.*',
+ 'table' => 'svc_www',
+ 'addl_from' => $addl_from,
+ 'hashref' => { 'usersvc' => $svcnum },
+ #XXX shit outta luck if you somehow got them linked across agents
+ # maybe we should show but not link to them? kinda makes sense...
+ # (maybe a specific ACL for this situation???)
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ ),
+});
+
+</%init>
diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi
new file mode 100644
index 000000000..145d34188
--- /dev/null
+++ b/httemplate/view/svc_broadband.cgi
@@ -0,0 +1,212 @@
+<%include("/elements/header.html",'Broadband Service View', menubar(
+ ( ( $custnum )
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ( "Cancel this (unaudited) website" =>
+ "${p}misc/cancel-unaudited.cgi?$svcnum" )
+ )
+))
+%>
+
+<A HREF="<%${p}%>edit/svc_broadband.cgi?<%$svcnum%>">Edit this information</A>
+<BR>
+<%ntable("#cccccc")%>
+ <TR>
+ <TD>
+ <%ntable("#cccccc",2)%>
+ <TR>
+ <TD ALIGN="right">Service number</TD>
+ <TD BGCOLOR="#ffffff"><%$svcnum%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Description</TD>
+ <TD BGCOLOR="#ffffff"><%$description%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Router</TD>
+ <TD BGCOLOR="#ffffff"><%$routernum%>: <%$routername%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Download Speed</TD>
+ <TD BGCOLOR="#ffffff"><%$speed_down%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Upload Speed</TD>
+ <TD BGCOLOR="#ffffff"><%$speed_up%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">IP Address</TD>
+ <TD BGCOLOR="#ffffff"><%$ip_addr%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">IP Netmask</TD>
+ <TD BGCOLOR="#ffffff"><%$ip_netmask%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">IP Gateway</TD>
+ <TD BGCOLOR="#ffffff"><%$ip_gateway%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">MAC Address</TD>
+ <TD BGCOLOR="#ffffff"><%$mac_addr%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Latitude</TD>
+ <TD BGCOLOR="#ffffff"><%$latitude%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Longitude</TD>
+ <TD BGCOLOR="#ffffff"><%$longitude%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Altitude</TD>
+ <TD BGCOLOR="#ffffff"><%$altitude%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">VLAN Profile</TD>
+ <TD BGCOLOR="#ffffff"><%$vlan_profile%></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Authentication Key</TD>
+ <TD BGCOLOR="#ffffff"><%$auth_key%></TD>
+ </TR>
+ <TR COLSPAN="2"><TD></TD></TR>
+%
+%foreach (sort { $a cmp $b } $svc_broadband->virtual_fields) {
+% print $svc_broadband->pvf($_)->widget('HTML', 'view',
+% $svc_broadband->getfield($_)), "\n";
+%}
+%
+%
+
+ </TABLE>
+ </TD>
+ </TR>
+</TABLE>
+
+<BR>
+<%ntable("#cccccc", 2)%>
+%
+% my $sb_router = qsearchs('router', { svcnum => $svcnum });
+% if ($sb_router) {
+%
+
+ <B>Router associated: <%$sb_router->routername%> </B>
+ <A HREF="<%popurl(2)%>edit/router.cgi?<%$sb_router->routernum%>">
+ (details)
+ </A>
+ <BR>
+% my @sb_addr_block;
+% if (@sb_addr_block = $sb_router->addr_block) {
+%
+
+ <B>Address space </B>
+ <A HREF="<%popurl(2)%>browse/addr_block.cgi">
+ (edit)
+ </A>
+ <BR>
+% print ntable("#cccccc", 1);
+% foreach (@sb_addr_block) {
+
+ <TR>
+ <TD><%$_->ip_gateway%>/<%$_->ip_netmask%></TD>
+ </TR>
+% }
+
+ </TABLE>
+% } else {
+
+ <B>No address space allocated.</B>
+% }
+
+ <BR>
+%
+% } else {
+%
+
+
+<FORM METHOD="GET" ACTION="<%popurl(2)%>edit/router.cgi">
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
+Add router named
+ <INPUT TYPE="text" NAME="routername" SIZE="32" VALUE="Broadband router (<%$svcnum%>)">
+ <INPUT TYPE="submit" VALUE="Add router">
+</FORM>
+%
+%}
+%
+
+
+<BR>
+<%joblisting({'svcnum'=>$svcnum}, 1)%>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_broadband = qsearchs({
+ 'select' => 'svc_broadband.*',
+ 'table' => 'svc_broadband',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'svcnum' => $svcnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+}) or die "svc_broadband: Unknown svcnum $svcnum";
+
+#false laziness w/all svc_*.cgi
+my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $svcnum } );
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum, $display_custnum);
+if ($pkgnum) {
+ $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+ $custnum = $cust_pkg->custnum;
+ $display_custnum = $cust_pkg->cust_main->display_custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+#eofalse
+
+my $addr_block = $svc_broadband->addr_block;
+my $router = $addr_block->router;
+
+if (not $router) { die "Could not lookup router for svc_broadband (svcnum $svcnum)" };
+
+my (
+ $routername,
+ $routernum,
+ $speed_down,
+ $speed_up,
+ $ip_addr,
+ $ip_gateway,
+ $ip_netmask,
+ $mac_addr,
+ $latitude,
+ $longitude,
+ $altitude,
+ $vlan_profile,
+ $auth_key,
+ $description,
+ ) = (
+ $router->getfield('routername'),
+ $router->getfield('routernum'),
+ $svc_broadband->getfield('speed_down'),
+ $svc_broadband->getfield('speed_up'),
+ $svc_broadband->getfield('ip_addr'),
+ $addr_block->ip_gateway,
+ $addr_block->NetAddr->mask,
+ $svc_broadband->mac_addr,
+ $svc_broadband->latitude,
+ $svc_broadband->longitude,
+ $svc_broadband->altitude,
+ $svc_broadband->vlan_profile,
+ $svc_broadband->auth_key,
+ $svc_broadband->description,
+ );
+
+</%init>
diff --git a/httemplate/view/svc_domain.cgi b/httemplate/view/svc_domain.cgi
new file mode 100755
index 000000000..8c1f4cecd
--- /dev/null
+++ b/httemplate/view/svc_domain.cgi
@@ -0,0 +1,161 @@
+<% include("/elements/header.html",'Domain View', menubar(
+ ( ( $pkgnum || $custnum )
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ( "Delete this (unaudited) domain" =>
+ "javascript:areyousure('${p}misc/cancel-unaudited.cgi?$svcnum', 'Delete $domain and all records?' )" )
+ )
+)) %>
+
+Service #<% $svcnum %>
+<BR>Service: <B><% $part_svc->svc %></B>
+<BR>Domain name: <B><% $domain %></B>
+% if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall') ) {
+ <BR>Catch all email <A HREF="<% ${p} %>misc/catchall.cgi?<% $svcnum %>">(change)</A>:
+% } else {
+ <BR>Catch all email:
+% }
+
+<% $email ? "<B>$email</B>" : "<I>(none)<I>" %>
+<BR><BR><A HREF="<% ${p} %>misc/whois.cgi?custnum=<%$custnum%>;svcnum=<%$svcnum%>;domain=<%$domain%>">View whois information.</A>
+<BR><BR>
+<SCRIPT>
+ function areyousure(href, message) {
+ if ( confirm(message) == true )
+ window.location.href = href;
+ }
+ function slave_areyousure() {
+ return confirm("Remove all records and slave from " + document.SlaveForm.recdata.value + "?");
+ }
+</SCRIPT>
+
+% my @records; if ( @records = $svc_domain->domain_record ) {
+
+ <% include('/elements/table-grid.html') %>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = $bgcolor2;
+
+ <tr>
+ <th CLASS="grid" BGCOLOR="#cccccc">Zone</th>
+ <th CLASS="grid" BGCOLOR="#cccccc">Type</th>
+ <th CLASS="grid" BGCOLOR="#cccccc">Data</th>
+ </tr>
+
+% foreach my $domain_record ( @records ) {
+% my $type = $domain_record->rectype eq '_mstr'
+% ? "(slave)"
+% : $domain_record->recaf. ' '. $domain_record->rectype;
+
+
+ <tr>
+ <td CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $domain_record->reczone %></td>
+ <td CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $type %></td>
+ <td CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $domain_record->recdata %>
+
+% unless ( $domain_record->rectype eq 'SOA'
+% || ! $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice')
+% ) {
+% ( my $recdata = $domain_record->recdata ) =~ s/"/\\'\\'/g;
+ (<A HREF="javascript:areyousure('<%$p%>misc/delete-domain_record.cgi?<%$domain_record->recnum%>', 'Delete \'<% $domain_record->reczone %> <% $type %> <% $recdata %>\' ?' )">delete</A>)
+% }
+ </td>
+ </tr>
+
+
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+% }
+
+ </table>
+% }
+
+% if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice') ) {
+ <BR>
+ <FORM METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
+ <INPUT TYPE="text" NAME="reczone">
+ <INPUT TYPE="hidden" NAME="recaf" VALUE="IN"> IN
+ <SELECT NAME="rectype">
+% foreach (qw( A NS CNAME MX PTR TXT) ) {
+ <OPTION VALUE="<%$_%>"><%$_%></OPTION>
+% }
+ </SELECT>
+ <INPUT TYPE="text" NAME="recdata">
+ <INPUT TYPE="submit" VALUE="Add record">
+ </FORM>
+
+ <BR><BR>
+ or
+ <BR><BR>
+
+ <FORM NAME="SlaveForm" METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
+% if ( @records ) {
+ Delete all records and
+% }
+ Slave from nameserver IP
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
+ <INPUT TYPE="hidden" NAME="reczone" VALUE="@">
+ <INPUT TYPE="hidden" NAME="recaf" VALUE="IN">
+ <INPUT TYPE="hidden" NAME="rectype" VALUE="_mstr">
+ <INPUT TYPE="text" NAME="recdata">
+ <INPUT TYPE="submit" VALUE="Slave domain" onClick="return slave_areyousure()">
+ </FORM>
+
+% }
+
+<BR><BR>
+
+<% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_domain = qsearchs({
+ 'select' => 'svc_domain.*',
+ 'table' => 'svc_domain',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => {'svcnum'=>$svcnum},
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Unknown svcnum" unless $svc_domain;
+
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum, $display_custnum);
+if ($pkgnum) {
+ $cust_pkg =qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ $custnum = $cust_pkg->custnum;
+ $custnum = $cust_pkg->cust_main->display_custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+
+my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } );
+die "Unknown svcpart" unless $part_svc;
+
+my $email = '';
+if ($svc_domain->catchall) {
+ my $svc_acct = qsearchs('svc_acct',{'svcnum'=> $svc_domain->catchall } );
+ die "Unknown svcpart" unless $svc_acct;
+ $email = $svc_acct->email;
+}
+
+my $domain = $svc_domain->domain;
+
+</%init>
diff --git a/httemplate/view/svc_external.cgi b/httemplate/view/svc_external.cgi
new file mode 100644
index 000000000..222f36a85
--- /dev/null
+++ b/httemplate/view/svc_external.cgi
@@ -0,0 +1,63 @@
+<% include("/elements/header.html",'External Service View', menubar(
+ ( ( $custnum )
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ( "Cancel this (unaudited) external service" =>
+ "${p}misc/cancel-unaudited.cgi?$svcnum" )
+ ),
+)) %>
+
+<A HREF="<%$p%>edit/svc_external.cgi?<%$svcnum%>">Edit this information</A><BR>
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+
+<TR><TD ALIGN="right">Service number</TD>
+ <TD BGCOLOR="#ffffff"><% $svcnum %></TD></TR>
+<TR><TD ALIGN="right"><% FS::Msgcat::_gettext('svc_external-id') || 'External&nbsp;ID' %></TD>
+ <TD BGCOLOR="#ffffff"><% $conf->config('svc_external-display_type') eq 'artera_turbo' ? sprintf('%010d', $svc_external->id) : $svc_external->id %></TD></TR>
+<TR><TD ALIGN="right"><% FS::Msgcat::_gettext('svc_external-title') || 'Title' %></TD>
+ <TD BGCOLOR="#ffffff"><% $svc_external->title %></TD></TR>
+% foreach (sort { $a cmp $b } $svc_external->virtual_fields) {
+
+ <% $svc_external->pvf($_)->widget('HTML', 'view', $svc_external->getfield($_)) %>
+% }
+
+
+</TABLE></TD></TR></TABLE>
+<BR><% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_external = qsearchs({
+ 'select' => 'svc_external.*',
+ 'table' => 'svc_external',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'svcnum' => $svcnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+}) or die "svc_external: Unknown svcnum $svcnum";
+
+my $conf = new FS::Conf;
+
+#false laziness w/all svc_*.cgi
+my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $svcnum } );
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum, $display_custnum);
+if ($pkgnum) {
+ $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+ $custnum = $cust_pkg->custnum;
+ $display_custnum = $cust_pkg->cust_main->display_custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+#eofalse
+
+</%init>
diff --git a/httemplate/view/svc_forward.cgi b/httemplate/view/svc_forward.cgi
new file mode 100755
index 000000000..ff84a282f
--- /dev/null
+++ b/httemplate/view/svc_forward.cgi
@@ -0,0 +1,105 @@
+<% include('/elements/header.html', 'Mail Forward View', menubar(
+ ( ( $pkgnum || $custnum )
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ( "Cancel this (unaudited) mail forward" =>
+ "${p}misc/cancel-unaudited.cgi?$svcnum" )
+ )
+))
+%>
+
+<A HREF="<% $p %>edit/svc_forward.cgi?<% $svcnum %>">Edit this information</A>
+
+<% ntable("#cccccc",2) %>
+
+ <TR>
+ <TD ALIGN="right">Service number</TD>
+ <TD BGCOLOR="#ffffff"><% $svcnum %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Service</TD>
+ <TD BGCOLOR="#ffffff"><% $svc %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Email to</TD>
+ <TD BGCOLOR="#ffffff"><% $source %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Forwards to </TD>
+ <TD BGCOLOR="#ffffff"><% $destination %></TD>
+ </TR>
+
+% foreach (sort { $a cmp $b } $svc_forward->virtual_fields) {
+ <% $svc_forward->pvf($_)->widget('HTML', 'view', $svc_forward->getfield($_)) %>
+% }
+
+</TABLE>
+
+<BR>
+<% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my $conf = new FS::Conf;
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_forward = qsearchs({
+ 'select' => 'svc_forward.*',
+ 'table' => 'svc_forward',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => {'svcnum'=>$svcnum},
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Unknown svcnum" unless $svc_forward;
+
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum, $display_custnum);
+if ($pkgnum) {
+ $cust_pkg=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
+ $custnum=$cust_pkg->getfield('custnum');
+ $display_custnum = $cust_pkg->cust_main->display_custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+
+my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } )
+ or die "Unknown svcpart";
+
+my($srcsvc,$dstsvc,$dst) = (
+ $svc_forward->srcsvc,
+ $svc_forward->dstsvc,
+ $svc_forward->dst,
+);
+my $src = $svc_forward->dbdef_table->column('src') ? $svc_forward->src : '';
+
+my $svc = $part_svc->svc;
+
+my $source;
+if ($srcsvc) {
+ my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$srcsvc})
+ or die "Corrupted database: no svc_acct.svcnum matching srcsvc $srcsvc";
+ $source = $svc_acct->email;
+} else {
+ $source = $src;
+}
+
+my $destination;
+if ($dstsvc) {
+ my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$dstsvc})
+ or die "Corrupted database: no svc_acct.svcnum matching dstsvc $dstsvc";
+ $destination = $svc_acct->email;
+} else {
+ $destination = $dst;
+}
+
+</%init>
diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi
new file mode 100644
index 000000000..f604daa47
--- /dev/null
+++ b/httemplate/view/svc_phone.cgi
@@ -0,0 +1,54 @@
+<% include('elements/svc_Common.html',
+ 'table' => 'svc_phone',
+ 'fields' => [qw(
+ countrycode
+ phonenum
+ sip_password
+ pin
+ phone_name
+ )],
+ 'labels' => {
+ 'countrycode' => 'Country code',
+ 'phonenum' => 'Phone number',
+ 'sip_password' => 'SIP password',
+ 'pin' => 'PIN',
+ 'phone_name' => 'Name',
+ },
+ 'html_foot' => $html_foot,
+ )
+%>
+<%init>
+
+my $html_foot = sub {
+ my $svc_phone = shift;
+
+ tie my %what, 'Tie::IxHash',
+ 'pending' => 'NULL',
+ 'billed' => 'done',
+ ;
+
+ #XXX src & charged party (& default prefix) as per voip_cdr.pm
+ #XXX handle toll free too
+
+ my $number = $svc_phone->phonenum;
+ $number = $svc_phone->countrycode. $number
+ unless $svc_phone->countrycode eq '1';
+
+ #my @links = map {
+ # qq(<A HREF="${p}search/cdr.html?src=$number;freesidestatus=$what{$_}">).
+ # "View $_ CDRs</A>";
+ #} keys(%what);
+ my @links = map {
+ qq(<A HREF="${p}search/cdr.html?cdrbatch=__ALL__;charged_party=$number;freesidestatus=$what{$_}">).
+ "View $_ CDRs</A>";
+ } keys(%what);
+
+ my @ilinks = ( qq(<A HREF="${p}search/cdr.html?dst=$number">).
+ 'View incoming CDRs</A>' );
+
+ join(' | ', @links ). '<BR>'.
+ join(' | ', @ilinks). '<BR>';
+
+};
+
+</%init>
diff --git a/httemplate/view/svc_www.cgi b/httemplate/view/svc_www.cgi
new file mode 100644
index 000000000..cb1a3bbdf
--- /dev/null
+++ b/httemplate/view/svc_www.cgi
@@ -0,0 +1,104 @@
+<% include("/elements/header.html", "Website View", menubar(
+ ( ( $custnum )
+ ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ : ( "Cancel this (unaudited) website" =>
+ "${p}misc/cancel-unaudited.cgi?$svcnum" )
+ ),
+ ))
+%>
+
+<A HREF="<% $p %>edit/svc_www.cgi?<% $svcnum %>">Edit this information</A><BR>
+
+<% ntable("#cccccc", 2) %>
+
+ <TR>
+ <TD ALIGN="right">Service number</TD>
+ <TD BGCOLOR="#ffffff"><% $svcnum %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right">Website name</TD>
+ <TD BGCOLOR="#ffffff"><A HREF="http://<% $www %>"><% $www %></A></TD>
+ </TR>
+
+% if ( $part_svc->part_svc_column('usersvc')->columnflag ne 'F'
+% || $part_svc->part_svc_column('usersvc')->columnvalue !~ /^\s*$/) {
+
+ <TR>
+ <TD ALIGN="right">Account</TD>
+ <TD BGCOLOR="#ffffff">
+% if ( $usersvc ) {
+ <A HREF="<% $p %>view/svc_acct.cgi?<% $usersvc %>"><% $email %></A>
+% } else {
+ </i>(none)</i>
+% }
+ </TD>
+ </TR>
+
+% }
+
+ <TR>
+ <TD ALIGN="right">Config lines</TD>
+ <TD BGCOLOR="#ffffff"><PRE><% join("\n", $svc_www->config) |h %></PRE></TD>
+ </TR>
+
+% foreach (sort { $a cmp $b } $svc_www->virtual_fields) {
+ <% $svc_www->pvf($_)->widget('HTML', 'view', $svc_www->getfield($_)) %>
+% }
+
+</TABLE>
+
+<BR>
+<% joblisting({'svcnum'=>$svcnum}, 1) %>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
+
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
+my $svc_www = qsearchs({
+ 'select' => 'svc_www.*',
+ 'table' => 'svc_www',
+ 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ',
+ 'hashref' => { 'svcnum' => $svcnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+}) or die "svc_www: Unknown svcnum $svcnum";
+
+#false laziness w/all svc_*.cgi
+my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $svcnum } );
+my $pkgnum = $cust_svc->getfield('pkgnum');
+my($cust_pkg, $custnum, $display_custnum);
+if ($pkgnum) {
+ $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $pkgnum } );
+ $custnum = $cust_pkg->custnum;
+ $display_custnum = $cust_pkg->cust_main->display_custnum;
+} else {
+ $cust_pkg = '';
+ $custnum = '';
+}
+#eofalse
+
+my $part_svc=qsearchs('part_svc',{'svcpart'=>$cust_svc->svcpart})
+ or die "svc_www: Unknown svcpart" . $cust_svc->svcpart;
+
+my $usersvc = $svc_www->usersvc;
+my $svc_acct = '';
+my $email = '';
+if ( $usersvc ) {
+ $svc_acct = qsearchs('svc_acct', { 'svcnum' => $usersvc } )
+ or die "svc_www: Unknown usersvc $usersvc";
+ $email = $svc_acct->email;
+}
+
+my $domain_record = qsearchs('domain_record', { 'recnum' => $svc_www->recnum } )
+ or die "svc_www: Unknown recnum ". $svc_www->recnum;
+
+my $www = $domain_record->zone;
+
+</%init>