From a7a6b7b22d88f4cff0bc3f1a307783c801655fc9 Mon Sep 17 00:00:00 2001
From: Karl Cordes
Date: Tue, 4 May 2010 16:49:57 +1000
Subject: [PATCH] Added Invoices, Jobs. Jobs not finished
---
controllers/invoices_controller.php | 99 ++
controllers/jobs_controller.php | 72 +
models/customer.php | 2 +-
models/enquiry.php | 8 +-
models/invoice.php | 45 +
models/job.php | 68 +
views/invoices/add.ctp | 25 +
views/invoices/edit.ctp | 27 +
views/invoices/index.ctp | 96 ++
views/invoices/view.ctp | 62 +
views/jobs/add.ctp | 28 +
views/jobs/edit.ctp | 30 +
views/jobs/index.ctp | 104 ++
views/jobs/view.ctp | 93 ++
webroot/js/ckeditor/_samples/api.html | 152 +++
webroot/js/ckeditor/_samples/fullpage.html | 62 +
.../js/ckeditor/_samples/jqueryadapter.html | 73 +
webroot/js/ckeditor/_samples/php/advanced.php | 93 ++
webroot/js/ckeditor/_samples/php/events.php | 130 ++
webroot/js/ckeditor/_samples/php/replace.php | 63 +
.../js/ckeditor/_samples/php/replaceall.php | 68 +
.../js/ckeditor/_samples/php/standalone.php | 64 +
.../js/ckeditor/_samples/sharedspaces.html | 131 ++
.../js/ckeditor/_source/adapters/jquery.js | 297 +++++
.../js/ckeditor/_source/core/dataprocessor.js | 66 +
.../js/ckeditor/_source/core/dom/comment.js | 32 +
webroot/js/ckeditor/_source/lang/cy.js | 699 ++++++++++
webroot/js/ckeditor/_source/lang/en-gb.js | 699 ++++++++++
.../plugins/a11yhelp/dialogs/a11yhelp.js | 211 +++
.../_source/plugins/a11yhelp/lang/en.js | 108 ++
.../_source/plugins/a11yhelp/plugin.js | 46 +
.../colordialog/dialogs/colordialog.js | 191 +++
.../_source/plugins/colordialog/plugin.js | 13 +
.../_source/plugins/div/dialogs/div.js | 535 ++++++++
.../js/ckeditor/_source/plugins/div/plugin.js | 121 ++
.../plugins/pastefromword/filter/default.js | 1179 +++++++++++++++++
.../_source/plugins/showborders/plugin.js | 170 +++
webroot/js/ckeditor/adapters/jquery.js | 6 +
webroot/js/ckeditor/ckeditor.php | 29 +
webroot/js/ckeditor/ckeditor_php4.php | 593 +++++++++
webroot/js/ckeditor/ckeditor_php5.php | 583 ++++++++
webroot/js/ckeditor/lang/cy.js | 6 +
webroot/js/ckeditor/lang/en-gb.js | 6 +
.../plugins/a11yhelp/dialogs/a11yhelp.js | 7 +
.../js/ckeditor/plugins/a11yhelp/lang/en.js | 6 +
.../colordialog/dialogs/colordialog.js | 6 +
.../js/ckeditor/plugins/div/dialogs/div.js | 7 +
.../plugins/pastefromword/filter/default.js | 10 +
webroot/js/costing_dialog.js | 21 +
webroot/js/editLineItem.js | 106 ++
webroot/js/enquiry_table.js | 71 +
51 files changed, 7415 insertions(+), 4 deletions(-)
create mode 100644 controllers/invoices_controller.php
create mode 100644 controllers/jobs_controller.php
create mode 100644 models/invoice.php
create mode 100644 models/job.php
create mode 100644 views/invoices/add.ctp
create mode 100644 views/invoices/edit.ctp
create mode 100644 views/invoices/index.ctp
create mode 100644 views/invoices/view.ctp
create mode 100644 views/jobs/add.ctp
create mode 100644 views/jobs/edit.ctp
create mode 100644 views/jobs/index.ctp
create mode 100644 views/jobs/view.ctp
create mode 100755 webroot/js/ckeditor/_samples/api.html
create mode 100755 webroot/js/ckeditor/_samples/fullpage.html
create mode 100755 webroot/js/ckeditor/_samples/jqueryadapter.html
create mode 100755 webroot/js/ckeditor/_samples/php/advanced.php
create mode 100755 webroot/js/ckeditor/_samples/php/events.php
create mode 100755 webroot/js/ckeditor/_samples/php/replace.php
create mode 100755 webroot/js/ckeditor/_samples/php/replaceall.php
create mode 100755 webroot/js/ckeditor/_samples/php/standalone.php
create mode 100755 webroot/js/ckeditor/_samples/sharedspaces.html
create mode 100755 webroot/js/ckeditor/_source/adapters/jquery.js
create mode 100755 webroot/js/ckeditor/_source/core/dataprocessor.js
create mode 100755 webroot/js/ckeditor/_source/core/dom/comment.js
create mode 100755 webroot/js/ckeditor/_source/lang/cy.js
create mode 100755 webroot/js/ckeditor/_source/lang/en-gb.js
create mode 100755 webroot/js/ckeditor/_source/plugins/a11yhelp/dialogs/a11yhelp.js
create mode 100755 webroot/js/ckeditor/_source/plugins/a11yhelp/lang/en.js
create mode 100755 webroot/js/ckeditor/_source/plugins/a11yhelp/plugin.js
create mode 100755 webroot/js/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js
create mode 100755 webroot/js/ckeditor/_source/plugins/colordialog/plugin.js
create mode 100755 webroot/js/ckeditor/_source/plugins/div/dialogs/div.js
create mode 100755 webroot/js/ckeditor/_source/plugins/div/plugin.js
create mode 100755 webroot/js/ckeditor/_source/plugins/pastefromword/filter/default.js
create mode 100755 webroot/js/ckeditor/_source/plugins/showborders/plugin.js
create mode 100755 webroot/js/ckeditor/adapters/jquery.js
create mode 100755 webroot/js/ckeditor/ckeditor.php
create mode 100755 webroot/js/ckeditor/ckeditor_php4.php
create mode 100755 webroot/js/ckeditor/ckeditor_php5.php
create mode 100755 webroot/js/ckeditor/lang/cy.js
create mode 100755 webroot/js/ckeditor/lang/en-gb.js
create mode 100755 webroot/js/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
create mode 100755 webroot/js/ckeditor/plugins/a11yhelp/lang/en.js
create mode 100755 webroot/js/ckeditor/plugins/colordialog/dialogs/colordialog.js
create mode 100755 webroot/js/ckeditor/plugins/div/dialogs/div.js
create mode 100755 webroot/js/ckeditor/plugins/pastefromword/filter/default.js
create mode 100644 webroot/js/costing_dialog.js
create mode 100644 webroot/js/editLineItem.js
create mode 100644 webroot/js/enquiry_table.js
diff --git a/controllers/invoices_controller.php b/controllers/invoices_controller.php
new file mode 100644
index 00000000..623d16e5
--- /dev/null
+++ b/controllers/invoices_controller.php
@@ -0,0 +1,99 @@
+ 100,
+ 'contain' => array('Customer')
+ );
+
+ function index() {
+ $this->Invoice->recursive = 0;
+ $this->set('invoices', $this->paginate());
+ }
+
+ function view($id = null) {
+ if (!$id) {
+ $this->Session->setFlash(__('Invalid Invoice.', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ $this->set('invoice', $this->Invoice->read(null, $id));
+ }
+
+
+
+ function add() {
+
+ if (!empty($this->data)) {
+ $this->Invoice->create();
+
+ $invoice_number_offset = 4500; //What Invoice number we are up to. Starting at 4500 due to the data loss.
+
+ $number_of_invoices = $this->Invoice->findCount();
+
+ $newInvoiceNumber = $invoice_number_offset + $number_of_invoices;
+
+ $this->data['Invoice']['title'] = "CMCIN".$newInvoiceNumber;
+
+ $enqid = $this->data['Invoice']['enquiry_id'];
+
+ if ($this->Invoice->save($this->data)) {
+ $this->Session->setFlash(__('The Invoice has been saved', true));
+ $this->redirect(array('controller'=>'enquiries', 'action'=>'view/'.$enqid));
+ } else {
+ $this->Session->setFlash(__('The Invoice could not be saved. Please, try again.', true));
+ }
+ }
+ else {
+ if(isset($this->params['named']['enquiryid'])) {
+ $enquiryid = $this->params['named']['enquiryid'];
+ $enquiry = $this->Invoice->Enquiry->findById($enquiryid);
+ $user = $this->Auth->user();
+ $this->set(compact('enquiry', 'user'));
+ }
+ else {
+ $this->Session->setFlash(__('Invalid Enquiry ID', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ }
+
+ }
+
+ function edit($id = null) {
+ if (!$id && empty($this->data)) {
+ $this->Session->setFlash(__('Invalid Invoice', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ if (!empty($this->data)) {
+ if ($this->Invoice->save($this->data)) {
+ $this->Session->setFlash(__('The Invoice has been saved', true));
+ $this->redirect(array('action'=>'index'));
+ } else {
+ $this->Session->setFlash(__('The Invoice could not be saved. Please, try again.', true));
+ }
+ }
+ if (empty($this->data)) {
+ $this->data = $this->Invoice->read(null, $id);
+ }
+ $enquiries = $this->Invoice->Enquiry->find('list');
+ $users = $this->Invoice->User->find('list');
+ $this->set(compact('enquiries','users'));
+ }
+
+ function delete($id = null) {
+ if (!$id) {
+ $this->Session->setFlash(__('Invalid id for Invoice', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ if ($this->Invoice->del($id)) {
+ $this->Session->setFlash(__('Invoice deleted', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/controllers/jobs_controller.php b/controllers/jobs_controller.php
new file mode 100644
index 00000000..d792bde6
--- /dev/null
+++ b/controllers/jobs_controller.php
@@ -0,0 +1,72 @@
+Job->recursive = 0;
+ $this->set('jobs', $this->paginate());
+ }
+
+ function view($id = null) {
+ if (!$id) {
+ $this->flash(__('Invalid Job', true), array('action'=>'index'));
+ }
+ $this->set('job', $this->Job->read(null, $id));
+ }
+
+ function add() {
+ if (!empty($this->data)) {
+ $this->Job->create();
+ if ($this->Job->save($this->data)) {
+ $this->flash(__('Job saved.', true), array('action'=>'index'));
+ } else {
+ }
+ }
+ else {
+ if(isset($this->params['named']['enquiryid'])) {
+
+ $enquiry = $this->Job->Enquiry->findById($this->params['named']['enquiryid']);
+
+ $this->set(compact('enquiry'));
+ }
+ else {
+ $this->Session->setFlash(__('Invalid Enquiry ID', true));
+ $this->redirect(array('action'=>'index'));
+ }
+ }
+
+ }
+
+ function edit($id = null) {
+ if (!$id && empty($this->data)) {
+ $this->flash(__('Invalid Job', true), array('action'=>'index'));
+ }
+ if (!empty($this->data)) {
+ if ($this->Job->save($this->data)) {
+ $this->flash(__('The Job has been saved.', true), array('action'=>'index'));
+ } else {
+ }
+ }
+ if (empty($this->data)) {
+ $this->data = $this->Job->read(null, $id);
+ }
+ $states = $this->Job->State->find('list');
+ $customers = $this->Job->Customer->find('list');
+ $enquiries = $this->Job->Enquiry->find('list');
+ $contacts = $this->Job->Contact->find('list');
+ $this->set(compact('states','customers','enquiries','contacts'));
+ }
+
+ function delete($id = null) {
+ if (!$id) {
+ $this->flash(__('Invalid Job', true), array('action'=>'index'));
+ }
+ if ($this->Job->del($id)) {
+ $this->flash(__('Job deleted', true), array('action'=>'index'));
+ }
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/models/customer.php b/models/customer.php
index 2f65774c..8afcc744 100755
--- a/models/customer.php
+++ b/models/customer.php
@@ -3,7 +3,7 @@ class Customer extends AppModel {
var $name = 'Customer';
- var $displayField = 'email';
+ var $displayField = 'name';
var $validate = array(
'name' => array(
diff --git a/models/enquiry.php b/models/enquiry.php
index 7fd34651..551225d9 100755
--- a/models/enquiry.php
+++ b/models/enquiry.php
@@ -178,7 +178,10 @@ class Enquiry extends AppModel {
'dependent' => false
),
'Invoice' => array('className' => 'Invoice',
- 'foreignKey'=>'enquiry_id')
+ 'foreignKey'=>'enquiry_id'),
+
+ 'Job' => array('className' => 'Job',
+ 'foreignKey' =>'enquiry_id')
/* 'EnquiryFile' => array('className' => 'EnquiryFile',
@@ -189,7 +192,6 @@ class Enquiry extends AppModel {
);
- var $hasOne = array('EnquiryEmailQueue');
-
+
}
?>
diff --git a/models/invoice.php b/models/invoice.php
new file mode 100644
index 00000000..4848ee91
--- /dev/null
+++ b/models/invoice.php
@@ -0,0 +1,45 @@
+ array('date'),
+ 'due_date' => array('date'),
+ 'title' => array('notempty'),
+ 'paid' => array('numeric'),
+ 'enquiry_id' => array('numeric'),
+ 'user_id' => array('numeric')
+ );
+
+ //The Associations below have been created with all possible keys, those that are not needed can be removed
+ var $belongsTo = array(
+ 'Enquiry' => array(
+ 'className' => 'Enquiry',
+ 'foreignKey' => 'enquiry_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => '',
+ 'counterCache'=>true
+ ),
+ 'User' => array(
+ 'className' => 'User',
+ 'foreignKey' => 'user_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ ),
+ 'Customer' => array(
+ 'className' => 'Customer',
+ 'foreignKey' => 'customer_id'
+ ),
+ 'Job' => array(
+ 'className' => 'Job',
+ 'foreignKey' => 'job_id'
+ )
+ );
+
+}
+?>
\ No newline at end of file
diff --git a/models/job.php b/models/job.php
new file mode 100644
index 00000000..adf0c7d1
--- /dev/null
+++ b/models/job.php
@@ -0,0 +1,68 @@
+ array('notempty'),
+ 'state_id' => array('numeric'),
+ 'customer_id' => array('numeric'),
+ 'enquiry_id' => array('numeric'),
+ 'contact_id' => array('numeric'),
+ 'date_order_received' => array('date'),
+ 'customer_order_number' => array('notempty'),
+ 'domestic_freight_paid_by' => array('notempty'),
+ 'sale_category' => array('notempty'),
+ 'shipment_category' => array('notempty')
+ );
+
+ //The Associations below have been created with all possible keys, those that are not needed can be removed
+ var $belongsTo = array(
+ 'State' => array(
+ 'className' => 'State',
+ 'foreignKey' => 'state_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ ),
+ 'Customer' => array(
+ 'className' => 'Customer',
+ 'foreignKey' => 'customer_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ ),
+ 'Enquiry' => array(
+ 'className' => 'Enquiry',
+ 'foreignKey' => 'enquiry_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => '',
+ 'counterCache' => true
+ ),
+ 'Contact' => array(
+ 'className' => 'Contact',
+ 'foreignKey' => 'contact_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ )
+ );
+
+ /*var $hasMany = array(
+ 'JobProduct' => array(
+ 'className' => 'JobProduct',
+ 'foreignKey' => 'job_id',
+ 'dependent' => false,
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => '',
+ 'limit' => '',
+ 'offset' => '',
+ 'exclusive' => '',
+ 'finderQuery' => '',
+ 'counterQuery' => ''
+ )
+ );*/
+
+}
+?>
\ No newline at end of file
diff --git a/views/invoices/add.ctp b/views/invoices/add.ctp
new file mode 100644
index 00000000..5d9e0c23
--- /dev/null
+++ b/views/invoices/add.ctp
@@ -0,0 +1,25 @@
+
+create('Invoice');?>
+
+
+ input('issue_date');
+ echo $form->input('due_date');
+
+
+ echo $form->input('enquiry_id', array('type'=>'hidden','value'=>$enquiry['Enquiry']['id']));
+ echo $form->input('user_id', array('type'=>'hidden','value'=>$user['User']['id']));
+ echo $form->input('customer_id', array('type'=>'hidden', 'value'=>$enquiry['Enquiry']['customer_id']));
+ ?>
+
+end('Submit');?>
+
+
+
+ link(__('List Invoices', true), array('action' => 'index'));?>
+ link(__('List Enquiries', true), array('controller' => 'enquiries', 'action' => 'index')); ?>
+ link(__('New Enquiry', true), array('controller' => 'enquiries', 'action' => 'add')); ?>
+ link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?>
+ link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?>
+
+
diff --git a/views/invoices/edit.ctp b/views/invoices/edit.ctp
new file mode 100644
index 00000000..6fa995f1
--- /dev/null
+++ b/views/invoices/edit.ctp
@@ -0,0 +1,27 @@
+
+create('Invoice');?>
+
+
+ input('id');
+ echo $form->input('issue_date');
+ echo $form->input('due_date');
+ echo $form->input('title');
+ echo $form->input('paid');
+ echo $form->input('payment_received_date');
+ echo $form->input('enquiry_id');
+ echo $form->input('user_id');
+ ?>
+
+end('Submit');?>
+
+
+
+ link(__('Delete', true), array('action' => 'delete', $form->value('Invoice.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $form->value('Invoice.id'))); ?>
+ link(__('List Invoices', true), array('action' => 'index'));?>
+ link(__('List Enquiries', true), array('controller' => 'enquiries', 'action' => 'index')); ?>
+ link(__('New Enquiry', true), array('controller' => 'enquiries', 'action' => 'add')); ?>
+ link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?>
+ link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?>
+
+
diff --git a/views/invoices/index.ctp b/views/invoices/index.ctp
new file mode 100644
index 00000000..4aaedb4f
--- /dev/null
+++ b/views/invoices/index.ctp
@@ -0,0 +1,96 @@
+
+
+
+ counter(array(
+ 'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
+ ));
+ ?>
+
+
+
+ sort('created');?>
+ sort('issue_date');?>
+ sort('due_date');?>
+ sort('Invoice Number');?>
+ sort('Customer'); ?>
+ sort('paid');?>
+ sort('payment_received_date');?>
+ sort('enquiry_id');?>
+ sort('user_id');?>
+
+
+
+ >
+
+
+ toUnix($invoice['Invoice']['created'])); ?>
+
+
+ toUnix($invoice['Invoice']['issue_date'])); ?>
+
+
+ toUnix($invoice['Invoice']['due_date'])); ?>
+
+
+
+
+
+
+
+
+ ";
+ echo " ";
+ echo "N/A";
+ echo " ";
+ }
+ else {
+ echo "PAID";
+ echo "";
+ echo "";
+ echo date('j M Y',$time->toUnix($invoice['Invoice']['payment_received_date']));
+ echo " ";
+ }
+
+
+
+ ?>
+
+
+
+ link($invoice['Enquiry']['title'], array('controller' => 'enquiries', 'action' => 'view', $invoice['Enquiry']['id'])); ?>
+
+
+ link($invoice['User']['username'], array('controller' => 'users', 'action' => 'view', $invoice['User']['id'])); ?>
+
+
+ link(__('View', true), array('action' => 'view', $invoice['Invoice']['id'])); ?>
+ link(__('Edit', true), array('action' => 'edit', $invoice['Invoice']['id'])); ?>
+ link(__('Delete', true), array('action' => 'delete', $invoice['Invoice']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $invoice['Invoice']['id'])); ?>
+
+
+
+
+
+
+ prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));?>
+ | numbers();?>
+ next(__('next', true).' >>', array(), null, array('class' => 'disabled'));?>
+
+
+
+ link(__('New Invoice', true), array('action' => 'add')); ?>
+
+
+
+
\ No newline at end of file
diff --git a/views/invoices/view.ctp b/views/invoices/view.ctp
new file mode 100644
index 00000000..393f6935
--- /dev/null
+++ b/views/invoices/view.ctp
@@ -0,0 +1,62 @@
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+ link($invoice['Enquiry']['title'], array('controller' => 'enquiries', 'action' => 'view', $invoice['Enquiry']['id'])); ?>
+
+
+ >
+ >
+ link($invoice['User']['username'], array('controller' => 'users', 'action' => 'view', $invoice['User']['id'])); ?>
+
+
+
+
+
+
+ link(__('Edit Invoice', true), array('action' => 'edit', $invoice['Invoice']['id'])); ?>
+ link(__('Delete Invoice', true), array('action' => 'delete', $invoice['Invoice']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $invoice['Invoice']['id'])); ?>
+ link(__('List Invoices', true), array('action' => 'index')); ?>
+ link(__('New Invoice', true), array('action' => 'add')); ?>
+ link(__('List Enquiries', true), array('controller' => 'enquiries', 'action' => 'index')); ?>
+ link(__('New Enquiry', true), array('controller' => 'enquiries', 'action' => 'add')); ?>
+ link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?>
+ link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?>
+
+
diff --git a/views/jobs/add.ctp b/views/jobs/add.ctp
new file mode 100644
index 00000000..c75cb46b
--- /dev/null
+++ b/views/jobs/add.ctp
@@ -0,0 +1,28 @@
+
+create('Job');?>
+
+
+ input('title');
+ echo $form->input('state_id');
+ echo $form->input('customer_id');
+ echo $form->input('enquiry_id');
+ echo $form->input('contact_id'); */
+ echo $form->input('comments');
+ echo $form->input('date_order_received');
+ echo $form->input('date_order_placed_on_principle');
+ echo $form->input('date_scheduled_ex_works');
+ echo $form->input('date_order_sent_to_customer');
+ echo $form->input('customer_order_number');
+ echo $form->input('domestic_freight_paid_by');
+ echo $form->input('sale_category');
+ echo $form->input('shipment_category');
+ ?>
+
+end('Submit');?>
+
+
+
+ link(__('List Jobs', true), array('action' => 'index'));?>
+
+
diff --git a/views/jobs/edit.ctp b/views/jobs/edit.ctp
new file mode 100644
index 00000000..f7a5422d
--- /dev/null
+++ b/views/jobs/edit.ctp
@@ -0,0 +1,30 @@
+
+create('Job');?>
+
+
+ input('id');
+ echo $form->input('title');
+ echo $form->input('state_id');
+ echo $form->input('customer_id');
+ echo $form->input('enquiry_id');
+ echo $form->input('contact_id');
+ echo $form->input('comments');
+ echo $form->input('date_order_received');
+ echo $form->input('date_order_placed_on_principle');
+ echo $form->input('date_scheduled_ex_works');
+ echo $form->input('date_order_sent_to_customer');
+ echo $form->input('customer_order_number');
+ echo $form->input('domestic_freight_paid_by');
+ echo $form->input('sale_category');
+ echo $form->input('shipment_category');
+ ?>
+
+end('Submit');?>
+
+
+
+ link(__('Delete', true), array('action' => 'delete', $form->value('Job.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $form->value('Job.id'))); ?>
+ link(__('List Jobs', true), array('action' => 'index'));?>
+
+
diff --git a/views/jobs/index.ctp b/views/jobs/index.ctp
new file mode 100644
index 00000000..93d6fbbe
--- /dev/null
+++ b/views/jobs/index.ctp
@@ -0,0 +1,104 @@
+
+
+
+counter(array(
+'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
+));
+?>
+
+
+ sort('id');?>
+ sort('created');?>
+ sort('title');?>
+ sort('state_id');?>
+ sort('customer_id');?>
+ sort('enquiry_id');?>
+ sort('contact_id');?>
+ sort('comments');?>
+ sort('date_order_received');?>
+ sort('date_order_placed_on_principle');?>
+ sort('date_scheduled_ex_works');?>
+ sort('date_order_sent_to_customer');?>
+ sort('customer_order_number');?>
+ sort('domestic_freight_paid_by');?>
+ sort('sale_category');?>
+ sort('shipment_category');?>
+
+
+
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link(__('View', true), array('action' => 'view', $job['Job']['id'])); ?>
+ link(__('Edit', true), array('action' => 'edit', $job['Job']['id'])); ?>
+ link(__('Delete', true), array('action' => 'delete', $job['Job']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $job['Job']['id'])); ?>
+
+
+
+
+
+
+ prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));?>
+ | numbers();?>
+ next(__('next', true).' >>', array(), null, array('class' => 'disabled'));?>
+
+
+
+ link(__('New Job', true), array('action' => 'add')); ?>
+
+
diff --git a/views/jobs/view.ctp b/views/jobs/view.ctp
new file mode 100644
index 00000000..785ea9f8
--- /dev/null
+++ b/views/jobs/view.ctp
@@ -0,0 +1,93 @@
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+ >
+ >
+
+
+
+
+
+
+
+ link(__('Edit Job', true), array('action' => 'edit', $job['Job']['id'])); ?>
+ link(__('Delete Job', true), array('action' => 'delete', $job['Job']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $job['Job']['id'])); ?>
+ link(__('List Jobs', true), array('action' => 'index')); ?>
+ link(__('New Job', true), array('action' => 'add')); ?>
+
+
diff --git a/webroot/js/ckeditor/_samples/api.html b/webroot/js/ckeditor/_samples/api.html
new file mode 100755
index 00000000..f853350c
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/api.html
@@ -0,0 +1,152 @@
+
+
+
+
+ API usage - CKEditor Sample
+
+
+
+
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/fullpage.html b/webroot/js/ckeditor/_samples/fullpage.html
new file mode 100755
index 00000000..bdd301e5
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/fullpage.html
@@ -0,0 +1,62 @@
+
+
+
+
+ Full Page Editing - CKEditor Sample
+
+
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ In this sample the editor is configured to edit entire HTML pages, from the <html>
+ tag to </html>.
+
+
+ Editor 1:
+ <html><head><title>CKEditor Sample</title></head><body><p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p></body></html>
+
+
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/jqueryadapter.html b/webroot/js/ckeditor/_samples/jqueryadapter.html
new file mode 100755
index 00000000..66bf9764
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/jqueryadapter.html
@@ -0,0 +1,73 @@
+
+
+
+
+ jQuery adapter - CKEditor Sample
+
+
+
+
+
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+
+
+ Editor 1:
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/php/advanced.php b/webroot/js/ckeditor/_samples/php/advanced.php
new file mode 100755
index 00000000..771cb0ca
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/php/advanced.php
@@ -0,0 +1,93 @@
+
+
+
+
+ Sample - CKEditor
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ Output
+
+
+ Editor 1:
+
+returnOutput = true;
+
+// Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+// $CKEditor->basePath = '/ckeditor/'
+// If not set, CKEditor will try to detect the correct path.
+$CKEditor->basePath = '../../';
+
+// Set global configuration (will be used by all instances of CKEditor).
+$CKEditor->config['width'] = 600;
+
+// Change default textarea attributes
+$CKEditor->textareaAttributes = array("cols" => 80, "rows" => 10);
+
+// The initial value to be displayed in the editor.
+$initialValue = 'This is some sample text . You are using CKEditor .
';
+
+// Create first instance.
+$code = $CKEditor->editor("editor1", $initialValue);
+
+echo $code;
+?>
+
+ Editor 2:
+
+editor("editor2", $initialValue, $config);
+?>
+
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/php/events.php b/webroot/js/ckeditor/_samples/php/events.php
new file mode 100755
index 00000000..36f2be27
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/php/events.php
@@ -0,0 +1,130 @@
+
+
+
+
+ Sample - CKEditor
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ Output
+
+
+ Editor 1:
+
+addGlobalEventHandler('dialogDefinition', $function);
+}
+
+/**
+ * Adds global event, will notify about opened dialog.
+ */
+function CKEditorNotifyAboutOpenedDialog(&$CKEditor) {
+ $function = 'function (evt) {
+ alert("Loading dialog: " + evt.data.name);
+ }';
+
+ $CKEditor->addGlobalEventHandler('dialogDefinition', $function);
+}
+
+// Include CKEditor class.
+include("../../ckeditor.php");
+
+// Create class instance.
+$CKEditor = new CKEditor();
+
+// Set configuration option for all editors.
+$CKEditor->config['width'] = 750;
+
+// Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+// $CKEditor->basePath = '/ckeditor/'
+// If not set, CKEditor will try to detect the correct path.
+$CKEditor->basePath = '../../';
+
+// The initial value to be displayed in the editor.
+$initialValue = 'This is some sample text . You are using CKEditor .
';
+
+// Event that will be handled only by the first editor.
+$CKEditor->addEventHandler('instanceReady', 'function (evt) {
+ alert("Loaded editor: " + evt.editor.name);
+}');
+
+// Create first instance.
+$CKEditor->editor("editor1", $initialValue);
+
+// Clear event handlers, instances that will be created later will not have
+// the 'instanceReady' listener defined a couple of lines above.
+$CKEditor->clearEventHandlers();
+?>
+
+ Editor 2:
+
+editor("editor2", $initialValue, $config, $events);
+?>
+
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/php/replace.php b/webroot/js/ckeditor/_samples/php/replace.php
new file mode 100755
index 00000000..80d813bd
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/php/replace.php
@@ -0,0 +1,63 @@
+
+
+
+
+ Sample - CKEditor
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ Output
+
+
+
+ Editor 1:
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+
+
+
+
+ basePath = '/ckeditor/'
+ // If not set, CKEditor will try to detect the correct path.
+ $CKEditor->basePath = '../../';
+ // Replace textarea with id (or name) "editor1".
+ $CKEditor->replace("editor1");
+ ?>
+
+
diff --git a/webroot/js/ckeditor/_samples/php/replaceall.php b/webroot/js/ckeditor/_samples/php/replaceall.php
new file mode 100755
index 00000000..38efc806
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/php/replaceall.php
@@ -0,0 +1,68 @@
+
+
+
+
+ Sample - CKEditor
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ Output
+
+
+
+ Editor 1:
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+ Editor 2:
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+
+
+
+
+ basePath = '/ckeditor/'
+ // If not set, CKEditor will try to detect the correct path.
+ $CKEditor->basePath = '../../';
+ // Replace all textareas with CKEditor.
+ $CKEditor->replaceAll();
+ ?>
+
+
diff --git a/webroot/js/ckeditor/_samples/php/standalone.php b/webroot/js/ckeditor/_samples/php/standalone.php
new file mode 100755
index 00000000..2a39ca16
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/php/standalone.php
@@ -0,0 +1,64 @@
+
+
+
+
+ Sample - CKEditor
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+ Output
+
+
+
+ Editor 1:
+
+
+ This is some sample text .
';
+ // Create class instance.
+ $CKEditor = new CKEditor();
+ // Path to CKEditor directory, ideally instead of relative dir, use an absolute path:
+ // $CKEditor->basePath = '/ckeditor/'
+ // If not set, CKEditor will try to detect the correct path.
+ $CKEditor->basePath = '../../';
+ // Create textarea element and attach CKEditor to it.
+ $CKEditor->editor("editor1", $initialValue);
+ ?>
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_samples/sharedspaces.html b/webroot/js/ckeditor/_samples/sharedspaces.html
new file mode 100755
index 00000000..7b32b9f9
--- /dev/null
+++ b/webroot/js/ckeditor/_samples/sharedspaces.html
@@ -0,0 +1,131 @@
+
+
+
+
+ Shared toolbars - CKEditor Sample
+
+
+
+
+
+
+
+
+ CKEditor Sample
+
+
+
+
+
+ CKEditor requires JavaScript to run . In a browser with no JavaScript
+ support, like yours, you should still see the contents (HTML data) and you should
+ be able to edit it normally, without a rich editor interface.
+
+
+
+
+
+
+
+
+ Editor 1 (uses the shared toolbar and element path):
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+ Editor 2 (uses the shared toolbar and element path):
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+ Editor 3 (uses the shared toolbar only):
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+ Editor 4 (no shared spaces):
+ <p>This is some <strong>sample text</strong>. You are using <a href="http://ckeditor.com/">CKEditor</a>.</p>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webroot/js/ckeditor/_source/adapters/jquery.js b/webroot/js/ckeditor/_source/adapters/jquery.js
new file mode 100755
index 00000000..e633758c
--- /dev/null
+++ b/webroot/js/ckeditor/_source/adapters/jquery.js
@@ -0,0 +1,297 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview jQuery adapter provides easy use of basic CKEditor functions
+ * and access to internal API. It also integrates some aspects of CKEditor with
+ * jQuery framework.
+ *
+ * Every TEXTAREA, DIV and P elements can be converted to working editor.
+ *
+ * Plugin exposes some of editor's event to jQuery event system. All of those are namespaces inside
+ * ".ckeditor" namespace and can be binded/listened on supported textarea, div and p nodes.
+ *
+ * Available jQuery events:
+ * - instanceReady.ckeditor( editor, rootNode )
+ * Triggered when new instance is ready.
+ * - destroy.ckeditor( editor )
+ * Triggered when instance is destroyed.
+ * - getData.ckeditor( editor, eventData )
+ * Triggered when getData event is fired inside editor. It can change returned data using eventData reference.
+ * - setData.ckeditor( editor )
+ * Triggered when getData event is fired inside editor.
+ *
+ * @example
+ *
+ *
+ *
+ */
+
+(function()
+{
+ /**
+ * Allow CKEditor to override jQuery.fn.val(). This results in ability to use val()
+ * function on textareas as usual and having those calls synchronized with CKEditor
+ * Rich Text Editor component.
+ *
+ * This config option is global and executed during plugin load.
+ * Can't be customized across editor instances.
+ *
+ * @type Boolean
+ * @example
+ * $( 'textarea' ).ckeditor();
+ * // ...
+ * $( 'textarea' ).val( 'New content' );
+ */
+ CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined'
+ ? true : CKEDITOR.config.jqueryOverrideVal;
+
+ var jQuery = window.jQuery;
+
+ if ( typeof jQuery == 'undefined' )
+ return;
+
+ // jQuery object methods.
+ jQuery.extend( jQuery.fn,
+ /** @lends jQuery.fn */
+ {
+ /**
+ * Return existing CKEditor instance for first matched element.
+ * Allows to easily use internal API. Doesn't return jQuery object.
+ *
+ * Raised exception if editor doesn't exist or isn't ready yet.
+ *
+ * @name jQuery.ckeditorGet
+ * @return CKEDITOR.editor
+ * @see CKEDITOR.editor
+ */
+ ckeditorGet: function()
+ {
+ var instance = this.eq( 0 ).data( 'ckeditorInstance' );
+ if ( !instance )
+ throw "CKEditor not yet initialized, use ckeditor() with callback.";
+ return instance;
+ },
+ /**
+ * Triggers creation of CKEditor in all matched elements (reduced to DIV, P and TEXTAREAs).
+ * Binds callback to instanceReady event of all instances. If editor is already created, than
+ * callback is fired right away.
+ *
+ * Mixed parameter order allowed.
+ *
+ * @param callback Function to be run on editor instance. Passed parameters: [ textarea ].
+ * Callback is fiered in "this" scope being ckeditor instance and having source textarea as first param.
+ *
+ * @param config Configuration options for new instance(s) if not already created.
+ * See URL
+ *
+ * @example
+ * $( 'textarea' ).ckeditor( function( textarea ) {
+ * $( textarea ).val( this.getData() )
+ * } );
+ *
+ * @name jQuery.fn.ckeditor
+ * @return jQuery.fn
+ */
+ ckeditor: function( callback, config )
+ {
+ if ( !jQuery.isFunction( callback ))
+ {
+ var tmp = config;
+ config = callback;
+ callback = tmp;
+ }
+ config = config || {};
+
+ this.filter( 'textarea, div, p' ).each( function()
+ {
+ var $element = jQuery( this ),
+ editor = $element.data( 'ckeditorInstance' ),
+ instanceLock = $element.data( '_ckeditorInstanceLock' ),
+ element = this;
+
+ if ( editor && !instanceLock )
+ {
+ if ( callback )
+ callback.apply( editor, [ this ] );
+ }
+ else if ( !instanceLock )
+ {
+ // CREATE NEW INSTANCE
+
+ // Handle config.autoUpdateElement inside this plugin if desired.
+ if ( config.autoUpdateElement
+ || ( typeof config.autoUpdateElement == 'undefined' && CKEDITOR.config.autoUpdateElement ) )
+ {
+ config.autoUpdateElementJquery = true;
+ }
+
+ // Always disable config.autoUpdateElement.
+ config.autoUpdateElement = false;
+ $element.data( '_ckeditorInstanceLock', true );
+
+ // Set instance reference in element's data.
+ editor = CKEDITOR.replace( element, config );
+ $element.data( 'ckeditorInstance', editor );
+
+ // Register callback.
+ editor.on( 'instanceReady', function( event )
+ {
+ var editor = event.editor;
+ setTimeout( function()
+ {
+ // Delay bit more if editor is still not ready.
+ if ( !editor.element )
+ {
+ setTimeout( arguments.callee, 100 );
+ return;
+ }
+
+ // Remove this listener.
+ event.removeListener( 'instanceReady', this.callee );
+
+ // Forward setData on dataReady.
+ editor.on( 'dataReady', function()
+ {
+ $element.trigger( 'setData' + '.ckeditor', [ editor ] );
+ });
+
+ // Forward getData.
+ editor.on( 'getData', function( event ) {
+ $element.trigger( 'getData' + '.ckeditor', [ editor, event.data ] );
+ }, 999 );
+
+ // Forward destroy event.
+ editor.on( 'destroy', function()
+ {
+ $element.trigger( 'destroy.ckeditor', [ editor ] );
+ });
+
+ // Integrate with form submit.
+ if ( editor.config.autoUpdateElementJquery && $element.is( 'textarea' ) && $element.parents( 'form' ).length )
+ {
+ var onSubmit = function()
+ {
+ $element.ckeditor( function()
+ {
+ editor.updateElement();
+ });
+ };
+
+ // Bind to submit event.
+ $element.parents( 'form' ).submit( onSubmit );
+
+ // Bind to form-pre-serialize from jQuery Forms plugin.
+ $element.parents( 'form' ).bind( 'form-pre-serialize', onSubmit );
+
+ // Unbind when editor destroyed.
+ $element.bind( 'destroy.ckeditor', function()
+ {
+ $element.parents( 'form' ).unbind( 'submit', onSubmit );
+ $element.parents( 'form' ).unbind( 'form-pre-serialize', onSubmit );
+ });
+ }
+
+ // Garbage collect on destroy.
+ editor.on( 'destroy', function()
+ {
+ $element.data( 'ckeditorInstance', null );
+ });
+
+ // Remove lock.
+ $element.data( '_ckeditorInstanceLock', null );
+
+ // Fire instanceReady event.
+ $element.trigger( 'instanceReady.ckeditor', [ editor ] );
+
+ // Run given (first) code.
+ if ( callback )
+ callback.apply( editor, [ element ] );
+ }, 0 );
+ }, null, null, 9999);
+ }
+ else
+ {
+ // Editor is already during creation process, bind our code to the event.
+ CKEDITOR.on( 'instanceReady', function( event )
+ {
+ var editor = event.editor;
+ setTimeout( function()
+ {
+ // Delay bit more if editor is still not ready.
+ if ( !editor.element )
+ {
+ setTimeout( arguments.callee, 100 );
+ return;
+ }
+
+ if ( editor.element.$ == element )
+ {
+ // Run given code.
+ if ( callback )
+ callback.apply( editor, [ element ] );
+ }
+ }, 0 );
+ }, null, null, 9999);
+ }
+ });
+ return this;
+ }
+ });
+
+ // New val() method for objects.
+ if ( CKEDITOR.config.jqueryOverrideVal )
+ {
+ jQuery.fn.val = CKEDITOR.tools.override( jQuery.fn.val, function( oldValMethod )
+ {
+ /**
+ * CKEditor-aware val() method.
+ *
+ * Acts same as original jQuery val(), but for textareas which have CKEditor instances binded to them, method
+ * returns editor's content. It also works for settings values.
+ *
+ * @param oldValMethod
+ * @name jQuery.fn.val
+ */
+ return function( newValue, forceNative )
+ {
+ var isSetter = typeof newValue != 'undefined',
+ result;
+
+ this.each( function()
+ {
+ var $this = jQuery( this ),
+ editor = $this.data( 'ckeditorInstance' );
+
+ if ( !forceNative && $this.is( 'textarea' ) && editor )
+ {
+ if ( isSetter )
+ editor.setData( newValue );
+ else
+ {
+ result = editor.getData();
+ // break;
+ return null;
+ }
+ }
+ else
+ {
+ if ( isSetter )
+ oldValMethod.call( $this, newValue );
+ else
+ {
+ result = oldValMethod.call( $this );
+ // break;
+ return null;
+ }
+ }
+
+ return true;
+ });
+ return isSetter ? this : result;
+ };
+ });
+ }
+})();
diff --git a/webroot/js/ckeditor/_source/core/dataprocessor.js b/webroot/js/ckeditor/_source/core/dataprocessor.js
new file mode 100755
index 00000000..cb8fcba2
--- /dev/null
+++ b/webroot/js/ckeditor/_source/core/dataprocessor.js
@@ -0,0 +1,66 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Defines the "virtual" {@link CKEDITOR.dataProcessor} class, which
+ * defines the basic structure of data processor objects to be
+ * set to {@link CKEDITOR.editor.dataProcessor}.
+ */
+
+/**
+ * If defined, points to the data processor which is responsible to translate
+ * and transform the editor data on input and output.
+ * Generaly it will point to an instance of {@link CKEDITOR.htmlDataProcessor},
+ * which handles HTML data. The editor may also handle other data formats by
+ * using different data processors provided by specific plugins.
+ * @name CKEDITOR.editor.dataProcessor
+ * @type CKEDITOR.dataProcessor
+ */
+
+/**
+ * Represents a data processor, which is responsible to translate and transform
+ * the editor data on input and output.
+ * This class is not really part of the API. It's here for documentation
+ * purposes, and serves as the base ("interface") for data processors
+ * implementation.
+ * @name CKEDITOR.dataProcessor
+ * @contructor
+ * @example
+ */
+
+/**
+ * Transforms input data into HTML to be loaded in the editor.
+ * While the editor is able to handle non HTML data (like BBCode), at runtime
+ * it can handle HTML data only. The role of the data processor is transforming
+ * the input data into HTML through this function.
+ * @name CKEDITOR.dataProcessor.prototype.toHtml
+ * @function
+ * @param {String} data The input data to be transformed.
+ * @param {String} [fixForBody] The tag name to be used if the data must be
+ * fixed because it is supposed to be loaded direcly into the <body>
+ * tag. This is generally not used by non-HTML data processors.
+ * @example
+ * // Tranforming BBCode data, having a custom BBCode data processor.
+ * var data = 'This is [b]an example[/b].';
+ * var html = editor.dataProcessor.toHtml( data ); // '<p>This is <b>an example</b>.</p>'
+ */
+
+/**
+ * Transforms HTML into data to be outputted by the editor, in the format
+ * expected by the data processor.
+ * While the editor is able to handle non HTML data (like BBCode), at runtime
+ * it can handle HTML data only. The role of the data processor is transforming
+ * the HTML data containined by the editor into a specific data format through
+ * this function.
+ * @name CKEDITOR.dataProcessor.prototype.toDataFormat
+ * @function
+ * @param {String} html The HTML to be transformed.
+ * @param {String} fixForBody The tag name to be used if the output data is
+ * coming from <body> and may be eventually fixed for it. This is
+ * generally not used by non-HTML data processors.
+ * // Tranforming into BBCode data, having a custom BBCode data processor.
+ * var html = '<p>This is <b>an example</b>.</p>';
+ * var data = editor.dataProcessor.toDataFormat( html ); // 'This is [b]an example[/b].'
+ */
diff --git a/webroot/js/ckeditor/_source/core/dom/comment.js b/webroot/js/ckeditor/_source/core/dom/comment.js
new file mode 100755
index 00000000..3daf537e
--- /dev/null
+++ b/webroot/js/ckeditor/_source/core/dom/comment.js
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Defines the {@link CKEDITOR.dom.comment} class, which represents
+ * a DOM comment node.
+ */
+
+CKEDITOR.dom.comment = CKEDITOR.tools.createClass(
+{
+ base : CKEDITOR.dom.node,
+
+ $ : function( text, ownerDocument )
+ {
+ if ( typeof text == 'string' )
+ text = ( ownerDocument ? ownerDocument.$ : document ).createComment( text );
+
+ this.base( text );
+ },
+
+ proto :
+ {
+ type : CKEDITOR.NODE_COMMENT,
+
+ getOuterHtml : function()
+ {
+ return '';
+ }
+ }
+});
diff --git a/webroot/js/ckeditor/_source/lang/cy.js b/webroot/js/ckeditor/_source/lang/cy.js
new file mode 100755
index 00000000..18dbf66a
--- /dev/null
+++ b/webroot/js/ckeditor/_source/lang/cy.js
@@ -0,0 +1,699 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Defines the {@link CKEDITOR.lang} object, for the
+ * Welsh language.
+ */
+
+/**#@+
+ @type String
+ @example
+*/
+
+/**
+ * Constains the dictionary of language entries.
+ * @namespace
+ */
+CKEDITOR.lang['cy'] =
+{
+ /**
+ * The language reading direction. Possible values are "rtl" for
+ * Right-To-Left languages (like Arabic) and "ltr" for Left-To-Right
+ * languages (like English).
+ * @default 'ltr'
+ */
+ dir : 'ltr',
+
+ /*
+ * Screenreader titles. Please note that screenreaders are not always capable
+ * of reading non-English words. So be careful while translating it.
+ */
+ editorTitle : 'Rich text editor, %1, press ALT 0 for help.', // MISSING
+
+ // ARIA descriptions.
+ toolbar : 'Toolbar', // MISSING
+ editor : 'Rich Text Editor', // MISSING
+
+ // Toolbar buttons without dialogs.
+ source : 'Tarddle',
+ newPage : 'Tudalen newydd',
+ save : 'Cadw',
+ preview : 'Rhagolwg',
+ cut : 'Torri',
+ copy : 'Copïo',
+ paste : 'Gludo',
+ print : 'Argraffu',
+ underline : 'Tanlinellu',
+ bold : 'Bras',
+ italic : 'Italig',
+ selectAll : 'Dewis Popeth',
+ removeFormat : 'Tynnu Fformat',
+ strike : 'Llinell Trwyddo',
+ subscript : 'Is-sgript',
+ superscript : 'Uwchsgript',
+ horizontalrule : 'Mewnosod Llinell Lorweddol',
+ pagebreak : 'Mewnosod Toriad Tudalen i Argraffu',
+ unlink : 'Datgysylltu',
+ undo : 'Dadwneud',
+ redo : 'Ailadrodd',
+
+ // Common messages and labels.
+ common :
+ {
+ browseServer : 'Pori\'r Gweinydd',
+ url : 'URL',
+ protocol : 'Protocol',
+ upload : 'Lanlwytho',
+ uploadSubmit : 'Anfon i\'r Gweinydd',
+ image : 'Delwedd',
+ flash : 'Flash',
+ form : 'Ffurflen',
+ checkbox : 'Blwch ticio',
+ radio : 'Botwm Radio',
+ textField : 'Maes Testun',
+ textarea : 'Ardal Testun',
+ hiddenField : 'Maes Cudd',
+ button : 'Botwm',
+ select : 'Maes Dewis',
+ imageButton : 'Botwm Delwedd',
+ notSet : '',
+ id : 'Id',
+ name : 'Name',
+ langDir : 'Cyfeiriad Iaith',
+ langDirLtr : 'Chwith i\'r Dde (LTR)',
+ langDirRtl : 'Dde i\'r Chwith (RTL)',
+ langCode : 'Cod Iaith',
+ longDescr : 'URL Disgrifiad Hir',
+ cssClass : 'Dosbarth Dalen Arddull',
+ advisoryTitle : 'Teitl Cynghorol',
+ cssStyle : 'Arddull',
+ ok : 'Iawn',
+ cancel : 'Diddymu',
+ close : 'Close', // MISSING
+ preview : 'Preview', // MISSING
+ generalTab : 'Cyffredinol',
+ advancedTab : 'Uwch',
+ validateNumberFailed : 'Nid yw\'r gwerth hwn yn rhif.',
+ confirmNewPage : 'Byddwch yn colli unrhyw newidiadau i\'r cynnwys sydd heb eu cadw. A ydych am barhau i lwytho tudalen newydd?',
+ confirmCancel : 'Mae rhai o\'r opsiynau wedi\'u newid. A ydych wir am gau\'r deialog?',
+ options : 'Options', // MISSING
+ target : 'Target', // MISSING
+ targetNew : 'New Window (_blank)', // MISSING
+ targetTop : 'Topmost Window (_top)', // MISSING
+ targetSelf : 'Same Window (_self)', // MISSING
+ targetParent : 'Parent Window (_parent)', // MISSING
+
+ // Put the voice-only part of the label in the span.
+ unavailable : '%1, ddim ar gael '
+ },
+
+ // Special char dialog.
+ specialChar :
+ {
+ toolbar : 'Mewnosod Nodau Arbennig',
+ title : 'Dewis Nod Arbennig'
+ },
+
+ // Link dialog.
+ link :
+ {
+ toolbar : 'Dolen',
+ menu : 'Golygu Dolen',
+ title : 'Dolen',
+ info : 'Gwyb ar y Ddolen',
+ target : 'Targed',
+ upload : 'Lanlwytho',
+ advanced : 'Uwch',
+ type : 'Math y Ddolen',
+ toUrl : 'URL', // MISSING
+ toAnchor : 'Dolen at angor yn y testun',
+ toEmail : 'E-bost',
+ targetFrame : '',
+ targetPopup : '',
+ targetFrameName : 'Enw Ffrâm y Targed',
+ targetPopupName : 'Enw Ffenestr Bop',
+ popupFeatures : 'Nodweddion Ffenestr Bop',
+ popupResizable : 'Ailfeintiol',
+ popupStatusBar : 'Bar Statws',
+ popupLocationBar: 'Bar Safle',
+ popupToolbar : 'Bar Offer',
+ popupMenuBar : 'Dewislen',
+ popupFullScreen : 'Sgrin Llawn (IE)',
+ popupScrollBars : 'Barrau Sgrolio',
+ popupDependent : 'Dibynnol (Netscape)',
+ popupWidth : 'Lled',
+ popupLeft : 'Safle Chwith',
+ popupHeight : 'Uchder',
+ popupTop : 'Safle Top',
+ id : 'Id',
+ langDir : 'Cyfeiriad Iaith',
+ langDirLTR : 'Chwith i\'r Dde (LTR)',
+ langDirRTL : 'Dde i\'r Chwith (RTL)',
+ acccessKey : 'Allwedd Mynediad',
+ name : 'Enw',
+ langCode : 'Cod Iaith',
+ tabIndex : 'Indecs Tab',
+ advisoryTitle : 'Teitl Cynghorol',
+ advisoryContentType : 'Math y Cynnwys Cynghorol',
+ cssClasses : 'Dosbarthiadau Dalen Arddull',
+ charset : 'Set nodau\'r Adnodd Cysylltiedig',
+ styles : 'Arddull',
+ selectAnchor : 'Dewiswch Angor',
+ anchorName : 'Gan Enw\'r Angor',
+ anchorId : 'Gan Id yr Elfen',
+ emailAddress : 'Cyfeiriad E-Bost',
+ emailSubject : 'Testun y Message Subject',
+ emailBody : 'Pwnc y Neges',
+ noAnchors : '(Dim angorau ar gael yn y ddogfen)',
+ noUrl : 'Teipiwch URL y ddolen',
+ noEmail : 'Teipiwch gyfeiriad yr e-bost'
+ },
+
+ // Anchor dialog
+ anchor :
+ {
+ toolbar : 'Angor',
+ menu : 'Golygwch yr Angor',
+ title : 'Priodweddau\'r Angor',
+ name : 'Enw\'r Angor',
+ errorName : 'Teipiwch enw\'r angor'
+ },
+
+ // Find And Replace Dialog
+ findAndReplace :
+ {
+ title : 'Chwilio ac Amnewid',
+ find : 'Chwilio',
+ replace : 'Amnewid',
+ findWhat : 'Chwilio\'r term:',
+ replaceWith : 'Amnewid gyda:',
+ notFoundMsg : 'Nid oedd y testun wedi\'i ddarganfod.',
+ matchCase : 'Cyfateb i\'r cas',
+ matchWord : 'Cyfateb gair cyfan',
+ matchCyclic : 'Cyfateb cylchol',
+ replaceAll : 'Amnewid pob un',
+ replaceSuccessMsg : 'Amnewidiwyd %1 achlysur.'
+ },
+
+ // Table Dialog
+ table :
+ {
+ toolbar : 'Tabl',
+ title : 'Nodweddion Tabl',
+ menu : 'Nodweddion Tabl',
+ deleteTable : 'Dileu Tabl',
+ rows : 'Rhesi',
+ columns : 'Colofnau',
+ border : 'Maint yr Ymyl',
+ align : 'Aliniad',
+ alignLeft : 'Chwith',
+ alignCenter : 'Canol',
+ alignRight : 'Dde',
+ width : 'Lled',
+ widthPx : 'picsel',
+ widthPc : 'y cant',
+ widthUnit : 'width unit', // MISSING
+ height : 'Uchder',
+ cellSpace : 'Bylchu\'r gell',
+ cellPad : 'Padio\'r gell',
+ caption : 'Pennawd',
+ summary : 'Crynodeb',
+ headers : 'Penynnau',
+ headersNone : 'Dim',
+ headersColumn : 'Colofn gyntaf',
+ headersRow : 'Rhes gyntaf',
+ headersBoth : 'Y Ddau',
+ invalidRows : 'Mae\'n rhaid cael o leiaf un rhes.',
+ invalidCols : 'Mae\'n rhaid cael o leiaf un golofn.',
+ invalidBorder : 'Mae\'n rhaid i faint yr ymyl fod yn rhif.',
+ invalidWidth : 'Mae\'n rhaid i led y tabl fod yn rhif.',
+ invalidHeight : 'Mae\'n rhaid i uchder y tabl fod yn rhif.',
+ invalidCellSpacing : 'Mae\'n rhaid i fylchiad y gell fod yn rhif.',
+ invalidCellPadding : 'Mae\'n rhaid i badiad y gell fod yn rhif.',
+
+ cell :
+ {
+ menu : 'Cell',
+ insertBefore : 'Mewnosod Cell Cyn',
+ insertAfter : 'Mewnosod Cell Ar Ôl',
+ deleteCell : 'Dileu Celloedd',
+ merge : 'Cyfuno Celloedd',
+ mergeRight : 'Cyfuno i\'r Dde',
+ mergeDown : 'Cyfuno i Lawr',
+ splitHorizontal : 'Hollti\'r Gell yn Lorweddol',
+ splitVertical : 'Hollti\'r Gell yn Fertigol',
+ title : 'Priodweddau\'r Gell',
+ cellType : 'Math y Gell',
+ rowSpan : 'Rhychwant Rhesi',
+ colSpan : 'Rhychwant Colofnau',
+ wordWrap : 'Lapio Geiriau',
+ hAlign : 'Aliniad Llorweddol',
+ vAlign : 'Aliniad Fertigol',
+ alignTop : 'Top',
+ alignMiddle : 'Canol',
+ alignBottom : 'Gwaelod',
+ alignBaseline : 'Baslinell',
+ bgColor : 'Lliw Cefndir',
+ borderColor : 'Lliw Ymyl',
+ data : 'Data',
+ header : 'Pennyn',
+ yes : 'Ie',
+ no : 'Na',
+ invalidWidth : 'Mae\'n rhaid i led y gell fod yn rhif.',
+ invalidHeight : 'Mae\'n rhaid i uchder y gell fod yn rhif.',
+ invalidRowSpan : 'Mae\'n rhaid i rychwant y rhesi fod yn gyfanrif.',
+ invalidColSpan : 'Mae\'n rhaid i rychwant y colofnau fod yn gyfanrif.',
+ chooseColor : 'Choose'
+ },
+
+ row :
+ {
+ menu : 'Rhes',
+ insertBefore : 'Mewnosod Rhes Cyn',
+ insertAfter : 'Mewnosod Rhes Ar Ôl',
+ deleteRow : 'Dileu Rhesi'
+ },
+
+ column :
+ {
+ menu : 'Colofn',
+ insertBefore : 'Mewnosod Colofn Cyn',
+ insertAfter : 'Mewnosod Colofn Ar Ôl',
+ deleteColumn : 'Dileu Colofnau'
+ }
+ },
+
+ // Button Dialog.
+ button :
+ {
+ title : 'Priodweddau Botymau',
+ text : 'Testun (Gwerth)',
+ type : 'Math',
+ typeBtn : 'Botwm',
+ typeSbm : 'Gyrru',
+ typeRst : 'Ailosod'
+ },
+
+ // Checkbox and Radio Button Dialogs.
+ checkboxAndRadio :
+ {
+ checkboxTitle : 'Priodweddau Blwch Ticio',
+ radioTitle : 'Priodweddau Botwm Radio',
+ value : 'Gwerth',
+ selected : 'Dewiswyd'
+ },
+
+ // Form Dialog.
+ form :
+ {
+ title : 'Priodweddau Ffurflen',
+ menu : 'Priodweddau Ffurflen',
+ action : 'Gweithred',
+ method : 'Dull',
+ encoding : 'Amgodio'
+ },
+
+ // Select Field Dialog.
+ select :
+ {
+ title : 'Priodweddau Maes Dewis',
+ selectInfo : 'Gwyb Dewis',
+ opAvail : 'Opsiynau ar Gael',
+ value : 'Gwerth',
+ size : 'Maint',
+ lines : 'llinellau',
+ chkMulti : 'Caniatàu aml-ddewisiadau',
+ opText : 'Testun',
+ opValue : 'Gwerth',
+ btnAdd : 'Ychwanegu',
+ btnModify : 'Newid',
+ btnUp : 'Lan',
+ btnDown : 'Lawr',
+ btnSetValue : 'Gosod fel gwerth a ddewiswyd',
+ btnDelete : 'Dileu'
+ },
+
+ // Textarea Dialog.
+ textarea :
+ {
+ title : 'Priodweddau Ardal Testun',
+ cols : 'Colofnau',
+ rows : 'Rhesi'
+ },
+
+ // Text Field Dialog.
+ textfield :
+ {
+ title : 'Priodweddau Maes Testun',
+ name : 'Enw',
+ value : 'Gwerth',
+ charWidth : 'Lled Nod',
+ maxChars : 'Uchafswm y Nodau',
+ type : 'Math',
+ typeText : 'Testun',
+ typePass : 'Cyfrinair'
+ },
+
+ // Hidden Field Dialog.
+ hidden :
+ {
+ title : 'Priodweddau Maes Cudd',
+ name : 'Enw',
+ value : 'Gwerth'
+ },
+
+ // Image Dialog.
+ image :
+ {
+ title : 'Priodweddau Delwedd',
+ titleButton : 'Priodweddau Botwm Delwedd',
+ menu : 'Priodweddau Delwedd',
+ infoTab : 'Gwyb Delwedd',
+ btnUpload : 'Anfon i\'r Gweinydd',
+ upload : 'lanlwytho',
+ alt : 'Testun Amgen',
+ width : 'Lled',
+ height : 'Uchder',
+ lockRatio : 'Cloi Cymhareb',
+ unlockRatio : 'Unlock Ratio', // MISSING
+ resetSize : 'Ailosod Maint',
+ border : 'Ymyl',
+ hSpace : 'BwlchLl',
+ vSpace : 'BwlchF',
+ align : 'Alinio',
+ alignLeft : 'Chwith',
+ alignRight : 'Dde',
+ alertUrl : 'Rhowch URL y ddelwedd',
+ linkTab : 'Dolen',
+ button2Img : 'Ydych am drawsffurfio\'r botwm ddelwedd hwn ar ddelwedd syml?',
+ img2Button : 'Ydych am drawsffurfio\'r ddelwedd hon ar fotwm delwedd?',
+ urlMissing : 'URL tarddle\'r ddelwedd ar goll.',
+ validateWidth : 'Width must be a whole number.', // MISSING
+ validateHeight : 'Height must be a whole number.', // MISSING
+ validateBorder : 'Border must be a whole number.', // MISSING
+ validateHSpace : 'HSpace must be a whole number.', // MISSING
+ validateVSpace : 'VSpace must be a whole number.' // MISSING
+ },
+
+ // Flash Dialog
+ flash :
+ {
+ properties : 'Priodweddau Flash',
+ propertiesTab : 'Priodweddau',
+ title : 'Priodweddau Flash',
+ chkPlay : 'AwtoChwarae',
+ chkLoop : 'Lwpio',
+ chkMenu : 'Galluogi Dewislen Flash',
+ chkFull : 'Caniatàu Sgrin Llawn',
+ scale : 'Graddfa',
+ scaleAll : 'Dangos pob',
+ scaleNoBorder : 'Dim Ymyl',
+ scaleFit : 'Ffit Union',
+ access : 'Mynediad Sgript',
+ accessAlways : 'Pob amser',
+ accessSameDomain: 'R\'un parth',
+ accessNever : 'Byth',
+ align : 'Alinio',
+ alignLeft : 'Chwith',
+ alignAbsBottom : 'Gwaelod Abs',
+ alignAbsMiddle : 'Canol Abs',
+ alignBaseline : 'Baslinell',
+ alignBottom : 'Gwaelod',
+ alignMiddle : 'Canol',
+ alignRight : 'Dde',
+ alignTextTop : 'Testun Top',
+ alignTop : 'Top',
+ quality : 'Ansawdd',
+ qualityBest : 'Gorau',
+ qualityHigh : 'Uchel',
+ qualityAutoHigh : 'Uchel Awto',
+ qualityMedium : 'Canolig',
+ qualityAutoLow : 'Isel Awto',
+ qualityLow : 'Isel',
+ windowModeWindow: 'Ffenestr',
+ windowModeOpaque: 'Afloyw',
+ windowModeTransparent : 'Tryloyw',
+ windowMode : 'Modd ffenestr',
+ flashvars : 'Newidynnau ar gyfer Flash',
+ bgcolor : 'Lliw cefndir',
+ width : 'Lled',
+ height : 'Uchder',
+ hSpace : 'BwlchLl',
+ vSpace : 'BwlchF',
+ validateSrc : 'Ni all yr URL fod yn wag.',
+ validateWidth : 'Rhaid i\'r Lled fod yn rhif.',
+ validateHeight : 'Rhaid i\'r Uchder fod yn rhif.',
+ validateHSpace : 'Rhaid i\'r BwlchLl fod yn rhif.',
+ validateVSpace : 'Rhaid i\'r BwlchF fod yn rhif.'
+ },
+
+ // Speller Pages Dialog
+ spellCheck :
+ {
+ toolbar : 'Gwirio Sillafu',
+ title : 'Gwirio Sillafu',
+ notAvailable : 'Nid yw\'r gwasanaeth hwn ar gael yn bresennol.',
+ errorLoading : 'Error loading application service host: %s.',
+ notInDic : 'Nid i\'w gael yn y geiriadur',
+ changeTo : 'Newid i',
+ btnIgnore : 'Anwybyddu Un',
+ btnIgnoreAll : 'Anwybyddu Pob',
+ btnReplace : 'Amnewid Un',
+ btnReplaceAll : 'Amnewid Pob',
+ btnUndo : 'Dadwneud',
+ noSuggestions : '- Dim awgrymiadau -',
+ progress : 'Gwirio sillafu yn ar y gweill...',
+ noMispell : 'Gwirio sillafu wedi gorffen: Dim camsillaf.',
+ noChanges : 'Gwirio sillafu wedi gorffen: Dim newidiadau',
+ oneChange : 'Gwirio sillafu wedi gorffen: Newidiwyd 1 gair',
+ manyChanges : 'Gwirio sillafu wedi gorffen: Newidiwyd %1 gair',
+ ieSpellDownload : 'Gwirydd sillafu heb ei arsefydlu. A ydych am ei lawrlwytho nawr?'
+ },
+
+ smiley :
+ {
+ toolbar : 'Gwenoglun',
+ title : 'Mewnosod Gwenoglun'
+ },
+
+ elementsPath :
+ {
+ eleLabel : 'Elements path', // MISSING
+ eleTitle : 'Elfen %1'
+ },
+
+ numberedlist : 'Mewnosod/Tynnu Rhestr Rhifol',
+ bulletedlist : 'Mewnosod/Tynnu Rhestr Bwled',
+ indent : 'Cynyddu\'r Mewnoliad',
+ outdent : 'Lleihau\'r Mewnoliad',
+
+ justify :
+ {
+ left : 'Alinio i\'r Chwith',
+ center : 'Alinio i\'r Canol',
+ right : 'Alinio i\'r Dde',
+ block : 'Aliniad Bloc'
+ },
+
+ blockquote : 'Dyfyniad bloc',
+
+ clipboard :
+ {
+ title : 'Gludo',
+ cutError : 'Nid yw gosodiadau diogelwch eich porwr yn caniatàu\'r golygydd i gynnal \'gweithredoedd torri\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl+X).',
+ copyError : 'Nid yw gosodiadau diogelwch eich porwr yn caniatàu\'r golygydd i gynnal \'gweithredoedd copïo\' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl+C).',
+ pasteMsg : 'Gludwch i mewn i\'r blwch canlynol gan ddefnyddio\'r bysellfwrdd (Ctrl+V ) a phwyso Iawn .',
+ securityMsg : 'Oherwydd gosodiadau diogelwch eich porwr, nid yw\'r porwr yn gallu ennill mynediad i\'r data ar y clipfwrdd yn uniongyrchol. Mae angen i chi ei ludo eto i\'r ffenestr hon.',
+ pasteArea : 'Paste Area' // MISSING
+ },
+
+ pastefromword :
+ {
+ confirmCleanup : 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
+ toolbar : 'Gludo o Word',
+ title : 'Gludo o Word',
+ error : 'It was not possible to clean up the pasted data due to an internal error' // MISSING
+ },
+
+ pasteText :
+ {
+ button : 'Gludo fel testun plaen',
+ title : 'Gludo fel Testun Plaen'
+ },
+
+ templates :
+ {
+ button : 'Templedi',
+ title : 'Templedi Cynnwys',
+ insertOption : 'Amnewid y cynnwys go iawn',
+ selectPromptMsg : 'Dewiswch dempled i\'w agor yn y golygydd',
+ emptyListMsg : '(Dim templedi wedi\'u diffinio)'
+ },
+
+ showBlocks : 'Dangos Blociau',
+
+ stylesCombo :
+ {
+ label : 'Arddulliau',
+ panelTitle : 'Formatting Styles', // MISSING
+ panelTitle1 : 'Arddulliau Bloc',
+ panelTitle2 : 'Arddulliau Mewnol',
+ panelTitle3 : 'Arddulliau Gwrthrych'
+ },
+
+ format :
+ {
+ label : 'Fformat',
+ panelTitle : 'Fformat Paragraff',
+
+ tag_p : 'Normal',
+ tag_pre : 'Wedi\'i Fformatio',
+ tag_address : 'Cyfeiriad',
+ tag_h1 : 'Pennawd 1',
+ tag_h2 : 'Pennawd 2',
+ tag_h3 : 'Pennawd 3',
+ tag_h4 : 'Pennawd 4',
+ tag_h5 : 'Pennawd 5',
+ tag_h6 : 'Pennawd 6',
+ tag_div : 'Normal (DIV)'
+ },
+
+ div :
+ {
+ title : 'Create Div Container', // MISSING
+ toolbar : 'Create Div Container', // MISSING
+ cssClassInputLabel : 'Stylesheet Classes', // MISSING
+ styleSelectLabel : 'Style', // MISSING
+ IdInputLabel : 'Id', // MISSING
+ languageCodeInputLabel : ' Language Code', // MISSING
+ inlineStyleInputLabel : 'Inline Style', // MISSING
+ advisoryTitleInputLabel : 'Advisory Title', // MISSING
+ langDirLabel : 'Language Direction', // MISSING
+ langDirLTRLabel : 'Left to Right (LTR)', // MISSING
+ langDirRTLLabel : 'Right to Left (RTL)', // MISSING
+ edit : 'Edit Div', // MISSING
+ remove : 'Remove Div' // MISSING
+ },
+
+ font :
+ {
+ label : 'Ffont',
+ voiceLabel : 'Ffont',
+ panelTitle : 'Enw\'r Ffont'
+ },
+
+ fontSize :
+ {
+ label : 'Maint',
+ voiceLabel : 'Maint y Ffont',
+ panelTitle : 'Maint y Ffont'
+ },
+
+ colorButton :
+ {
+ textColorTitle : 'Lliw Testun',
+ bgColorTitle : 'Lliw Cefndir',
+ panelTitle : 'Colors', // MISSING
+ auto : 'Awtomatig',
+ more : 'Mwy o Liwiau...'
+ },
+
+ colors :
+ {
+ '000' : 'Du',
+ '800000' : 'Marwn',
+ '8B4513' : 'Brown Cyfrwy',
+ '2F4F4F' : 'Llechen Tywyll',
+ '008080' : 'Corhwyad',
+ '000080' : 'Nefi',
+ '4B0082' : 'Indigo',
+ '696969' : 'Llwyd Pwl',
+ 'B22222' : 'Bric Tân',
+ 'A52A2A' : 'Brown',
+ 'DAA520' : 'Rhoden Aur',
+ '006400' : 'Gwyrdd Tywyll',
+ '40E0D0' : 'Gwyrddlas',
+ '0000CD' : 'Glas Canolig',
+ '800080' : 'Porffor',
+ '808080' : 'Llwyd',
+ 'F00' : 'Coch',
+ 'FF8C00' : 'Oren Tywyll',
+ 'FFD700' : 'Aur',
+ '008000' : 'Gwyrdd',
+ '0FF' : 'Cyan',
+ '00F' : 'Glas',
+ 'EE82EE' : 'Fioled',
+ 'A9A9A9' : 'Llwyd Tywyll',
+ 'FFA07A' : 'Samwn Golau',
+ 'FFA500' : 'Oren',
+ 'FFFF00' : 'Melyn',
+ '00FF00' : 'Leim',
+ 'AFEEEE' : 'Gwyrddlas Golau',
+ 'ADD8E6' : 'Glas Golau',
+ 'DDA0DD' : 'Eirinen',
+ 'D3D3D3' : 'Llwyd Golau',
+ 'FFF0F5' : 'Gwrid Lafant',
+ 'FAEBD7' : 'Gwyn Hynafol',
+ 'FFFFE0' : 'Melyn Golau',
+ 'F0FFF0' : 'Melwn Gwyrdd Golau',
+ 'F0FFFF' : 'Aswr',
+ 'F0F8FF' : 'Glas Alys',
+ 'E6E6FA' : 'Lafant',
+ 'FFF' : 'Gwyn'
+ },
+
+ scayt :
+ {
+ title : 'Gwirio\'r Sillafu Wrth Deipio',
+ enable : 'Galluogi SCAYT',
+ disable : 'Analluogi SCAYT',
+ about : 'Ynghylch SCAYT',
+ toggle : 'Togl SCAYT',
+ options : 'Opsiynau',
+ langs : 'Ieithoedd',
+ moreSuggestions : 'Awgrymiadau pellach',
+ ignore : 'Anwybyddu',
+ ignoreAll : 'Anwybyddu pob',
+ addWord : 'Ychwanegu Gair',
+ emptyDic : 'Ni ddylai enw\'r geiriadur fod yn wag.',
+ optionsTab : 'Opsiynau',
+ languagesTab : 'Ieithoedd',
+ dictionariesTab : 'Geiriaduron',
+ aboutTab : 'Ynghylch'
+ },
+
+ about :
+ {
+ title : 'Ynghylch CKEditor',
+ dlgTitle : 'Ynghylch CKEditor',
+ moreInfo : 'Am wybodaeth ynghylch trwyddedau, ewch i\'n gwefan:',
+ copy : 'Hawlfraint © $1. Cedwir pob hawl.'
+ },
+
+ maximize : 'Mwyhau',
+ minimize : 'Lleihau',
+
+ fakeobjects :
+ {
+ anchor : 'Angor',
+ flash : 'Animeiddiant Flash',
+ div : 'Toriad Tudalen',
+ unknown : 'Gwrthrych Anhysbys'
+ },
+
+ resize : 'Llusgo i ailfeintio',
+
+ colordialog :
+ {
+ title : 'Dewis lliw',
+ highlight : 'Uwcholeuo',
+ selected : 'Dewiswyd',
+ clear : 'Clirio'
+ },
+
+ toolbarCollapse : 'Cyfangu\'r Bar Offer',
+ toolbarExpand : 'Ehangu\'r Bar Offer'
+};
diff --git a/webroot/js/ckeditor/_source/lang/en-gb.js b/webroot/js/ckeditor/_source/lang/en-gb.js
new file mode 100755
index 00000000..fa23d611
--- /dev/null
+++ b/webroot/js/ckeditor/_source/lang/en-gb.js
@@ -0,0 +1,699 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Defines the {@link CKEDITOR.lang} object, for the
+ * English (United Kingdom) language.
+ */
+
+/**#@+
+ @type String
+ @example
+*/
+
+/**
+ * Constains the dictionary of language entries.
+ * @namespace
+ */
+CKEDITOR.lang['en-gb'] =
+{
+ /**
+ * The language reading direction. Possible values are "rtl" for
+ * Right-To-Left languages (like Arabic) and "ltr" for Left-To-Right
+ * languages (like English).
+ * @default 'ltr'
+ */
+ dir : 'ltr',
+
+ /*
+ * Screenreader titles. Please note that screenreaders are not always capable
+ * of reading non-English words. So be careful while translating it.
+ */
+ editorTitle : 'Rich text editor, %1, press ALT 0 for help.', // MISSING
+
+ // ARIA descriptions.
+ toolbar : 'Toolbar', // MISSING
+ editor : 'Rich Text Editor', // MISSING
+
+ // Toolbar buttons without dialogs.
+ source : 'Source',
+ newPage : 'New Page',
+ save : 'Save',
+ preview : 'Preview',
+ cut : 'Cut',
+ copy : 'Copy',
+ paste : 'Paste',
+ print : 'Print',
+ underline : 'Underline',
+ bold : 'Bold',
+ italic : 'Italic',
+ selectAll : 'Select All',
+ removeFormat : 'Remove Format',
+ strike : 'Strike Through',
+ subscript : 'Subscript',
+ superscript : 'Superscript',
+ horizontalrule : 'Insert Horizontal Line',
+ pagebreak : 'Insert Page Break for Printing',
+ unlink : 'Unlink',
+ undo : 'Undo',
+ redo : 'Redo',
+
+ // Common messages and labels.
+ common :
+ {
+ browseServer : 'Browse Server',
+ url : 'URL',
+ protocol : 'Protocol',
+ upload : 'Upload',
+ uploadSubmit : 'Send it to the Server',
+ image : 'Image',
+ flash : 'Flash',
+ form : 'Form',
+ checkbox : 'Checkbox',
+ radio : 'Radio Button',
+ textField : 'Text Field',
+ textarea : 'Textarea',
+ hiddenField : 'Hidden Field',
+ button : 'Button',
+ select : 'Selection Field',
+ imageButton : 'Image Button',
+ notSet : '',
+ id : 'Id',
+ name : 'Name',
+ langDir : 'Language Direction',
+ langDirLtr : 'Left to Right (LTR)',
+ langDirRtl : 'Right to Left (RTL)',
+ langCode : 'Language Code',
+ longDescr : 'Long Description URL',
+ cssClass : 'Stylesheet Classes',
+ advisoryTitle : 'Advisory Title',
+ cssStyle : 'Style',
+ ok : 'OK',
+ cancel : 'Cancel',
+ close : 'Close', // MISSING
+ preview : 'Preview', // MISSING
+ generalTab : 'General',
+ advancedTab : 'Advanced',
+ validateNumberFailed : 'This value is not a number.',
+ confirmNewPage : 'Any unsaved changes to this content will be lost. Are you sure you want to load new page?',
+ confirmCancel : 'Some of the options have been changed. Are you sure to close the dialog?',
+ options : 'Options', // MISSING
+ target : 'Target', // MISSING
+ targetNew : 'New Window (_blank)', // MISSING
+ targetTop : 'Topmost Window (_top)', // MISSING
+ targetSelf : 'Same Window (_self)', // MISSING
+ targetParent : 'Parent Window (_parent)', // MISSING
+
+ // Put the voice-only part of the label in the span.
+ unavailable : '%1, unavailable ' // MISSING
+ },
+
+ // Special char dialog.
+ specialChar :
+ {
+ toolbar : 'Insert Special Character',
+ title : 'Select Special Character'
+ },
+
+ // Link dialog.
+ link :
+ {
+ toolbar : 'Link',
+ menu : 'Edit Link',
+ title : 'Link',
+ info : 'Link Info',
+ target : 'Target',
+ upload : 'Upload',
+ advanced : 'Advanced',
+ type : 'Link Type',
+ toUrl : 'URL', // MISSING
+ toAnchor : 'Link to anchor in the text',
+ toEmail : 'E-mail',
+ targetFrame : ' ',
+ targetPopup : '',
+ targetFrameName : 'Target Frame Name',
+ targetPopupName : 'Popup Window Name',
+ popupFeatures : 'Popup Window Features',
+ popupResizable : 'Resizable',
+ popupStatusBar : 'Status Bar',
+ popupLocationBar: 'Location Bar',
+ popupToolbar : 'Toolbar',
+ popupMenuBar : 'Menu Bar',
+ popupFullScreen : 'Full Screen (IE)',
+ popupScrollBars : 'Scroll Bars',
+ popupDependent : 'Dependent (Netscape)',
+ popupWidth : 'Width',
+ popupLeft : 'Left Position',
+ popupHeight : 'Height',
+ popupTop : 'Top Position',
+ id : 'Id',
+ langDir : 'Language Direction',
+ langDirLTR : 'Left to Right (LTR)',
+ langDirRTL : 'Right to Left (RTL)',
+ acccessKey : 'Access Key',
+ name : 'Name',
+ langCode : 'Language Code',
+ tabIndex : 'Tab Index',
+ advisoryTitle : 'Advisory Title',
+ advisoryContentType : 'Advisory Content Type',
+ cssClasses : 'Stylesheet Classes',
+ charset : 'Linked Resource Charset',
+ styles : 'Style',
+ selectAnchor : 'Select an Anchor',
+ anchorName : 'By Anchor Name',
+ anchorId : 'By Element Id',
+ emailAddress : 'E-Mail Address',
+ emailSubject : 'Message Subject',
+ emailBody : 'Message Body',
+ noAnchors : '(No anchors available in the document)',
+ noUrl : 'Please type the link URL',
+ noEmail : 'Please type the e-mail address'
+ },
+
+ // Anchor dialog
+ anchor :
+ {
+ toolbar : 'Anchor',
+ menu : 'Edit Anchor',
+ title : 'Anchor Properties',
+ name : 'Anchor Name',
+ errorName : 'Please type the anchor name'
+ },
+
+ // Find And Replace Dialog
+ findAndReplace :
+ {
+ title : 'Find and Replace',
+ find : 'Find',
+ replace : 'Replace',
+ findWhat : 'Find what:',
+ replaceWith : 'Replace with:',
+ notFoundMsg : 'The specified text was not found.',
+ matchCase : 'Match case',
+ matchWord : 'Match whole word',
+ matchCyclic : 'Match cyclic',
+ replaceAll : 'Replace All',
+ replaceSuccessMsg : '%1 occurrence(s) replaced.'
+ },
+
+ // Table Dialog
+ table :
+ {
+ toolbar : 'Table',
+ title : 'Table Properties',
+ menu : 'Table Properties',
+ deleteTable : 'Delete Table',
+ rows : 'Rows',
+ columns : 'Columns',
+ border : 'Border size',
+ align : 'Alignment',
+ alignLeft : 'Left',
+ alignCenter : 'Centre',
+ alignRight : 'Right',
+ width : 'Width',
+ widthPx : 'pixels',
+ widthPc : 'percent',
+ widthUnit : 'width unit', // MISSING
+ height : 'Height',
+ cellSpace : 'Cell spacing',
+ cellPad : 'Cell padding',
+ caption : 'Caption',
+ summary : 'Summary',
+ headers : 'Headers',
+ headersNone : 'None',
+ headersColumn : 'First column',
+ headersRow : 'First Row',
+ headersBoth : 'Both',
+ invalidRows : 'Number of rows must be a number greater than 0.',
+ invalidCols : 'Number of columns must be a number greater than 0.',
+ invalidBorder : 'Border size must be a number.',
+ invalidWidth : 'Table width must be a number.',
+ invalidHeight : 'Table height must be a number.',
+ invalidCellSpacing : 'Cell spacing must be a number.',
+ invalidCellPadding : 'Cell padding must be a number.',
+
+ cell :
+ {
+ menu : 'Cell',
+ insertBefore : 'Insert Cell Before',
+ insertAfter : 'Insert Cell After',
+ deleteCell : 'Delete Cells',
+ merge : 'Merge Cells',
+ mergeRight : 'Merge Right',
+ mergeDown : 'Merge Down',
+ splitHorizontal : 'Split Cell Horizontally',
+ splitVertical : 'Split Cell Vertically',
+ title : 'Cell Properties',
+ cellType : 'Cell Type',
+ rowSpan : 'Rows Span',
+ colSpan : 'Columns Span',
+ wordWrap : 'Word Wrap',
+ hAlign : 'Horizontal Alignment',
+ vAlign : 'Vertical Alignment',
+ alignTop : 'Top',
+ alignMiddle : 'Middle',
+ alignBottom : 'Bottom',
+ alignBaseline : 'Baseline',
+ bgColor : 'Background Color',
+ borderColor : 'Border Color',
+ data : 'Data',
+ header : 'Header',
+ yes : 'Yes',
+ no : 'No',
+ invalidWidth : 'Cell width must be a number.',
+ invalidHeight : 'Cell height must be a number.',
+ invalidRowSpan : 'Rows span must be a whole number.',
+ invalidColSpan : 'Columns span must be a whole number.',
+ chooseColor : 'Choose' // MISSING
+ },
+
+ row :
+ {
+ menu : 'Row',
+ insertBefore : 'Insert Row Before',
+ insertAfter : 'Insert Row After',
+ deleteRow : 'Delete Rows'
+ },
+
+ column :
+ {
+ menu : 'Column',
+ insertBefore : 'Insert Column Before',
+ insertAfter : 'Insert Column After',
+ deleteColumn : 'Delete Columns'
+ }
+ },
+
+ // Button Dialog.
+ button :
+ {
+ title : 'Button Properties',
+ text : 'Text (Value)',
+ type : 'Type',
+ typeBtn : 'Button',
+ typeSbm : 'Submit',
+ typeRst : 'Reset'
+ },
+
+ // Checkbox and Radio Button Dialogs.
+ checkboxAndRadio :
+ {
+ checkboxTitle : 'Checkbox Properties',
+ radioTitle : 'Radio Button Properties',
+ value : 'Value',
+ selected : 'Selected'
+ },
+
+ // Form Dialog.
+ form :
+ {
+ title : 'Form Properties',
+ menu : 'Form Properties',
+ action : 'Action',
+ method : 'Method',
+ encoding : 'Encoding'
+ },
+
+ // Select Field Dialog.
+ select :
+ {
+ title : 'Selection Field Properties',
+ selectInfo : 'Select Info',
+ opAvail : 'Available Options',
+ value : 'Value',
+ size : 'Size',
+ lines : 'lines',
+ chkMulti : 'Allow multiple selections',
+ opText : 'Text',
+ opValue : 'Value',
+ btnAdd : 'Add',
+ btnModify : 'Modify',
+ btnUp : 'Up',
+ btnDown : 'Down',
+ btnSetValue : 'Set as selected value',
+ btnDelete : 'Delete'
+ },
+
+ // Textarea Dialog.
+ textarea :
+ {
+ title : 'Textarea Properties',
+ cols : 'Columns',
+ rows : 'Rows'
+ },
+
+ // Text Field Dialog.
+ textfield :
+ {
+ title : 'Text Field Properties',
+ name : 'Name',
+ value : 'Value',
+ charWidth : 'Character Width',
+ maxChars : 'Maximum Characters',
+ type : 'Type',
+ typeText : 'Text',
+ typePass : 'Password'
+ },
+
+ // Hidden Field Dialog.
+ hidden :
+ {
+ title : 'Hidden Field Properties',
+ name : 'Name',
+ value : 'Value'
+ },
+
+ // Image Dialog.
+ image :
+ {
+ title : 'Image Properties',
+ titleButton : 'Image Button Properties',
+ menu : 'Image Properties',
+ infoTab : 'Image Info',
+ btnUpload : 'Send it to the Server',
+ upload : 'Upload',
+ alt : 'Alternative Text',
+ width : 'Width',
+ height : 'Height',
+ lockRatio : 'Lock Ratio',
+ unlockRatio : 'Unlock Ratio', // MISSING
+ resetSize : 'Reset Size',
+ border : 'Border',
+ hSpace : 'HSpace',
+ vSpace : 'VSpace',
+ align : 'Align',
+ alignLeft : 'Left',
+ alignRight : 'Right',
+ alertUrl : 'Please type the image URL',
+ linkTab : 'Link',
+ button2Img : 'Do you want to transform the selected image button on a simple image?',
+ img2Button : 'Do you want to transform the selected image on a image button?',
+ urlMissing : 'Image source URL is missing.', // MISSING
+ validateWidth : 'Width must be a whole number.', // MISSING
+ validateHeight : 'Height must be a whole number.', // MISSING
+ validateBorder : 'Border must be a whole number.', // MISSING
+ validateHSpace : 'HSpace must be a whole number.', // MISSING
+ validateVSpace : 'VSpace must be a whole number.' // MISSING
+ },
+
+ // Flash Dialog
+ flash :
+ {
+ properties : 'Flash Properties',
+ propertiesTab : 'Properties',
+ title : 'Flash Properties',
+ chkPlay : 'Auto Play',
+ chkLoop : 'Loop',
+ chkMenu : 'Enable Flash Menu',
+ chkFull : 'Allow Fullscreen',
+ scale : 'Scale',
+ scaleAll : 'Show all',
+ scaleNoBorder : 'No Border',
+ scaleFit : 'Exact Fit',
+ access : 'Script Access',
+ accessAlways : 'Always',
+ accessSameDomain: 'Same domain',
+ accessNever : 'Never',
+ align : 'Align',
+ alignLeft : 'Left',
+ alignAbsBottom : 'Abs Bottom',
+ alignAbsMiddle : 'Abs Middle',
+ alignBaseline : 'Baseline',
+ alignBottom : 'Bottom',
+ alignMiddle : 'Middle',
+ alignRight : 'Right',
+ alignTextTop : 'Text Top',
+ alignTop : 'Top',
+ quality : 'Quality',
+ qualityBest : 'Best', // MISSING
+ qualityHigh : 'High', // MISSING
+ qualityAutoHigh : 'Auto High', // MISSING
+ qualityMedium : 'Medium', // MISSING
+ qualityAutoLow : 'Auto Low', // MISSING
+ qualityLow : 'Low', // MISSING
+ windowModeWindow: 'Window', // MISSING
+ windowModeOpaque: 'Opaque', // MISSING
+ windowModeTransparent : 'Transparent', // MISSING
+ windowMode : 'Window mode',
+ flashvars : 'Variables for Flash',
+ bgcolor : 'Background colour',
+ width : 'Width',
+ height : 'Height',
+ hSpace : 'HSpace',
+ vSpace : 'VSpace',
+ validateSrc : 'URL must not be empty.',
+ validateWidth : 'Width must be a number.',
+ validateHeight : 'Height must be a number.',
+ validateHSpace : 'HSpace must be a number.',
+ validateVSpace : 'VSpace must be a number.'
+ },
+
+ // Speller Pages Dialog
+ spellCheck :
+ {
+ toolbar : 'Check Spelling',
+ title : 'Spell Check',
+ notAvailable : 'Sorry, but service is unavailable now.',
+ errorLoading : 'Error loading application service host: %s.',
+ notInDic : 'Not in dictionary',
+ changeTo : 'Change to',
+ btnIgnore : 'Ignore',
+ btnIgnoreAll : 'Ignore All',
+ btnReplace : 'Replace',
+ btnReplaceAll : 'Replace All',
+ btnUndo : 'Undo',
+ noSuggestions : '- No suggestions -',
+ progress : 'Spell check in progress...',
+ noMispell : 'Spell check complete: No misspellings found',
+ noChanges : 'Spell check complete: No words changed',
+ oneChange : 'Spell check complete: One word changed',
+ manyChanges : 'Spell check complete: %1 words changed',
+ ieSpellDownload : 'Spell checker not installed. Do you want to download it now?'
+ },
+
+ smiley :
+ {
+ toolbar : 'Smiley',
+ title : 'Insert a Smiley'
+ },
+
+ elementsPath :
+ {
+ eleLabel : 'Elements path', // MISSING
+ eleTitle : '%1 element'
+ },
+
+ numberedlist : 'Insert/Remove Numbered List',
+ bulletedlist : 'Insert/Remove Bulleted List',
+ indent : 'Increase Indent',
+ outdent : 'Decrease Indent',
+
+ justify :
+ {
+ left : 'Left Justify',
+ center : 'Centre Justify',
+ right : 'Right Justify',
+ block : 'Block Justify'
+ },
+
+ blockquote : 'Block Quote',
+
+ clipboard :
+ {
+ title : 'Paste',
+ cutError : 'Your browser security settings don\'t permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).',
+ copyError : 'Your browser security settings don\'t permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).',
+ pasteMsg : 'Please paste inside the following box using the keyboard (Ctrl+V ) and hit OK',
+ securityMsg : '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.',
+ pasteArea : 'Paste Area'
+ },
+
+ pastefromword :
+ {
+ confirmCleanup : 'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?', // MISSING
+ toolbar : 'Paste from Word',
+ title : 'Paste from Word',
+ error : 'It was not possible to clean up the pasted data due to an internal error' // MISSING
+ },
+
+ pasteText :
+ {
+ button : 'Paste as plain text',
+ title : 'Paste as Plain Text'
+ },
+
+ templates :
+ {
+ button : 'Templates',
+ title : 'Content Templates',
+ insertOption : 'Replace actual contents',
+ selectPromptMsg : 'Please select the template to open in the editor',
+ emptyListMsg : '(No templates defined)'
+ },
+
+ showBlocks : 'Show Blocks',
+
+ stylesCombo :
+ {
+ label : 'Styles',
+ panelTitle : 'Formatting Styles', // MISSING
+ panelTitle1 : 'Block Styles',
+ panelTitle2 : 'Inline Styles',
+ panelTitle3 : 'Object Styles'
+ },
+
+ format :
+ {
+ label : 'Format',
+ panelTitle : 'Paragraph Format',
+
+ tag_p : 'Normal',
+ tag_pre : 'Formatted',
+ tag_address : 'Address',
+ tag_h1 : 'Heading 1',
+ tag_h2 : 'Heading 2',
+ tag_h3 : 'Heading 3',
+ tag_h4 : 'Heading 4',
+ tag_h5 : 'Heading 5',
+ tag_h6 : 'Heading 6',
+ tag_div : 'Normal (DIV)'
+ },
+
+ div :
+ {
+ title : 'Create Div Container', // MISSING
+ toolbar : 'Create Div Container', // MISSING
+ cssClassInputLabel : 'Stylesheet Classes', // MISSING
+ styleSelectLabel : 'Style', // MISSING
+ IdInputLabel : 'Id', // MISSING
+ languageCodeInputLabel : ' Language Code', // MISSING
+ inlineStyleInputLabel : 'Inline Style', // MISSING
+ advisoryTitleInputLabel : 'Advisory Title', // MISSING
+ langDirLabel : 'Language Direction', // MISSING
+ langDirLTRLabel : 'Left to Right (LTR)', // MISSING
+ langDirRTLLabel : 'Right to Left (RTL)', // MISSING
+ edit : 'Edit Div', // MISSING
+ remove : 'Remove Div' // MISSING
+ },
+
+ font :
+ {
+ label : 'Font',
+ voiceLabel : 'Font', // MISSING
+ panelTitle : 'Font Name'
+ },
+
+ fontSize :
+ {
+ label : 'Size',
+ voiceLabel : 'Font Size', // MISSING
+ panelTitle : 'Font Size'
+ },
+
+ colorButton :
+ {
+ textColorTitle : 'Text Colour',
+ bgColorTitle : 'Background Colour',
+ panelTitle : 'Colors', // MISSING
+ auto : 'Automatic',
+ more : 'More Colours...'
+ },
+
+ colors :
+ {
+ '000' : 'Black', // MISSING
+ '800000' : 'Maroon', // MISSING
+ '8B4513' : 'Saddle Brown', // MISSING
+ '2F4F4F' : 'Dark Slate Gray', // MISSING
+ '008080' : 'Teal', // MISSING
+ '000080' : 'Navy', // MISSING
+ '4B0082' : 'Indigo', // MISSING
+ '696969' : 'Dim Gray', // MISSING
+ 'B22222' : 'Fire Brick', // MISSING
+ 'A52A2A' : 'Brown', // MISSING
+ 'DAA520' : 'Golden Rod', // MISSING
+ '006400' : 'Dark Green', // MISSING
+ '40E0D0' : 'Turquoise', // MISSING
+ '0000CD' : 'Medium Blue', // MISSING
+ '800080' : 'Purple', // MISSING
+ '808080' : 'Gray', // MISSING
+ 'F00' : 'Red', // MISSING
+ 'FF8C00' : 'Dark Orange', // MISSING
+ 'FFD700' : 'Gold', // MISSING
+ '008000' : 'Green', // MISSING
+ '0FF' : 'Cyan', // MISSING
+ '00F' : 'Blue', // MISSING
+ 'EE82EE' : 'Violet', // MISSING
+ 'A9A9A9' : 'Dark Gray', // MISSING
+ 'FFA07A' : 'Light Salmon', // MISSING
+ 'FFA500' : 'Orange', // MISSING
+ 'FFFF00' : 'Yellow', // MISSING
+ '00FF00' : 'Lime', // MISSING
+ 'AFEEEE' : 'Pale Turquoise', // MISSING
+ 'ADD8E6' : 'Light Blue', // MISSING
+ 'DDA0DD' : 'Plum', // MISSING
+ 'D3D3D3' : 'Light Grey', // MISSING
+ 'FFF0F5' : 'Lavender Blush', // MISSING
+ 'FAEBD7' : 'Antique White', // MISSING
+ 'FFFFE0' : 'Light Yellow', // MISSING
+ 'F0FFF0' : 'Honeydew', // MISSING
+ 'F0FFFF' : 'Azure', // MISSING
+ 'F0F8FF' : 'Alice Blue', // MISSING
+ 'E6E6FA' : 'Lavender', // MISSING
+ 'FFF' : 'White' // MISSING
+ },
+
+ scayt :
+ {
+ title : 'Spell Check As You Type', // MISSING
+ enable : 'Enable SCAYT', // MISSING
+ disable : 'Disable SCAYT', // MISSING
+ about : 'About SCAYT', // MISSING
+ toggle : 'Toggle SCAYT', // MISSING
+ options : 'Options', // MISSING
+ langs : 'Languages', // MISSING
+ moreSuggestions : 'More suggestions', // MISSING
+ ignore : 'Ignore', // MISSING
+ ignoreAll : 'Ignore All', // MISSING
+ addWord : 'Add Word', // MISSING
+ emptyDic : 'Dictionary name should not be empty.', // MISSING
+ optionsTab : 'Options', // MISSING
+ languagesTab : 'Languages', // MISSING
+ dictionariesTab : 'Dictionaries', // MISSING
+ aboutTab : 'About' // MISSING
+ },
+
+ about :
+ {
+ title : 'About CKEditor',
+ dlgTitle : 'About CKEditor', // MISSING
+ moreInfo : 'For licensing information please visit our web site:',
+ copy : 'Copyright © $1. All rights reserved.'
+ },
+
+ maximize : 'Maximize',
+ minimize : 'Minimize', // MISSING
+
+ fakeobjects :
+ {
+ anchor : 'Anchor', // MISSING
+ flash : 'Flash Animation', // MISSING
+ div : 'Page Break', // MISSING
+ unknown : 'Unknown Object' // MISSING
+ },
+
+ resize : 'Drag to resize', // MISSING
+
+ colordialog :
+ {
+ title : 'Select color', // MISSING
+ highlight : 'Highlight', // MISSING
+ selected : 'Selected', // MISSING
+ clear : 'Clear' // MISSING
+ },
+
+ toolbarCollapse : 'Collapse Toolbar', // MISSING
+ toolbarExpand : 'Expand Toolbar' // MISSING
+};
diff --git a/webroot/js/ckeditor/_source/plugins/a11yhelp/dialogs/a11yhelp.js b/webroot/js/ckeditor/_source/plugins/a11yhelp/dialogs/a11yhelp.js
new file mode 100755
index 00000000..3348f931
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/a11yhelp/dialogs/a11yhelp.js
@@ -0,0 +1,211 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.dialog.add( 'a11yHelp', function( editor )
+{
+ var lang = editor.lang.accessibilityHelp,
+ id = CKEDITOR.tools.getNextNumber();
+
+ // CharCode <-> KeyChar.
+ var keyMap =
+ {
+ 8 : "BACKSPACE",
+ 9 : "TAB" ,
+ 13 : "ENTER" ,
+ 16 : "SHIFT" ,
+ 17 : "CTRL" ,
+ 18 : "ALT" ,
+ 19 : "PAUSE" ,
+ 20 : "CAPSLOCK" ,
+ 27 : "ESCAPE" ,
+ 33 : "PAGE UP" ,
+ 34 : "PAGE DOWN" ,
+ 35 : "END" ,
+ 36 : "HOME" ,
+ 37 : "LEFT ARROW" ,
+ 38 : "UP ARROW" ,
+ 39 : "RIGHT ARROW" ,
+ 40 : "DOWN ARROW" ,
+ 45 : "INSERT" ,
+ 46 : "DELETE" ,
+ 91 : "LEFT WINDOW KEY" ,
+ 92 : "RIGHT WINDOW KEY" ,
+ 93 : "SELECT KEY" ,
+ 96 : "NUMPAD 0" ,
+ 97 : "NUMPAD 1" ,
+ 98 : "NUMPAD 2" ,
+ 99 : "NUMPAD 3" ,
+ 100 : "NUMPAD 4" ,
+ 101 : "NUMPAD 5" ,
+ 102 : "NUMPAD 6" ,
+ 103 : "NUMPAD 7" ,
+ 104 : "NUMPAD 8" ,
+ 105 : "NUMPAD 9" ,
+ 106 : "MULTIPLY" ,
+ 107 : "ADD" ,
+ 109 : "SUBTRACT" ,
+ 110 : "DECIMAL POINT" ,
+ 111 : "DIVIDE" ,
+ 112 : "F1" ,
+ 113 : "F2" ,
+ 114 : "F3" ,
+ 115 : "F4" ,
+ 116 : "F5" ,
+ 117 : "F6" ,
+ 118 : "F7" ,
+ 119 : "F8" ,
+ 120 : "F9" ,
+ 121 : "F10" ,
+ 122 : "F11" ,
+ 123 : "F12" ,
+ 144 : "NUM LOCK" ,
+ 145 : "SCROLL LOCK" ,
+ 186 : "SEMI-COLON" ,
+ 187 : "EQUAL SIGN" ,
+ 188 : "COMMA" ,
+ 189 : "DASH" ,
+ 190 : "PERIOD" ,
+ 191 : "FORWARD SLASH" ,
+ 192 : "GRAVE ACCENT" ,
+ 219 : "OPEN BRACKET" ,
+ 220 : "BACK SLASH" ,
+ 221 : "CLOSE BRAKET" ,
+ 222 : "SINGLE QUOTE"
+ };
+
+ // Modifier keys override.
+ keyMap[ CKEDITOR.ALT ] = 'ALT';
+ keyMap[ CKEDITOR.SHIFT ] = 'SHIFT';
+ keyMap[ CKEDITOR.CTRL ] = 'CTRL';
+
+ // Sort in desc.
+ var modifiers = [ CKEDITOR.ALT, CKEDITOR.SHIFT, CKEDITOR.CTRL ];
+
+ function representKeyStroke( keystroke )
+ {
+ var quotient,
+ modifier,
+ presentation = [];
+
+ for ( var i = 0; i < modifiers.length; i++ )
+ {
+ modifier = modifiers[ i ];
+ quotient = keystroke / modifiers[ i ];
+ if ( quotient > 1 && quotient <= 2 )
+ {
+ keystroke -= modifier;
+ presentation.push( keyMap[ modifier ] );
+ }
+ }
+
+ presentation.push( keyMap[ keystroke ]
+ || String.fromCharCode( keystroke ) );
+
+ return presentation.join( '+' );
+ }
+
+ var variablesPattern = /\$\{(.*?)\}/g;
+ function replaceVariables( match, name )
+ {
+ var keystrokes = editor.config.keystrokes,
+ definition,
+ length = keystrokes.length;
+
+ for ( var i = 0; i < length; i++ )
+ {
+ definition = keystrokes[ i ];
+ if ( definition[ 1 ] == name )
+ break;
+ }
+ return representKeyStroke( definition[ 0 ] );
+ }
+
+ // Create the help list directly from lang file entries.
+ function buildHelpContents()
+ {
+ var pageTpl = '%1
' +
+ '' + lang.contents + ' ',
+ sectionTpl = '%1 %2 ',
+ itemTpl = '%1 %2 ';
+
+ var pageHtml = [],
+ sections = lang.legend,
+ sectionLength = sections.length;
+
+ for ( var i = 0; i < sectionLength; i++ )
+ {
+ var section = sections[ i ],
+ sectionHtml = [],
+ items = section.items,
+ itemsLength = items.length;
+
+ for ( var j = 0; j < itemsLength; j++ )
+ {
+ var item = items[ j ],
+ itemHtml;
+ itemHtml = itemTpl.replace( '%1', item.name ).
+ replace( '%2', item.legend.replace( variablesPattern, replaceVariables ) );
+ sectionHtml.push( itemHtml );
+ }
+
+ pageHtml.push( sectionTpl.replace( '%1', section.name ).replace( '%2', sectionHtml.join( '' ) ) );
+ }
+
+ return pageTpl.replace( '%1', pageHtml.join( '' ) );
+ }
+
+ return {
+ title : lang.title,
+ minWidth : 600,
+ minHeight : 400,
+ contents : [
+ {
+ id : 'info',
+ label : editor.lang.common.generalTab,
+ expand : true,
+ elements :
+ [
+ {
+ type : 'html',
+ id : 'legends',
+ focus : function() {},
+ html : buildHelpContents() +
+ ''
+ }
+ ]
+ }
+ ],
+ buttons : [ CKEDITOR.dialog.cancelButton ]
+ };
+});
diff --git a/webroot/js/ckeditor/_source/plugins/a11yhelp/lang/en.js b/webroot/js/ckeditor/_source/plugins/a11yhelp/lang/en.js
new file mode 100755
index 00000000..b01885a9
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/a11yhelp/lang/en.js
@@ -0,0 +1,108 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.plugins.setLang( 'a11yhelp', 'en',
+{
+ accessibilityHelp :
+ {
+ title : 'Accessibility Instructions',
+ contents : 'Help Contents. To close this dialog press ESC.',
+ legend :
+ [
+ {
+ name : 'General',
+ items :
+ [
+ {
+ name : 'Editor Toolbar',
+ legend:
+ 'Press ${toolbarFocus} to navigate to the toolbar. ' +
+ 'Move to next toolbar button with TAB or RIGHT ARROW. ' +
+ 'Move to previous button with SHIFT+TAB or LEFT ARROW. ' +
+ 'Press SPACE or ENTER to activate the toolbar button.'
+ },
+
+ {
+ name : 'Editor Dialog',
+ legend :
+ 'Inside a dialog, press TAB to navigate to next dialog field, press SHIFT + TAB to move to previous field, press ENTER to submit dialog, press ESC to cancel dialog. ' +
+ 'For dialogs that have multiple tab pages, press ALT + F10 to navigate to tab-list. ' +
+ 'Then move to next tab with TAB OR RIGTH ARROW. ' +
+ 'Move to previous tab with SHIFT + TAB or LEFT ARROW. ' +
+ 'Press SPACE or ENTER to select the tab page.'
+ },
+
+ {
+ name : 'Editor Context Menu',
+ legend :
+ 'Press ${contextMenu} or APPLICATION KEY to open context-menu. ' +
+ 'Then move to next menu option with TAB or DOWN ARROW. ' +
+ 'Move to previous option with SHIFT+TAB or UP ARROW. ' +
+ 'Press SPACE or ENTER to select the menu option. ' +
+ 'Open sub-menu of current option wtih SPACE or ENTER or RIGHT ARROW. ' +
+ 'Go back to parent menu item with ESC or LEFT ARROW. ' +
+ 'Close context menu with ESC.'
+ },
+
+ {
+ name : 'Editor List Box',
+ legend :
+ 'Inside a list-box, move to next list item with TAB OR DOWN ARROW. ' +
+ 'Move to previous list item with SHIFT + TAB or UP ARROW. ' +
+ 'Press SPACE or ENTER to select the list option. ' +
+ 'Press ESC to close the list-box.'
+ },
+
+ {
+ name : 'Editor Element Path Bar',
+ legend :
+ 'Press ${elementsPathFocus} to navigate to the elements path bar. ' +
+ 'Move to next element button with TAB or RIGHT ARROW. ' +
+ 'Move to previous button with SHIFT+TAB or LEFT ARROW. ' +
+ 'Press SPACE or ENTER to select the element in editor.'
+ }
+ ]
+ },
+ {
+ name : 'Commands',
+ items :
+ [
+ {
+ name : ' Undo command',
+ legend : 'Press ${undo}'
+ },
+ {
+ name : ' Redo command',
+ legend : 'Press ${redo}'
+ },
+ {
+ name : ' Bold command',
+ legend : 'Press ${bold}'
+ },
+ {
+ name : ' Italic command',
+ legend : 'Press ${italic}'
+ },
+ {
+ name : ' Underline command',
+ legend : 'Press ${underline}'
+ },
+ {
+ name : ' Link command',
+ legend : 'Press ${link}'
+ },
+ {
+ name : ' Toolbar Collapse command',
+ legend : 'Press ${toolbarCollapse}'
+ },
+ {
+ name : ' Accessibility Help',
+ legend : 'Press ${a11yHelp}'
+ }
+ ]
+ }
+ ]
+ }
+});
diff --git a/webroot/js/ckeditor/_source/plugins/a11yhelp/plugin.js b/webroot/js/ckeditor/_source/plugins/a11yhelp/plugin.js
new file mode 100755
index 00000000..455d21e2
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/a11yhelp/plugin.js
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Plugin definition for the a11yhelp, which provides a dialog
+ * with accessibility related help.
+ */
+
+(function()
+{
+ var pluginName = 'a11yhelp',
+ commandName = 'a11yHelp';
+
+ CKEDITOR.plugins.add( pluginName,
+ {
+ // List of available localizations.
+ availableLangs : { en:1 },
+
+ init : function( editor )
+ {
+ var plugin = this;
+ editor.addCommand( commandName,
+ {
+ exec : function()
+ {
+ var langCode = editor.langCode;
+ langCode = plugin.availableLangs[ langCode ] ? langCode : 'en';
+
+ CKEDITOR.scriptLoader.load(
+ CKEDITOR.getUrl( plugin.path + 'lang/' + langCode + '.js' ),
+ function()
+ {
+ CKEDITOR.tools.extend( editor.lang, plugin.lang[ langCode ] );
+ editor.openDialog( commandName );
+ });
+ },
+ modes : { wysiwyg:1, source:1 },
+ canUndo : false
+ });
+
+ CKEDITOR.dialog.add( commandName, this.path + 'dialogs/a11yhelp.js' );
+ }
+ });
+})();
diff --git a/webroot/js/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js b/webroot/js/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js
new file mode 100755
index 00000000..d99d033e
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js
@@ -0,0 +1,191 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.dialog.add( 'colordialog', function( editor )
+ {
+ // Define some shorthands.
+ var $el = CKEDITOR.dom.element,
+ $doc = CKEDITOR.document,
+ $tools = CKEDITOR.tools,
+ lang = editor.lang.colordialog;
+
+ // Reference the dialog.
+ var dialog;
+
+ function spacer()
+ {
+ return {
+ type : 'html',
+ html : ' '
+ };
+ }
+
+ var table = new $el( 'table' );
+ createColorTable();
+
+ var cellMouseover = function( event )
+ {
+ var color = new $el( event.data.getTarget() ).getAttribute( 'title' );
+ $doc.getById( 'hicolor' ).setStyle( 'background-color', color );
+ $doc.getById( 'hicolortext' ).setHtml( color );
+ };
+
+ var cellClick = function( event )
+ {
+ var color = new $el( event.data.getTarget() ).getAttribute( 'title' );
+ dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color );
+ };
+
+ function createColorTable()
+ {
+ // 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 row = table.$.insertRow(-1);
+
+ for ( var j = rangeB ; j < rangeB + 3 ; j++ )
+ {
+ for ( var n = 0 ; n < 6 ; n++ )
+ {
+ appendColorCell( row, '#' + aColors[j] + aColors[n] + aColors[i] );
+ }
+ }
+ }
+ }
+
+ // This function create a single color cell in the color table.
+ function appendColorCell( targetRow, color )
+ {
+ var cell = new $el( targetRow.insertCell( -1 ) );
+ cell.setAttribute( 'class', 'ColorCell' );
+ cell.setStyle( 'background-color', color );
+
+ cell.setStyle( 'width', '15px' );
+ cell.setStyle( 'height', '15px' );
+
+ // Pass unparsed color value in some markup-degradable form.
+ cell.setAttribute( 'title', color );
+ }
+
+ appendColorRow( 0, 0 );
+ appendColorRow( 3, 0 );
+ appendColorRow( 0, 3 );
+ appendColorRow( 3, 3 );
+
+ // Create the last row.
+ var oRow = table.$.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()
+ {
+ $doc.getById( 'selhicolor' ).removeStyle( 'background-color' );
+ dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' );
+ }
+
+ var clearActual = $tools.addFunction( function()
+ {
+ $doc.getById( 'hicolor' ).removeStyle( 'background-color' );
+ $doc.getById( 'hicolortext' ).setHtml( ' ' );
+ } );
+
+ return {
+ title : lang.title,
+ minWidth : 360,
+ minHeight : 220,
+ onLoad : function()
+ {
+ // Update reference.
+ dialog = this;
+ },
+ contents : [
+ {
+ id : 'picker',
+ label : lang.title,
+ accessKey : 'I',
+ elements :
+ [
+ {
+ type : 'hbox',
+ padding : 0,
+ widths : [ '70%', '10%', '30%' ],
+ children :
+ [
+ {
+ type : 'html',
+ html : '',
+ onLoad : function()
+ {
+ var table = CKEDITOR.document.getById( this.domId );
+ table.on( 'mouseover', cellMouseover );
+ table.on( 'click', cellClick );
+ }
+ },
+ spacer(),
+ {
+ type : 'vbox',
+ padding : 0,
+ widths : [ '70%', '5%', '25%' ],
+ children :
+ [
+ {
+ type : 'html',
+ html : '' + lang.highlight +' \
+
\
+
\
+ ' + lang.selected +' \
+
'
+ },
+ {
+ type : 'text',
+ id : 'selectedColor',
+ style : 'width: 74px',
+ onChange : function()
+ {
+ // Try to update color preview with new value. If fails, then set it no none.
+ try
+ {
+ $doc.getById( 'selhicolor' ).setStyle( 'background-color', this.getValue() );
+ }
+ catch ( e )
+ {
+ clear();
+ }
+ }
+ },
+ spacer(),
+ {
+ type : 'button',
+ id : 'clear',
+ style : 'margin-top: 5px',
+ label : lang.clear,
+ onClick : clear
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ };
+ }
+ );
diff --git a/webroot/js/ckeditor/_source/plugins/colordialog/plugin.js b/webroot/js/ckeditor/_source/plugins/colordialog/plugin.js
new file mode 100755
index 00000000..7006d682
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/colordialog/plugin.js
@@ -0,0 +1,13 @@
+( function()
+{
+ CKEDITOR.plugins.colordialog =
+ {
+ init : function( editor )
+ {
+ editor.addCommand( 'colordialog', new CKEDITOR.dialogCommand( 'colordialog' ) );
+ CKEDITOR.dialog.add( 'colordialog', this.path + 'dialogs/colordialog.js' );
+ }
+ };
+
+ CKEDITOR.plugins.add( 'colordialog', CKEDITOR.plugins.colordialog );
+} )();
diff --git a/webroot/js/ckeditor/_source/plugins/div/dialogs/div.js b/webroot/js/ckeditor/_source/plugins/div/dialogs/div.js
new file mode 100755
index 00000000..e3b39c33
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/div/dialogs/div.js
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+
+(function()
+{
+
+ /**
+ * Add to collection with DUP examination.
+ * @param {Object} collection
+ * @param {Object} element
+ * @param {Object} database
+ */
+ function addSafely( collection, element, database )
+ {
+ // 1. IE doesn't support customData on text nodes;
+ // 2. Text nodes never get chance to appear twice;
+ if ( !element.is || !element.getCustomData( 'block_processed' ) )
+ {
+ element.is && CKEDITOR.dom.element.setMarker( database, element, 'block_processed', true );
+ collection.push( element );
+ }
+ }
+
+ function getNonEmptyChildren( element )
+ {
+ var retval = [];
+ var children = element.getChildren();
+ for ( var i = 0 ; i < children.count() ; i++ )
+ {
+ var child = children.getItem( i );
+ if ( ! ( child.type === CKEDITOR.NODE_TEXT
+ && ( /^[ \t\n\r]+$/ ).test( child.getText() ) ) )
+ retval.push( child );
+ }
+ return retval;
+ }
+
+
+ /**
+ * Dialog reused by both 'creatediv' and 'editdiv' commands.
+ * @param {Object} editor
+ * @param {String} command The command name which indicate what the current command is.
+ */
+ function divDialog( editor, command )
+ {
+ // Definition of elements at which div operation should stopped.
+ var divLimitDefinition = ( function(){
+
+ // Customzie from specialize blockLimit elements
+ var definition = CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$blockLimit );
+
+ // Exclude 'div' itself.
+ delete definition.div;
+
+ // Exclude 'td' and 'th' when 'wrapping table'
+ if ( editor.config.div_wrapTable )
+ {
+ delete definition.td;
+ delete definition.th;
+ }
+ return definition;
+ })();
+
+ // DTD of 'div' element
+ var dtd = CKEDITOR.dtd.div;
+
+ /**
+ * Get the first div limit element on the element's path.
+ * @param {Object} element
+ */
+ function getDivLimitElement( element )
+ {
+ var pathElements = new CKEDITOR.dom.elementPath( element ).elements;
+ var divLimit;
+ for ( var i = 0; i < pathElements.length ; i++ )
+ {
+ if ( pathElements[ i ].getName() in divLimitDefinition )
+ {
+ divLimit = pathElements[ i ];
+ break;
+ }
+ }
+ return divLimit;
+ }
+
+ /**
+ * Init all fields' setup/commit function.
+ * @memberof divDialog
+ */
+ function setupFields()
+ {
+ this.foreach( function( field )
+ {
+ // Exclude layout container elements
+ if ( /^(?!vbox|hbox)/.test( field.type ) )
+ {
+ if ( !field.setup )
+ {
+ // Read the dialog fields values from the specified
+ // element attributes.
+ field.setup = function( element )
+ {
+ field.setValue( element.getAttribute( field.id ) || '' );
+ };
+ }
+ if ( !field.commit )
+ {
+ // Set element attributes assigned by the dialog
+ // fields.
+ field.commit = function( element )
+ {
+ var fieldValue = this.getValue();
+ // ignore default element attribute values
+ if ( 'dir' == field.id && element.getComputedStyle( 'direction' ) == fieldValue )
+ return;
+
+ if ( fieldValue )
+ element.setAttribute( field.id, fieldValue );
+ else
+ element.removeAttribute( field.id );
+ };
+ }
+ }
+ } );
+ }
+
+ /**
+ * Wrapping 'div' element around appropriate blocks among the selected ranges.
+ * @param {Object} editor
+ */
+ function createDiv( editor )
+ {
+ // new adding containers OR detected pre-existed containers.
+ var containers = [];
+ // node markers store.
+ var database = {};
+ // All block level elements which contained by the ranges.
+ var containedBlocks = [], block;
+
+ // Get all ranges from the selection.
+ var selection = editor.document.getSelection();
+ var ranges = selection.getRanges();
+ var bookmarks = selection.createBookmarks();
+ var i, iterator;
+
+ // Calcualte a default block tag if we need to create blocks.
+ var blockTag = editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p';
+
+ // collect all included elements from dom-iterator
+ for ( i = 0 ; i < ranges.length ; i++ )
+ {
+ iterator = ranges[ i ].createIterator();
+ while ( ( block = iterator.getNextParagraph() ) )
+ {
+ // include contents of blockLimit elements.
+ if ( block.getName() in divLimitDefinition )
+ {
+ var j, childNodes = block.getChildren();
+ for ( j = 0 ; j < childNodes.count() ; j++ )
+ addSafely( containedBlocks, childNodes.getItem( j ) , database );
+ }
+ else
+ {
+ // Bypass dtd disallowed elements.
+ while ( !dtd[ block.getName() ] && block.getName() != 'body' )
+ block = block.getParent();
+ addSafely( containedBlocks, block, database );
+ }
+ }
+ }
+
+ CKEDITOR.dom.element.clearAllMarkers( database );
+
+ var blockGroups = groupByDivLimit( containedBlocks );
+ var ancestor, blockEl, divElement;
+
+ for ( i = 0 ; i < blockGroups.length ; i++ )
+ {
+ var currentNode = blockGroups[ i ][ 0 ];
+
+ // Calculate the common parent node of all contained elements.
+ ancestor = currentNode.getParent();
+ for ( j = 1 ; j < blockGroups[ i ].length; j++ )
+ ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] );
+
+ divElement = new CKEDITOR.dom.element( 'div', editor.document );
+
+ // Normalize the blocks in each group to a common parent.
+ for ( j = 0; j < blockGroups[ i ].length ; j++ )
+ {
+ currentNode = blockGroups[ i ][ j ];
+
+ while ( !currentNode.getParent().equals( ancestor ) )
+ currentNode = currentNode.getParent();
+
+ // This could introduce some duplicated elements in array.
+ blockGroups[ i ][ j ] = currentNode;
+ }
+
+ // Wrapped blocks counting
+ var fixedBlock = null;
+ for ( j = 0 ; j < blockGroups[ i ].length ; j++ )
+ {
+ currentNode = blockGroups[ i ][ j ];
+
+ // Avoid DUP elements introduced by grouping.
+ if ( !( currentNode.getCustomData && currentNode.getCustomData( 'block_processed' ) ) )
+ {
+ currentNode.is && CKEDITOR.dom.element.setMarker( database, currentNode, 'block_processed', true );
+
+ // Establish new container, wrapping all elements in this group.
+ if ( !j )
+ divElement.insertBefore( currentNode );
+
+ divElement.append( currentNode );
+ }
+ }
+
+ CKEDITOR.dom.element.clearAllMarkers( database );
+ containers.push( divElement );
+ }
+
+ selection.selectBookmarks( bookmarks );
+ return containers;
+ }
+
+ function getDiv( editor )
+ {
+ var path = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() ),
+ blockLimit = path.blockLimit,
+ div = blockLimit && blockLimit.getAscendant( 'div', true );
+ return div;
+ }
+ /**
+ * Divide a set of nodes to different groups by their path's blocklimit element.
+ * Note: the specified nodes should be in source order naturally, which mean they are supposed to producea by following class:
+ * * CKEDITOR.dom.range.Iterator
+ * * CKEDITOR.dom.domWalker
+ * @return {Array []} the grouped nodes
+ */
+ function groupByDivLimit( nodes )
+ {
+ var groups = [],
+ lastDivLimit = null,
+ path, block;
+ for ( var i = 0 ; i < nodes.length ; i++ )
+ {
+ block = nodes[i];
+ var limit = getDivLimitElement( block );
+ if ( !limit.equals( lastDivLimit ) )
+ {
+ lastDivLimit = limit ;
+ groups.push( [] ) ;
+ }
+ groups[ groups.length - 1 ].push( block ) ;
+ }
+ return groups;
+ }
+
+ // Synchronous field values to other impacted fields is required, e.g. div styles
+ // change should also alter inline-style text.
+ function commitInternally( targetFields )
+ {
+ var dialog = this.getDialog(),
+ element = dialog._element && dialog._element.clone()
+ || new CKEDITOR.dom.element( 'div', editor.document );
+
+ // Commit this field and broadcast to target fields.
+ this.commit( element, true );
+
+ targetFields = [].concat( targetFields );
+ var length = targetFields.length, field;
+ for ( var i = 0; i < length; i++ )
+ {
+ field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) );
+ field && field.setup && field.setup( element, true );
+ }
+ }
+
+
+ // Registered 'CKEDITOR.style' instances.
+ var styles = {} ;
+ /**
+ * Hold a collection of created block container elements.
+ */
+ var containers = [];
+ /**
+ * @type divDialog
+ */
+ return {
+ title : editor.lang.div.title,
+ minWidth : 400,
+ minHeight : 165,
+ contents :
+ [
+ {
+ id :'info',
+ label :editor.lang.common.generalTab,
+ title :editor.lang.common.generalTab,
+ elements :
+ [
+ {
+ type :'hbox',
+ widths : [ '50%', '50%' ],
+ children :
+ [
+ {
+ id :'elementStyle',
+ type :'select',
+ style :'width: 100%;',
+ label :editor.lang.div.styleSelectLabel,
+ 'default' : '',
+ // Options are loaded dynamically.
+ items :
+ [
+ [ editor.lang.common.notSet , '' ]
+ ],
+ onChange : function()
+ {
+ commitInternally.call( this, [ 'info:class', 'advanced:dir', 'advanced:style' ] );
+ },
+ setup : function( element )
+ {
+ for ( var name in styles )
+ styles[ name ].checkElementRemovable( element, true ) && this.setValue( name );
+ },
+ commit: function( element )
+ {
+ var styleName;
+ if ( ( styleName = this.getValue() ) )
+ styles[ styleName ].applyToObject( element );
+ }
+ },
+ {
+ id :'class',
+ type :'text',
+ label :editor.lang.common.cssClass,
+ 'default' : ''
+ }
+ ]
+ }
+ ]
+ },
+ {
+ id :'advanced',
+ label :editor.lang.common.advancedTab,
+ title :editor.lang.common.advancedTab,
+ elements :
+ [
+ {
+ type :'vbox',
+ padding :1,
+ children :
+ [
+ {
+ type :'hbox',
+ widths : [ '50%', '50%' ],
+ children :
+ [
+ {
+ type :'text',
+ id :'id',
+ label :editor.lang.common.id,
+ 'default' : ''
+ },
+ {
+ type :'text',
+ id :'lang',
+ label :editor.lang.link.langCode,
+ 'default' : ''
+ }
+ ]
+ },
+ {
+ type :'hbox',
+ children :
+ [
+ {
+ type :'text',
+ id :'style',
+ style :'width: 100%;',
+ label :editor.lang.common.cssStyle,
+ 'default' : '',
+ commit : function( element )
+ {
+ // Merge with 'elementStyle', which is of higher priority.
+ var value = this.getValue(),
+ merged = [ value, element.getAttribute( 'style' ) ].join( ';' );
+ value && element.setAttribute( 'style', merged );
+ }
+ }
+ ]
+ },
+ {
+ type :'hbox',
+ children :
+ [
+ {
+ type :'text',
+ id :'title',
+ style :'width: 100%;',
+ label :editor.lang.common.advisoryTitle,
+ 'default' : ''
+ }
+ ]
+ },
+ {
+ type :'select',
+ id :'dir',
+ style :'width: 100%;',
+ label :editor.lang.common.langDir,
+ 'default' : '',
+ items :
+ [
+ [ editor.lang.common.notSet , '' ],
+ [
+ editor.lang.common.langDirLtr,
+ 'ltr'
+ ],
+ [
+ editor.lang.common.langDirRtl,
+ 'rtl'
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ onLoad : function()
+ {
+ setupFields.call(this);
+
+ // Preparing for the 'elementStyle' field.
+ var dialog = this,
+ stylesField = this.getContentElement( 'info', 'elementStyle' ),
+ // Reuse the 'stylescombo' plugin's styles definition.
+ customStylesConfig = editor.config.stylesCombo_stylesSet,
+ stylesSetName = customStylesConfig && customStylesConfig.split( ':' )[ 0 ];
+
+ if ( stylesSetName )
+ {
+ CKEDITOR.stylesSet.load( stylesSetName,
+ function( stylesSet )
+ {
+ var stylesDefinitions = stylesSet[ stylesSetName ],
+ styleName;
+
+ if ( stylesDefinitions )
+ {
+ // Digg only those styles that apply to 'div'.
+ for ( var i = 0 ; i < stylesDefinitions.length ; i++ )
+ {
+ var styleDefinition = stylesDefinitions[ i ];
+ if ( styleDefinition.element && styleDefinition.element == 'div' )
+ {
+ styleName = styleDefinition.name;
+ styles[ styleName ] = new CKEDITOR.style( styleDefinition );
+
+ // Populate the styles field options with style name.
+ stylesField.items.push( [ styleName, styleName ] );
+ stylesField.add( styleName, styleName );
+ }
+ }
+ }
+
+
+ // We should disable the content element
+ // it if no options are available at all.
+ stylesField[ stylesField.items.length > 1 ? 'enable' : 'disable' ]();
+
+ // Now setup the field value manually.
+ setTimeout( function() { stylesField.setup( dialog._element ); }, 0 );
+ } );
+ }
+ },
+ onShow : function()
+ {
+ // Whether always create new container regardless of existed
+ // ones.
+ if ( command == 'editdiv' )
+ {
+ // Try to discover the containers that already existed in
+ // ranges
+ var div = getDiv( editor );
+ // update dialog field values
+ div && this.setupContent( this._element = div );
+ }
+ },
+ onOk : function()
+ {
+ if ( command == 'editdiv' )
+ containers = [ this._element ];
+ else
+ containers = createDiv( editor, true );
+
+ // Update elements attributes
+ var size = containers.length;
+ for ( var i = 0; i < size; i++ )
+ {
+ this.commitContent( containers[ i ] );
+
+ // Remove empty 'style' attribute.
+ !containers[ i ].getAttribute( 'style' ) && containers[ i ].removeAttribute( 'style' );
+ }
+
+ this.hide();
+ },
+ onHide : function()
+ {
+ delete this._element;
+ }
+ };
+ }
+
+ CKEDITOR.dialog.add( 'creatediv', function( editor )
+ {
+ return divDialog( editor, 'creatediv' );
+ } );
+ CKEDITOR.dialog.add( 'editdiv', function( editor )
+ {
+ return divDialog( editor, 'editdiv' );
+ } );
+} )();
+
+/*
+ * @name CKEDITOR.config.div_wrapTable
+ * Whether to wrap the whole table instead of indivisual cells when created 'div' in table cell.
+ * @type Boolean
+ * @default false
+ * @example config.div_wrapTable = true;
+ */
diff --git a/webroot/js/ckeditor/_source/plugins/div/plugin.js b/webroot/js/ckeditor/_source/plugins/div/plugin.js
new file mode 100755
index 00000000..0714deeb
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/div/plugin.js
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview The "div" plugin. It wraps the selected block level elements with a 'div' element with specified styles and attributes.
+ *
+ */
+
+(function()
+{
+ CKEDITOR.plugins.add( 'div',
+ {
+ requires : [ 'editingblock', 'domiterator', 'styles' ],
+
+ init : function( editor )
+ {
+ var lang = editor.lang.div;
+
+ editor.addCommand( 'creatediv', new CKEDITOR.dialogCommand( 'creatediv' ) );
+ editor.addCommand( 'editdiv', new CKEDITOR.dialogCommand( 'editdiv' ) );
+ editor.addCommand( 'removediv',
+ {
+ exec : function( editor )
+ {
+ var selection = editor.getSelection(),
+ ranges = selection && selection.getRanges(),
+ range,
+ bookmarks = selection.createBookmarks(),
+ walker,
+ toRemove = [];
+
+ function findDiv( node )
+ {
+ var path = new CKEDITOR.dom.elementPath( node ),
+ blockLimit = path.blockLimit,
+ div = blockLimit.is( 'div' ) && blockLimit;
+
+ if ( div && !div.getAttribute( '_cke_div_added' ) )
+ {
+ toRemove.push( div );
+ div.setAttribute( '_cke_div_added' );
+ }
+ }
+
+ for ( var i = 0 ; i < ranges.length ; i++ )
+ {
+ range = ranges[ i ];
+ if ( range.collapsed )
+ findDiv( selection.getStartElement() );
+ else
+ {
+ walker = new CKEDITOR.dom.walker( range );
+ walker.evaluator = findDiv;
+ walker.lastForward();
+ }
+ }
+
+ for ( i = 0 ; i < toRemove.length ; i++ )
+ toRemove[ i ].remove( true );
+
+ selection.selectBookmarks( bookmarks );
+ }
+ } );
+
+ editor.ui.addButton( 'CreateDiv',
+ {
+ label : lang.toolbar,
+ command :'creatediv'
+ } );
+
+ if ( editor.addMenuItems )
+ {
+ editor.addMenuItems(
+ {
+ editdiv :
+ {
+ label : lang.edit,
+ command : 'editdiv',
+ group : 'div',
+ order : 1
+ },
+
+ removediv:
+ {
+ label : lang.remove,
+ command : 'removediv',
+ group : 'div',
+ order : 5
+ }
+ } );
+
+ if ( editor.contextMenu )
+ {
+ editor.contextMenu.addListener( function( element, selection )
+ {
+ if ( !element )
+ return null;
+
+ var elementPath = new CKEDITOR.dom.elementPath( element ),
+ blockLimit = elementPath.blockLimit;
+
+ if ( blockLimit && blockLimit.getAscendant( 'div', true ) )
+ {
+ return {
+ editdiv : CKEDITOR.TRISTATE_OFF,
+ removediv : CKEDITOR.TRISTATE_OFF
+ };
+ }
+
+ return null;
+ } );
+ }
+ }
+
+ CKEDITOR.dialog.add( 'creatediv', this.path + 'dialogs/div.js' );
+ CKEDITOR.dialog.add( 'editdiv', this.path + 'dialogs/div.js' );
+ }
+ } );
+})();
diff --git a/webroot/js/ckeditor/_source/plugins/pastefromword/filter/default.js b/webroot/js/ckeditor/_source/plugins/pastefromword/filter/default.js
new file mode 100755
index 00000000..b042a33c
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/pastefromword/filter/default.js
@@ -0,0 +1,1179 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+ var fragmentPrototype = CKEDITOR.htmlParser.fragment.prototype,
+ elementPrototype = CKEDITOR.htmlParser.element.prototype;
+
+ fragmentPrototype.onlyChild = elementPrototype.onlyChild = function()
+ {
+ var children = this.children,
+ count = children.length,
+ firstChild = ( count == 1 ) && children[ 0 ];
+ return firstChild || null;
+ };
+
+ elementPrototype.removeAnyChildWithName = function( tagName )
+ {
+ var children = this.children,
+ childs = [],
+ child;
+
+ for ( var i = 0; i < children.length; i++ )
+ {
+ child = children[ i ];
+ if ( !child.name )
+ continue;
+
+ if ( child.name == tagName )
+ {
+ childs.push( child );
+ children.splice( i--, 1 );
+ }
+ childs = childs.concat( child.removeAnyChildWithName( tagName ) );
+ }
+ return childs;
+ };
+
+ elementPrototype.getAncestor = function( tagNameRegex )
+ {
+ var parent = this.parent;
+ while ( parent && !( parent.name && parent.name.match( tagNameRegex ) ) )
+ parent = parent.parent;
+ return parent;
+ };
+
+ fragmentPrototype.firstChild = elementPrototype.firstChild = function( evaluator )
+ {
+ var child;
+
+ for ( var i = 0 ; i < this.children.length ; i++ )
+ {
+ child = this.children[ i ];
+ if ( evaluator( child ) )
+ return child;
+ else if ( child.name )
+ {
+ child = child.firstChild( evaluator );
+ if ( child )
+ return child;
+ else
+ continue;
+ }
+ }
+
+ return null;
+ };
+
+ // Adding a (set) of styles to the element's attributes.
+ elementPrototype.addStyle = function( name, value, isPrepend )
+ {
+ var styleText, addingStyleText = '';
+ // name/value pair.
+ if ( typeof value == 'string' )
+ addingStyleText += name + ':' + value + ';';
+ else
+ {
+ // style literal.
+ if ( typeof name == 'object' )
+ {
+ for ( var style in name )
+ {
+ if ( name.hasOwnProperty( style ) )
+ addingStyleText += style + ':' + name[ style ] + ';';
+ }
+ }
+ // raw style text form.
+ else
+ addingStyleText += name;
+
+ isPrepend = value;
+ }
+
+ if ( !this.attributes )
+ this.attributes = {};
+
+ styleText = this.attributes.style || '';
+
+ styleText = ( isPrepend ?
+ [ addingStyleText, styleText ]
+ : [ styleText, addingStyleText ] ).join( ';' );
+
+ this.attributes.style = styleText.replace( /^;|;(?=;)/, '' );
+ };
+
+ /**
+ * Return the DTD-valid parent tag names of the specified one.
+ * @param tagName
+ */
+ CKEDITOR.dtd.parentOf = function( tagName )
+ {
+ var result = {};
+ for ( var tag in this )
+ {
+ if ( tag.indexOf( '$' ) == -1 && this[ tag ][ tagName ] )
+ result[ tag ] = 1;
+ }
+ return result;
+ };
+
+ var cssLengthRelativeUnit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz){1}?/i;
+ var emptyMarginRegex = /^(?:\b0[^\s]*\s*){1,4}$/;
+
+ var listBaseIndent = 0,
+ previousListItemMargin;
+
+ CKEDITOR.plugins.pastefromword =
+ {
+ utils :
+ {
+ // Create a which indicate an list item type.
+ createListBulletMarker : function ( bulletStyle, bulletText )
+ {
+ var marker = new CKEDITOR.htmlParser.element( 'cke:listbullet' ),
+ listType;
+
+ // TODO: Support more list style type from MS-Word.
+ if ( !bulletStyle )
+ {
+ bulletStyle = 'decimal';
+ listType = 'ol';
+ }
+ else if ( bulletStyle[ 2 ] )
+ {
+ if ( !isNaN( bulletStyle[ 1 ] ) )
+ bulletStyle = 'decimal';
+ // No way to distinguish between Roman numerals and Alphas,
+ // detect them as a whole.
+ else if ( /^[a-z]+$/.test( bulletStyle[ 1 ] ) )
+ bulletStyle = 'lower-alpha';
+ else if ( /^[A-Z]+$/.test( bulletStyle[ 1 ] ) )
+ bulletStyle = 'upper-alpha';
+ // Simply use decimal for the rest forms of unrepresentable
+ // numerals, e.g. Chinese...
+ else
+ bulletStyle = 'decimal';
+
+ listType = 'ol';
+ }
+ else
+ {
+ if ( /[l\u00B7\u2002]/.test( bulletStyle[ 1 ] ) ) //l·•
+ bulletStyle = 'disc';
+ else if ( /[\u006F\u00D8]/.test( bulletStyle[ 1 ] ) ) //oØ
+ bulletStyle = 'circle';
+ else if ( /[\u006E\u25C6]/.test( bulletStyle[ 1 ] ) ) //n◆
+ bulletStyle = 'square';
+ else
+ bulletStyle = 'disc';
+
+ listType = 'ul';
+ }
+
+ // Represent list type as CSS style.
+ marker.attributes =
+ {
+ 'cke:listtype' : listType,
+ 'style' : 'list-style-type:' + bulletStyle + ';'
+ };
+ marker.add( new CKEDITOR.htmlParser.text( bulletText ) );
+ return marker;
+ },
+
+ isListBulletIndicator : function( element )
+ {
+ var styleText = element.attributes && element.attributes.style;
+ if ( /mso-list\s*:\s*Ignore/i.test( styleText ) )
+ return true;
+ },
+
+ isContainingOnlySpaces : function( element )
+ {
+ var text;
+ return ( ( text = element.onlyChild() )
+ && ( /^(:?\s| )+$/ ).test( text.value ) );
+ },
+
+ resolveList : function( element )
+ {
+ // indicate a list item.
+ var children = element.children,
+ attrs = element.attributes,
+ listMarker;
+
+ if ( ( listMarker = element.removeAnyChildWithName( 'cke:listbullet' ) )
+ && listMarker.length
+ && ( listMarker = listMarker[ 0 ] ) )
+ {
+ element.name = 'cke:li';
+
+ if ( attrs.style )
+ {
+ attrs.style = CKEDITOR.plugins.pastefromword.filters.stylesFilter(
+ [
+ // Text-indent is not representing list item level any more.
+ [ 'text-indent' ],
+ [ 'line-height' ],
+ // Resolve indent level from 'margin-left' value.
+ [ ( /^margin(:?-left)?$/ ), null, function( margin )
+ {
+ // Be able to deal with component/short-hand form style.
+ var values = margin.split( ' ' );
+ margin = values[ 3 ] || values[ 1 ] || values [ 0 ];
+ margin = parseInt( margin, 10 );
+
+ // Figure out the indent unit by looking at the first increament.
+ if ( !listBaseIndent && previousListItemMargin && margin > previousListItemMargin )
+ listBaseIndent = margin - previousListItemMargin;
+
+ attrs[ 'cke:margin' ] = previousListItemMargin = margin;
+ } ]
+ ] )( attrs.style, element ) || '' ;
+ }
+
+ // Inherit list-type-style from bullet.
+ var listBulletAttrs = listMarker.attributes,
+ listBulletStyle = listBulletAttrs.style;
+
+ element.addStyle( listBulletStyle );
+ CKEDITOR.tools.extend( attrs, listBulletAttrs );
+ return true;
+ }
+
+ return false;
+ },
+
+ // Convert various length units to 'px' in ignorance of DPI.
+ convertToPx : ( function ()
+ {
+ var calculator = CKEDITOR.dom.element.createFromHtml(
+ '
', CKEDITOR.document );
+ CKEDITOR.document.getBody().append( calculator );
+
+ return function( cssLength )
+ {
+ if ( cssLengthRelativeUnit.test( cssLength ) )
+ {
+ calculator.setStyle( 'width', cssLength );
+ return calculator.$.clientWidth + 'px';
+ }
+
+ return cssLength;
+ };
+ } )(),
+
+ // Providing a shorthand style then retrieve one or more style component values.
+ getStyleComponents : ( function()
+ {
+ var calculator = CKEDITOR.dom.element.createFromHtml(
+ '
',
+ CKEDITOR.document );
+ CKEDITOR.document.getBody().append( calculator );
+
+ return function( name, styleValue, fetchList )
+ {
+ calculator.setStyle( name, styleValue );
+ var styles = {},
+ count = fetchList.length;
+ for ( var i = 0; i < count; i++ )
+ styles[ fetchList[ i ] ] = calculator.getStyle( fetchList[ i ] );
+
+ return styles;
+ };
+ } )(),
+
+ listDtdParents : CKEDITOR.dtd.parentOf( 'ol' )
+ },
+
+ filters :
+ {
+ // Transform a normal list into flat list items only presentation.
+ // E.g. level1level2 =>
+ // level1
+ // level2
+ flattenList : function( element )
+ {
+ var attrs = element.attributes,
+ parent = element.parent;
+
+ var listStyleType,
+ indentLevel = 1;
+
+ // Resolve how many level nested.
+ while ( parent )
+ {
+ parent.attributes && parent.attributes[ 'cke:list'] && indentLevel++;
+ parent = parent.parent;
+ }
+
+ // All list items are of the same type.
+ switch ( attrs.type )
+ {
+ case 'a' :
+ listStyleType = 'lower-alpha';
+ break;
+ // TODO: Support more list style type from MS-Word.
+ }
+
+ var children = element.children,
+ child;
+
+ for ( var i = 0; i < children.length; i++ )
+ {
+ child = children[ i ];
+ var attributes = child.attributes;
+
+ if ( child.name in CKEDITOR.dtd.$listItem )
+ {
+ var listItemChildren = child.children,
+ count = listItemChildren.length,
+ last = listItemChildren[ count - 1 ];
+
+ // Move out nested list.
+ if ( last.name in CKEDITOR.dtd.$list )
+ {
+ children.splice( i + 1, 0, last );
+ last.parent = element;
+
+ // Remove the parent list item if it's just a holder.
+ if ( !--listItemChildren.length )
+ children.splice( i, 1 );
+ }
+
+ child.name = 'cke:li';
+ attributes[ 'cke:indent' ] = indentLevel;
+ previousListItemMargin = 0;
+ attributes[ 'cke:listtype' ] = element.name;
+ listStyleType && child.addStyle( 'list-style-type', listStyleType, true );
+ }
+ }
+
+ delete element.name;
+
+ // We're loosing tag name here, signalize this element as a list.
+ attrs[ 'cke:list' ] = 1;
+ },
+
+ /**
+ * Try to collect all list items among the children and establish one
+ * or more HTML list structures for them.
+ * @param element
+ */
+ assembleList : function( element )
+ {
+ var children = element.children, child,
+ listItem, // The current processing cke:li element.
+ listItemAttrs,
+ listType, // Determine the root type of the list.
+ listItemIndent, // Indent level of current list item.
+ lastListItem, // The previous one just been added to the list.
+ list, parentList, // Current staging list and it's parent list if any.
+ indent;
+
+ for ( var i = 0; i < children.length; i++ )
+ {
+ child = children[ i ];
+
+ if ( 'cke:li' == child.name )
+ {
+ child.name = 'li';
+ listItem = child;
+ listItemAttrs = listItem.attributes;
+ listType = listItem.attributes[ 'cke:listtype' ];
+
+ // List item indent level might come from a real list indentation or
+ // been resolved from a pseudo list item's margin value, even get
+ // no indentation at all.
+ listItemIndent = parseInt( listItemAttrs[ 'cke:indent' ], 10 )
+ || listBaseIndent && ( Math.ceil( listItemAttrs[ 'cke:margin' ] / listBaseIndent ) )
+ || 1;
+
+ // Ignore the 'list-style-type' attribute if it's matched with
+ // the list root element's default style type.
+ listItemAttrs.style && ( listItemAttrs.style =
+ CKEDITOR.plugins.pastefromword.filters.stylesFilter(
+ [
+ [ 'list-style-type', listType == 'ol' ? 'decimal' : 'disc' ]
+ ] )( listItemAttrs.style )
+ || '' );
+
+ if ( !list )
+ {
+ list = new CKEDITOR.htmlParser.element( listType );
+ list.add( listItem );
+ children[ i ] = list;
+ }
+ else
+ {
+ if ( listItemIndent > indent )
+ {
+ list = new CKEDITOR.htmlParser.element( listType );
+ list.add( listItem );
+ lastListItem.add( list );
+ }
+ else if ( listItemIndent < indent )
+ {
+ // There might be a negative gap between two list levels. (#4944)
+ var diff = indent - listItemIndent,
+ parent;
+ while ( diff-- && ( parent = list.parent ) )
+ list = parent.parent;
+
+ list.add( listItem );
+ }
+ else
+ list.add( listItem );
+
+ children.splice( i--, 1 );
+ }
+
+ lastListItem = listItem;
+ indent = listItemIndent;
+ }
+ else
+ list = null;
+ }
+
+ listBaseIndent = 0;
+ },
+
+ /**
+ * A simple filter which always rejecting.
+ */
+ falsyFilter : function( value )
+ {
+ return false;
+ },
+
+ /**
+ * A filter dedicated on the 'style' attribute filtering, e.g. dropping/replacing style properties.
+ * @param styles {Array} in form of [ styleNameRegexp, styleValueRegexp,
+ * newStyleValue/newStyleGenerator, newStyleName ] where only the first
+ * parameter is mandatory.
+ * @param whitelist {Boolean} Whether the {@param styles} will be considered as a white-list.
+ */
+ stylesFilter : function( styles, whitelist )
+ {
+ return function( styleText, element )
+ {
+ var rules = [];
+ // html-encoded quote might be introduced by 'font-family'
+ // from MS-Word which confused the following regexp. e.g.
+ //'font-family: "Lucida, Console"'
+ styleText
+ .replace( /"/g, '"' )
+ .replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,
+ function( match, name, value )
+ {
+ name = name.toLowerCase();
+ name == 'font-family' && ( value = value.replace( /["']/g, '' ) );
+
+ var namePattern,
+ valuePattern,
+ newValue,
+ newName;
+ for ( var i = 0 ; i < styles.length; i++ )
+ {
+ if ( styles[ i ] )
+ {
+ namePattern = styles[ i ][ 0 ];
+ valuePattern = styles[ i ][ 1 ];
+ newValue = styles[ i ][ 2 ];
+ newName = styles[ i ][ 3 ];
+
+ if ( name.match( namePattern )
+ && ( !valuePattern || value.match( valuePattern ) ) )
+ {
+ name = newName || name;
+ whitelist && ( newValue = newValue || value );
+
+ if ( typeof newValue == 'function' )
+ newValue = newValue( value, element, name );
+
+ // Return an couple indicate both name and value
+ // changed.
+ if ( newValue && newValue.push )
+ name = newValue[ 0 ], newValue = newValue[ 1 ];
+
+ if ( typeof newValue == 'string' )
+ rules.push( [ name, newValue ] );
+ return;
+ }
+ }
+ }
+
+ !whitelist && rules.push( [ name, value ] );
+
+ });
+
+ for ( var i = 0 ; i < rules.length ; i++ )
+ rules[ i ] = rules[ i ].join( ':' );
+ return rules.length ?
+ ( rules.join( ';' ) + ';' ) : false;
+ };
+ },
+
+ /**
+ * Migrate the element by decorate styles on it.
+ * @param styleDefiniton
+ * @param variables
+ */
+ elementMigrateFilter : function ( styleDefiniton, variables )
+ {
+ return function( element )
+ {
+ var styleDef =
+ variables ?
+ new CKEDITOR.style( styleDefiniton, variables )._.definition
+ : styleDefiniton;
+ element.name = styleDef.element;
+ CKEDITOR.tools.extend( element.attributes, CKEDITOR.tools.clone( styleDef.attributes ) );
+ element.addStyle( CKEDITOR.style.getStyleText( styleDef ) );
+ };
+ },
+
+ /**
+ * Migrate styles by creating a new nested stylish element.
+ * @param styleDefinition
+ */
+ styleMigrateFilter : function( styleDefinition, variableName )
+ {
+
+ var elementMigrateFilter = this.elementMigrateFilter;
+ return function( value, element )
+ {
+ // Build an stylish element first.
+ var styleElement = new CKEDITOR.htmlParser.element( null ),
+ variables = {};
+
+ variables[ variableName ] = value;
+ elementMigrateFilter( styleDefinition, variables )( styleElement );
+ // Place the new element inside the existing span.
+ styleElement.children = element.children;
+ element.children = [ styleElement ];
+ };
+ },
+
+ /**
+ * A filter which remove cke-namespaced-attribute on
+ * all none-cke-namespaced elements.
+ * @param value
+ * @param element
+ */
+ bogusAttrFilter : function( value, element )
+ {
+ if ( element.name.indexOf( 'cke:' ) == -1 )
+ return false;
+ },
+
+ /**
+ * A filter which will be used to apply inline css style according the stylesheet
+ * definition rules, is generated lazily when filtering.
+ */
+ applyStyleFilter : null
+
+ },
+
+ getRules : function( editor )
+ {
+ var dtd = CKEDITOR.dtd,
+ blockLike = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent ),
+ config = editor.config,
+ filters = this.filters,
+ falsyFilter = filters.falsyFilter,
+ stylesFilter = filters.stylesFilter,
+ elementMigrateFilter = filters.elementMigrateFilter,
+ styleMigrateFilter = CKEDITOR.tools.bind( this.filters.styleMigrateFilter, this.filters ),
+ bogusAttrFilter = filters.bogusAttrFilter,
+ createListBulletMarker = this.utils.createListBulletMarker,
+ flattenList = filters.flattenList,
+ assembleList = filters.assembleList,
+ isListBulletIndicator = this.utils.isListBulletIndicator,
+ containsNothingButSpaces = this.utils.isContainingOnlySpaces,
+ resolveListItem = this.utils.resolveList,
+ convertToPx = this.utils.convertToPx,
+ getStyleComponents = this.utils.getStyleComponents,
+ listDtdParents = this.utils.listDtdParents,
+ removeFontStyles = config.pasteFromWordRemoveFontStyles !== false,
+ removeStyles = config.pasteFromWordRemoveStyles !== false;
+
+ return {
+
+ elementNames :
+ [
+ // Remove script, meta and link elements.
+ [ ( /meta|link|script/ ), '' ]
+ ],
+
+ root : function( element )
+ {
+ element.filterChildren();
+ assembleList( element );
+ },
+
+ elements :
+ {
+ '^' : function( element )
+ {
+ // Transform CSS style declaration to inline style.
+ var applyStyleFilter;
+ if ( CKEDITOR.env.gecko && ( applyStyleFilter = filters.applyStyleFilter ) )
+ applyStyleFilter( element );
+ },
+
+ $ : function( element )
+ {
+ var tagName = element.name || '',
+ attrs = element.attributes;
+
+ // Convert length unit of width/height on blocks to
+ // a more editor-friendly way (px).
+ if ( tagName in blockLike
+ && attrs.style )
+ {
+ attrs.style = stylesFilter(
+ [ [ ( /^(:?width|height)$/ ), null, convertToPx ] ] )( attrs.style ) || '';
+ }
+
+ // Processing headings.
+ if ( tagName.match( /h\d/ ) )
+ {
+ element.filterChildren();
+ // Is the heading actually a list item?
+ if ( resolveListItem( element ) )
+ return;
+
+ // Adapt heading styles to editor's convention.
+ elementMigrateFilter( config[ 'format_' + tagName ] )( element );
+ }
+ // Remove inline elements which contain only empty spaces.
+ else if ( tagName in dtd.$inline )
+ {
+ element.filterChildren();
+ if ( containsNothingButSpaces( element ) )
+ delete element.name;
+ }
+ // Remove element with ms-office namespace,
+ // with it's content preserved, e.g. 'o:p'.
+ else if ( tagName.indexOf( ':' ) != -1
+ && tagName.indexOf( 'cke' ) == -1 )
+ {
+ element.filterChildren();
+
+ // Restore image real link from vml.
+ if ( tagName == 'v:imagedata' )
+ {
+ var href = element.attributes[ 'o:href' ];
+ if ( href )
+ element.attributes.src = href;
+ element.name = 'img';
+ return;
+ }
+ delete element.name;
+ }
+
+ // Assembling list items into a whole list.
+ if ( tagName in listDtdParents )
+ {
+ element.filterChildren();
+ assembleList( element );
+ }
+ },
+
+ // We'll drop any style sheet, but Firefox conclude
+ // certain styles in a single style element, which are
+ // required to be changed into inline ones.
+ 'style' : function( element )
+ {
+ if ( CKEDITOR.env.gecko )
+ {
+ // Grab only the style definition section.
+ var styleDefSection = element.onlyChild().value.match( /\/\* Style Definitions \*\/([\s\S]*?)\/\*/ ),
+ styleDefText = styleDefSection && styleDefSection[ 1 ],
+ rules = {}; // Storing the parsed result.
+
+ if ( styleDefText )
+ {
+ styleDefText
+ // Remove line-breaks.
+ .replace(/[\n\r]/g,'')
+ // Extract selectors and style properties.
+ .replace( /(.+?)\{(.+?)\}/g,
+ function( rule, selectors, styleBlock )
+ {
+ selectors = selectors.split( ',' );
+ var length = selectors.length, selector;
+ for ( var i = 0; i < length; i++ )
+ {
+ // Assume MS-Word mostly generate only simple
+ // selector( [Type selector][Class selector]).
+ CKEDITOR.tools.trim( selectors[ i ] )
+ .replace( /^(\w+)(\.[\w-]+)?$/g,
+ function( match, tagName, className )
+ {
+ tagName = tagName || '*';
+ className = className.substring( 1, className.length );
+
+ // Reject MS-Word Normal styles.
+ if ( className.match( /MsoNormal/ ) )
+ return;
+
+ if ( !rules[ tagName ] )
+ rules[ tagName ] = {};
+ if ( className )
+ rules[ tagName ][ className ] = styleBlock;
+ else
+ rules[ tagName ] = styleBlock;
+ } );
+ }
+ });
+
+ filters.applyStyleFilter = function( element )
+ {
+ var name = rules[ '*' ] ? '*' : element.name,
+ className = element.attributes && element.attributes[ 'class' ],
+ style;
+ if ( name in rules )
+ {
+ style = rules[ name ];
+ if ( typeof style == 'object' )
+ style = style[ className ];
+ // Maintain style rules priorities.
+ style && element.addStyle( style, true );
+ }
+ };
+ }
+ }
+ return false;
+ },
+
+ 'p' : function( element )
+ {
+ element.filterChildren();
+
+ var attrs = element.attributes,
+ parent = element.parent,
+ children = element.children;
+
+ // Is the paragraph actually a list item?
+ if ( resolveListItem( element ) )
+ return;
+
+ // Adapt paragraph formatting to editor's convention
+ // according to enter-mode.
+ if ( config.enterMode == CKEDITOR.ENTER_BR )
+ {
+ // We suffer from attribute/style lost in this situation.
+ delete element.name;
+ element.add( new CKEDITOR.htmlParser.element( 'br' ) );
+ }
+ else
+ elementMigrateFilter( config[ 'format_' + ( config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ] )( element );
+ },
+
+ 'div' : function( element )
+ {
+ // Aligned table with no text surrounded is represented by a wrapper div, from which
+ // table cells inherit as text-align styles, which is wrong.
+ // Instead we use a clear-float div after the table to properly achieve the same layout.
+ var singleChild = element.onlyChild();
+ if ( singleChild && singleChild.name == 'table' )
+ {
+ var attrs = element.attributes;
+ singleChild.attributes = CKEDITOR.tools.extend( singleChild.attributes, attrs );
+ attrs.style && singleChild.addStyle( attrs.style );
+
+ var clearFloatDiv = new CKEDITOR.htmlParser.element( 'div' );
+ clearFloatDiv.addStyle( 'clear' ,'both' );
+ element.add( clearFloatDiv );
+ delete element.name;
+ }
+ },
+
+ 'td' : function ( element )
+ {
+ // 'td' in 'thead' is actually .
+ if ( element.getAncestor( 'thead') )
+ element.name = 'th';
+ },
+
+ // MS-Word sometimes present list as a mixing of normal list
+ // and pseudo-list, normalize the previous ones into pseudo form.
+ 'ol' : flattenList,
+ 'ul' : flattenList,
+ 'dl' : flattenList,
+
+ 'font' : function( element )
+ {
+ // IE/Safari: drop the font tag if it comes from list bullet text.
+ if ( !CKEDITOR.env.gecko && isListBulletIndicator( element.parent ) )
+ {
+ delete element.name;
+ return;
+ }
+
+ element.filterChildren();
+
+ var attrs = element.attributes,
+ styleText = attrs.style,
+ parent = element.parent;
+
+ if ( 'font' == parent.name ) // Merge nested tags.
+ {
+ CKEDITOR.tools.extend( parent.attributes,
+ element.attributes );
+ styleText && parent.addStyle( styleText );
+ delete element.name;
+ return;
+ }
+ // Convert the merged into a span with all attributes preserved.
+ else
+ {
+ styleText = styleText || '';
+ // IE's having those deprecated attributes, normalize them.
+ if ( attrs.color )
+ {
+ attrs.color != '#000000' && ( styleText += 'color:' + attrs.color + ';' );
+ delete attrs.color;
+ }
+ if ( attrs.face )
+ {
+ styleText += 'font-family:' + attrs.face + ';';
+ delete attrs.face;
+ }
+ // TODO: Mapping size in ranges of xx-small,
+ // x-small, small, medium, large, x-large, xx-large.
+ if ( attrs.size )
+ {
+ styleText += 'font-size:' +
+ ( attrs.size > 3 ? 'large'
+ : ( attrs.size < 3 ? 'small' : 'medium' ) ) + ';';
+ delete attrs.size;
+ }
+
+ element.name = 'span';
+ element.addStyle( styleText );
+ }
+ },
+
+ 'span' : function( element )
+ {
+ // IE/Safari: remove the span if it comes from list bullet text.
+ if ( !CKEDITOR.env.gecko && isListBulletIndicator( element.parent ) )
+ return false;
+
+ element.filterChildren();
+ if ( containsNothingButSpaces( element ) )
+ {
+ delete element.name;
+ return null;
+ }
+
+ // For IE/Safari: List item bullet type is supposed to be indicated by
+ // the text of a span with style 'mso-list : Ignore' or an image.
+ if ( !CKEDITOR.env.gecko && isListBulletIndicator( element ) )
+ {
+ var listSymbolNode = element.firstChild( function( node )
+ {
+ return node.value || node.name == 'img';
+ });
+
+ var listSymbol = listSymbolNode && ( listSymbolNode.value || 'l.' ),
+ listType = listSymbol.match( /^([^\s]+?)([.)]?)$/ );
+ return createListBulletMarker( listType, listSymbol );
+ }
+
+ // Update the src attribute of image element with href.
+ var children = element.children,
+ attrs = element.attributes,
+ styleText = attrs && attrs.style,
+ firstChild = children && children[ 0 ];
+
+ // Assume MS-Word mostly carry font related styles on ,
+ // adapting them to editor's convention.
+ if ( styleText )
+ {
+ attrs.style = stylesFilter(
+ [
+ // Drop 'inline-height' style which make lines overlapping.
+ [ 'line-height' ],
+ [ ( /^font-family$/ ), null, !removeFontStyles ? styleMigrateFilter( config[ 'font_style' ], 'family' ) : null ] ,
+ [ ( /^font-size$/ ), null, !removeFontStyles ? styleMigrateFilter( config[ 'fontSize_style' ], 'size' ) : null ] ,
+ [ ( /^color$/ ), null, !removeFontStyles ? styleMigrateFilter( config[ 'colorButton_foreStyle' ], 'color' ) : null ] ,
+ [ ( /^background-color$/ ), null, !removeFontStyles ? styleMigrateFilter( config[ 'colorButton_backStyle' ], 'color' ) : null ]
+ ] )( styleText, element ) || '';
+ }
+
+ return null;
+ },
+
+ // Migrate basic style formats to editor configured ones.
+ 'b' : elementMigrateFilter( config[ 'coreStyles_bold' ] ),
+ 'i' : elementMigrateFilter( config[ 'coreStyles_italic' ] ),
+ 'u' : elementMigrateFilter( config[ 'coreStyles_underline' ] ),
+ 's' : elementMigrateFilter( config[ 'coreStyles_strike' ] ),
+ 'sup' : elementMigrateFilter( config[ 'coreStyles_superscript' ] ),
+ 'sub' : elementMigrateFilter( config[ 'coreStyles_subscript' ] ),
+ // Editor doesn't support anchor with content currently (#3582),
+ // drop such anchors with content preserved.
+ 'a' : function( element )
+ {
+ var attrs = element.attributes;
+ if ( attrs && !attrs.href && attrs.name )
+ delete element.name;
+ },
+ 'cke:listbullet' : function( element )
+ {
+ if ( element.getAncestor( /h\d/ ) && !config.pasteFromWordNumberedHeadingToList )
+ delete element.name;
+ }
+ },
+
+ attributeNames :
+ [
+ // Remove onmouseover and onmouseout events (from MS Word comments effect)
+ [ ( /^onmouse(:?out|over)/ ), '' ],
+ // Onload on image element.
+ [ ( /^onload$/ ), '' ],
+ // Remove office and vml attribute from elements.
+ [ ( /(?:v|o):\w+/ ), '' ],
+ // Remove lang/language attributes.
+ [ ( /^lang/ ), '' ]
+ ],
+
+ attributes :
+ {
+ 'style' : stylesFilter(
+ removeStyles ?
+ // Provide a white-list of styles that we preserve, those should
+ // be the ones that could later be altered with editor tools.
+ [
+ // Preserve margin-left/right which used as default indent style in the editor.
+ [ ( /^margin$|^margin-(?!bottom|top)/ ), null, function( value, element, name )
+ {
+ if ( element.name in { p : 1, div : 1 } )
+ {
+ var indentStyleName = config.contentsLangDirection == 'ltr' ?
+ 'margin-left' : 'margin-right';
+
+ // Extract component value from 'margin' shorthand.
+ if ( name == 'margin' )
+ {
+ value = getStyleComponents( name, value,
+ [ indentStyleName ] )[ indentStyleName ];
+ }
+ else if ( name != indentStyleName )
+ return null;
+
+ if ( value && !emptyMarginRegex.test( value ) )
+ return [ indentStyleName, value ];
+ }
+
+ return null;
+ } ],
+
+ // Preserve clear float style.
+ [ ( /^clear$/ ) ],
+
+ [ ( /^border.*|margin.*|vertical-align|float$/ ), null,
+ function( value, element )
+ {
+ if ( element.name == 'img' )
+ return value;
+ } ],
+
+ [ (/^width|height$/ ), null,
+ function( value, element )
+ {
+ if ( element.name in { table : 1, td : 1, th : 1, img : 1 } )
+ return value;
+ } ]
+ ] :
+ // Otherwise provide a black-list of styles that we remove.
+ [
+ [ ( /^mso-/ ) ],
+ // Fixing color values.
+ [ ( /-color$/ ), null, function( value )
+ {
+ if ( value == 'transparent' )
+ return false;
+ if ( CKEDITOR.env.gecko )
+ return value.replace( /-moz-use-text-color/g, 'transparent' );
+ } ],
+ // Remove empty margin values, e.g. 0.00001pt 0em 0pt
+ [ ( /^margin$/ ), emptyMarginRegex ],
+ [ 'text-indent', '0cm' ],
+ [ 'page-break-before' ],
+ [ 'tab-stops' ],
+ [ 'display', 'none' ],
+ removeFontStyles ? [ ( /font-?/ ) ] : null
+ ], removeStyles ),
+
+ // Prefer width styles over 'width' attributes.
+ 'width' : function( value, element )
+ {
+ if ( element.name in dtd.$tableContent )
+ return false;
+ },
+ // Prefer border styles over table 'border' attributes.
+ 'border' : function( value, element )
+ {
+ if ( element.name in dtd.$tableContent )
+ return false;
+ },
+
+ // Only Firefox carry style sheet from MS-Word, which
+ // will be applied by us manually. For other browsers
+ // the css className is useless.
+ 'class' : falsyFilter,
+
+ // MS-Word always generate 'background-color' along with 'bgcolor',
+ // simply drop the deprecated attributes.
+ 'bgcolor' : falsyFilter,
+
+ // Deprecate 'valign' attribute in favor of 'vertical-align'.
+ 'valign' : removeStyles ? falsyFilter : function( value, element )
+ {
+ element.addStyle( 'vertical-align', value );
+ return false;
+ }
+ },
+
+ // Fore none-IE, some useful data might be buried under these IE-conditional
+ // comments where RegExp were the right approach to dig them out where usual approach
+ // is transform it into a fake element node which hold the desired data.
+ comment :
+ !CKEDITOR.env.ie ?
+ function( value, node )
+ {
+ var imageInfo = value.match( // ),
+ listInfo = value.match( /^\[if !supportLists\]([\s\S]*?)\[endif\]$/ );
+
+ // Seek for list bullet indicator.
+ if ( listInfo )
+ {
+ // Bullet symbol could be either text or an image.
+ var listSymbol = listInfo[ 1 ] || ( imageInfo && 'l.' ),
+ listType = listSymbol && listSymbol.match( />([^\s]+?)([.)]?) );
+ return createListBulletMarker( listType, listSymbol );
+ }
+
+ // Reveal the element in conditional comments for Firefox.
+ if ( CKEDITOR.env.gecko && imageInfo )
+ {
+ var img = CKEDITOR.htmlParser.fragment.fromHtml( imageInfo[ 0 ] ).children[ 0 ],
+ previousComment = node.previous,
+ // Try to dig the real image link from vml markup from previous comment text.
+ imgSrcInfo = previousComment && previousComment.value.match( /]*o:href=['"](.*?)['"]/ ),
+ imgSrc = imgSrcInfo && imgSrcInfo[ 1 ];
+
+ // Is there a real 'src' url to be used?
+ imgSrc && ( img.attributes.src = imgSrc );
+ return img;
+ }
+
+ return false;
+ }
+ : falsyFilter
+ };
+ }
+ };
+
+ // The paste processor here is just a reduced copy of html data processor.
+ var pasteProcessor = function()
+ {
+ this.dataFilter = new CKEDITOR.htmlParser.filter();
+ };
+
+ pasteProcessor.prototype =
+ {
+ toHtml : function( data )
+ {
+ var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data, false ),
+ writer = new CKEDITOR.htmlParser.basicWriter();
+
+ fragment.writeHtml( writer, this.dataFilter );
+ return writer.getHtml( true );
+ }
+ };
+
+ CKEDITOR.cleanWord = function( data, editor )
+ {
+ // Firefox will be confused by those downlevel-revealed IE conditional
+ // comments, fixing them first( convert it to upperlevel-revealed one ).
+ // e.g. ...
+ if ( CKEDITOR.env.gecko )
+ data = data.replace( /(([\S\s]*?))/gi, '$1$2$3' );
+
+ var dataProcessor = new pasteProcessor(),
+ dataFilter = dataProcessor.dataFilter;
+
+ // These rules will have higher priorities than default ones.
+ dataFilter.addRules( CKEDITOR.plugins.pastefromword.getRules( editor ) );
+
+ // Allow extending data filter rules.
+ editor.fire( 'beforeCleanWord', { filter : dataFilter } );
+
+ try
+ {
+ data = dataProcessor.toHtml( data, false );
+ }
+ catch ( e )
+ {
+ alert( editor.lang.pastefromword.error );
+ }
+
+ /* Below post processing those things that are unable to delivered by filter rules. */
+
+ // Remove 'cke' namespaced attribute used in filter rules as marker.
+ data = data.replace( /cke:.*?".*?"/g, '' );
+
+ // Remove empty style attribute.
+ data = data.replace( /style=""/g, '' );
+
+ // Remove the dummy spans ( having no inline style ).
+ data = data.replace( //g, '' );
+
+ return data;
+ };
+})();
+
+/**
+ * Whether to ignore all font related formatting styles, including:
+ * font size;
+ * font family;
+ * font foreground/background color.
+ * @name CKEDITOR.config.pasteFromWordRemoveFontStyles
+ * @since 3.1
+ * @type Boolean
+ * @default true
+ * @example
+ * config.pasteFromWordRemoveFontStyles = false;
+ */
+
+/**
+ * Whether to transform MS Word outline numbered headings into lists.
+ * @name CKEDITOR.config.pasteFromWordNumberedHeadingToList
+ * @since 3.1
+ * @type Boolean
+ * @default false
+ * @example
+ * config.pasteFromWordNumberedHeadingToList = true;
+ */
+
+/**
+ * Whether to remove element styles that can't be managed with the editor. Note
+ * that this doesn't handle the font specific styles, which depends on the
+ * {@link CKEDITOR.config.pasteFromWordRemoveFontStyles} setting instead.
+ * @name CKEDITOR.config.pasteFromWordRemoveStyles
+ * @since 3.1
+ * @type Boolean
+ * @default true
+ * @example
+ * config.pasteFromWordRemoveStyles = false;
+ */
diff --git a/webroot/js/ckeditor/_source/plugins/showborders/plugin.js b/webroot/js/ckeditor/_source/plugins/showborders/plugin.js
new file mode 100755
index 00000000..4fc46b6b
--- /dev/null
+++ b/webroot/js/ckeditor/_source/plugins/showborders/plugin.js
@@ -0,0 +1,170 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview The "show border" plugin. The command display visible outline
+ * border line around all table elements if table doesn't have a none-zero 'border' attribute specified.
+ */
+
+(function()
+{
+ var showBorderClassName = 'cke_show_border',
+ cssStyleText,
+ cssTemplate =
+ // TODO: For IE6, we don't have child selector support,
+ // where nested table cells could be incorrect.
+ ( CKEDITOR.env.ie6Compat ?
+ [
+ '.%1 table.%2,',
+ '.%1 table.%2 td, .%1 table.%2 th,',
+ '{',
+ 'border : #d3d3d3 1px dotted',
+ '}'
+ ] :
+ [
+ '.%1 table.%2,',
+ '.%1 table.%2 > tr > td, .%1 table.%2 > tr > th,',
+ '.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,',
+ '.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,',
+ '.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th',
+ '{',
+ 'border : #d3d3d3 1px dotted',
+ '}'
+ ] ).join( '' );
+
+ cssStyleText = cssTemplate.replace( /%2/g, showBorderClassName ).replace( /%1/g, 'cke_show_borders ' );
+
+ var commandDefinition =
+ {
+ preserveState : true,
+ editorFocus : false,
+
+ exec : function ( editor )
+ {
+ this.toggleState();
+ this.refresh( editor );
+ },
+
+ refresh : function( editor )
+ {
+ var funcName = ( this.state == CKEDITOR.TRISTATE_ON ) ? 'addClass' : 'removeClass';
+ editor.document.getBody()[ funcName ]( 'cke_show_borders' );
+ }
+ };
+
+ CKEDITOR.plugins.add( 'showborders',
+ {
+ requires : [ 'wysiwygarea' ],
+ modes : { 'wysiwyg' : 1 },
+
+ init : function( editor )
+ {
+
+ var command = editor.addCommand( 'showborders', commandDefinition );
+ command.canUndo = false;
+
+ if ( editor.config.startupShowBorders !== false )
+ command.setState( CKEDITOR.TRISTATE_ON );
+
+ editor.addCss( cssStyleText );
+
+ // Refresh the command on setData.
+ editor.on( 'mode', function()
+ {
+ if ( command.state != CKEDITOR.TRISTATE_DISABLED )
+ command.refresh( editor );
+ }, null, null, 100 );
+
+ // Refresh the command on wysiwyg frame reloads.
+ editor.on( 'contentDom', function()
+ {
+ if ( command.state != CKEDITOR.TRISTATE_DISABLED )
+ command.refresh( editor );
+ });
+ },
+
+ afterInit : function( editor )
+ {
+ var dataProcessor = editor.dataProcessor,
+ dataFilter = dataProcessor && dataProcessor.dataFilter,
+ htmlFilter = dataProcessor && dataProcessor.htmlFilter;
+
+ if ( dataFilter )
+ {
+ dataFilter.addRules(
+ {
+ elements :
+ {
+ 'table' : function( element )
+ {
+ var attributes = element.attributes,
+ cssClass = attributes[ 'class' ],
+ border = parseInt( attributes.border, 10 );
+
+ if ( !border || border <= 0 )
+ attributes[ 'class' ] = ( cssClass || '' ) + ' ' + showBorderClassName;
+ }
+ }
+ } );
+ }
+
+ if ( htmlFilter )
+ {
+ htmlFilter.addRules(
+ {
+ elements :
+ {
+ 'table' : function( table )
+ {
+ var attributes = table.attributes,
+ cssClass = attributes[ 'class' ];
+
+ cssClass && ( attributes[ 'class' ] =
+ cssClass.replace( showBorderClassName, '' )
+ .replace( /\s{2}/, ' ' )
+ .replace( /^\s+|\s+$/, '' ) );
+ }
+ }
+ } );
+ }
+
+ // Table dialog must be aware of it.
+ CKEDITOR.on( 'dialogDefinition', function( ev )
+ {
+ if ( ev.editor != editor )
+ return;
+
+ var dialogName = ev.data.name;
+
+ if ( dialogName == 'table' || dialogName == 'tableProperties' )
+ {
+ var dialogDefinition = ev.data.definition,
+ infoTab = dialogDefinition.getContents( 'info' ),
+ borderField = infoTab.get( 'txtBorder' ),
+ originalCommit = borderField.commit;
+
+ borderField.commit = CKEDITOR.tools.override( originalCommit, function( org )
+ {
+ return function( data, selectedTable )
+ {
+ org.apply( this, arguments );
+ var value = parseInt( this.getValue(), 10 );
+ selectedTable[ ( !value || value <= 0 ) ? 'addClass' : 'removeClass' ]( showBorderClassName );
+ };
+ } );
+ }
+ });
+ }
+
+ });
+} )();
+
+/**
+ * Whether to automatically enable the "show borders" command when the editor loads.
+ * @type Boolean
+ * @default true
+ * @example
+ * config.startupShowBorders = false;
+ */
diff --git a/webroot/js/ckeditor/adapters/jquery.js b/webroot/js/ckeditor/adapters/jquery.js
new file mode 100755
index 00000000..a70f6b3a
--- /dev/null
+++ b/webroot/js/ckeditor/adapters/jquery.js
@@ -0,0 +1,6 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function(){CKEDITOR.config.jqueryOverrideVal=typeof CKEDITOR.config.jqueryOverrideVal=='undefined'?true:CKEDITOR.config.jqueryOverrideVal;var a=window.jQuery;if(typeof a=='undefined')return;a.extend(a.fn,{ckeditorGet:function(){var b=this.eq(0).data('ckeditorInstance');if(!b)throw 'CKEditor not yet initialized, use ckeditor() with callback.';return b;},ckeditor:function(b,c){if(!a.isFunction(b)){var d=c;c=b;b=d;}c=c||{};this.filter('textarea, div, p').each(function(){var e=a(this),f=e.data('ckeditorInstance'),g=e.data('_ckeditorInstanceLock'),h=this;if(f&&!g){if(b)b.apply(f,[this]);}else if(!g){if(c.autoUpdateElement||typeof c.autoUpdateElement=='undefined'&&CKEDITOR.config.autoUpdateElement)c.autoUpdateElementJquery=true;c.autoUpdateElement=false;e.data('_ckeditorInstanceLock',true);f=CKEDITOR.replace(h,c);e.data('ckeditorInstance',f);f.on('instanceReady',function(i){var j=i.editor;setTimeout(function(){if(!j.element){setTimeout(arguments.callee,100);return;}i.removeListener('instanceReady',this.callee);j.on('dataReady',function(){e.trigger('setData.ckeditor',[j]);});j.on('getData',function(l){e.trigger('getData.ckeditor',[j,l.data]);},999);j.on('destroy',function(){e.trigger('destroy.ckeditor',[j]);});if(j.config.autoUpdateElementJquery&&e.is('textarea')&&e.parents('form').length){var k=function(){e.ckeditor(function(){j.updateElement();});};e.parents('form').submit(k);e.parents('form').bind('form-pre-serialize',k);e.bind('destroy.ckeditor',function(){e.parents('form').unbind('submit',k);e.parents('form').unbind('form-pre-serialize',k);});}j.on('destroy',function(){e.data('ckeditorInstance',null);});e.data('_ckeditorInstanceLock',null);e.trigger('instanceReady.ckeditor',[j]);if(b)b.apply(j,[h]);},0);},null,null,9999);}else CKEDITOR.on('instanceReady',function(i){var j=i.editor;setTimeout(function(){if(!j.element){setTimeout(arguments.callee,100);return;}if(j.element.$==h)if(b)b.apply(j,[h]);},0);},null,null,9999);});return this;}});if(CKEDITOR.config.jqueryOverrideVal)a.fn.val=CKEDITOR.tools.override(a.fn.val,function(b){return function(c,d){var e=typeof c!='undefined',f;this.each(function(){var g=a(this),h=g.data('ckeditorInstance');if(!d&&g.is('textarea')&&h){if(e)h.setData(c);else{f=h.getData();return null;}}else if(e)b.call(g,c);else{f=b.call(g);return null;}return true;});return e?this:f;};});})();
diff --git a/webroot/js/ckeditor/ckeditor.php b/webroot/js/ckeditor/ckeditor.php
new file mode 100755
index 00000000..edbc7037
--- /dev/null
+++ b/webroot/js/ckeditor/ckeditor.php
@@ -0,0 +1,29 @@
+CKEditor web site to find more information about the editor.
+ * \section install_sec Installation
+ * \subsection step1 Include ckeditor.php in your PHP web site.
+ * @code
+ *
+ * @endcode
+ * \subsection step2 Create CKEditor class instance and use one of available methods to insert CKEditor.
+ * @code
+ * textarea("field1", "Initial value.
");
+ * ?>
+ * @endcode
+ */
+
+if ( !function_exists('version_compare') || version_compare( phpversion(), '5', '<' ) )
+ include_once( 'ckeditor_php4.php' ) ;
+else
+ include_once( 'ckeditor_php5.php' ) ;
diff --git a/webroot/js/ckeditor/ckeditor_php4.php b/webroot/js/ckeditor/ckeditor_php4.php
new file mode 100755
index 00000000..699d7e59
--- /dev/null
+++ b/webroot/js/ckeditor/ckeditor_php4.php
@@ -0,0 +1,593 @@
+editor("editor1", "Initial value.
");
+ * @endcode
+ */
+class CKEditor
+{
+ /**
+ * The version of %CKEditor.
+ * \private
+ */
+ var $version = '3.2';
+ /**
+ * A constant string unique for each release of %CKEditor.
+ * \private
+ */
+ var $_timestamp = 'A1QD';
+
+ /**
+ * URL to the %CKEditor installation directory (absolute or relative to document root).
+ * If not set, CKEditor will try to guess it's path.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->basePath = '/ckeditor/';
+ * @endcode
+ */
+ var $basePath;
+ /**
+ * An array that holds the global %CKEditor configuration.
+ * For the list of available options, see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->config['height'] = 400;
+ * // Use @@ at the beggining of a string to ouput it without surrounding quotes.
+ * $CKEditor->config['width'] = '@@screen.width * 0.8';
+ * @endcode
+ */
+ var $config = array();
+ /**
+ * A boolean variable indicating whether CKEditor has been initialized.
+ * Set it to true only if you have already included
+ * <script> tag loading ckeditor.js in your website.
+ */
+ var $initialized = false;
+ /**
+ * Boolean variable indicating whether created code should be printed out or returned by a function.
+ *
+ * Example 1: get the code creating %CKEditor instance and print it on a page with the "echo" function.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->returnOutput = true;
+ * $code = $CKEditor->editor("editor1", "Initial value.
");
+ * echo "Editor 1:
";
+ * echo $code;
+ * @endcode
+ */
+ var $returnOutput = false;
+ /**
+ * An array with textarea attributes.
+ *
+ * When %CKEditor is created with the editor() method, a HTML <textarea> element is created,
+ * it will be displayed to anyone with JavaScript disabled or with incompatible browser.
+ */
+ var $textareaAttributes = array( "rows" => 8, "cols" => 60 );
+ /**
+ * A string indicating the creation date of %CKEditor.
+ * Do not change it unless you want to force browsers to not use previously cached version of %CKEditor.
+ */
+ var $timestamp = "A1QD";
+ /**
+ * An array that holds event listeners.
+ * \private
+ */
+ var $_events = array();
+ /**
+ * An array that holds global event listeners.
+ * \private
+ */
+ var $_globalEvents = array();
+
+ /**
+ * Main Constructor.
+ *
+ * @param $basePath (string) URL to the %CKEditor installation directory (optional).
+ */
+ function CKEditor($basePath = null) {
+ if (!empty($basePath)) {
+ $this->basePath = $basePath;
+ }
+ }
+
+ /**
+ * Creates a %CKEditor instance.
+ * In incompatible browsers %CKEditor will downgrade to plain HTML <textarea> element.
+ *
+ * @param $name (string) Name of the %CKEditor instance (this will be also the "name" attribute of textarea element).
+ * @param $value (string) Initial value (optional).
+ * @param $config (array) The specific configurations to apply to this editor instance (optional).
+ * @param $events (array) Event listeners for this editor instance (optional).
+ *
+ * Example usage:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->editor("field1", "Initial value.
");
+ * @endcode
+ *
+ * Advanced example:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $config = array();
+ * $config['toolbar'] = array(
+ * array( 'Source', '-', 'Bold', 'Italic', 'Underline', 'Strike' ),
+ * array( 'Image', 'Link', 'Unlink', 'Anchor' )
+ * );
+ * $events['instanceReady'] = 'function (ev) {
+ * alert("Loaded: " + ev.editor.name);
+ * }';
+ * $CKEditor->editor("field1", "Initial value.
", $config, $events);
+ * @endcode
+ */
+ function editor($name, $value = "", $config = array(), $events = array())
+ {
+ $attr = "";
+ foreach ($this->textareaAttributes as $key => $val) {
+ $attr.= " " . $key . '="' . str_replace('"', '"', $val) . '"';
+ }
+ $out = "" . htmlspecialchars($value) . " \n";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings($config, $events);
+
+ $js = $this->returnGlobalEvents();
+ if (!empty($_config))
+ $js .= "CKEDITOR.replace('".$name."', ".$this->jsEncode($_config).");";
+ else
+ $js .= "CKEDITOR.replace('".$name."');";
+
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Replaces a <textarea> with a %CKEditor instance.
+ *
+ * @param $id (string) The id or name of textarea element.
+ * @param $config (array) The specific configurations to apply to this editor instance (optional).
+ * @param $events (array) Event listeners for this editor instance (optional).
+ *
+ * Example 1: adding %CKEditor to <textarea name="article"></textarea> element:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replace("article");
+ * @endcode
+ */
+ function replace($id, $config = array(), $events = array())
+ {
+ $out = "";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings($config, $events);
+
+ $js = $this->returnGlobalEvents();
+ if (!empty($_config)) {
+ $js .= "CKEDITOR.replace('".$id."', ".$this->jsEncode($_config).");";
+ }
+ else {
+ $js .= "CKEDITOR.replace('".$id."');";
+ }
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Replace all <textarea> elements available in the document with editor instances.
+ *
+ * @param $className (string) If set, replace all textareas with class className in the page.
+ *
+ * Example 1: replace all <textarea> elements in the page.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replaceAll();
+ * @endcode
+ *
+ * Example 2: replace all <textarea class="myClassName"> elements in the page.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replaceAll( 'myClassName' );
+ * @endcode
+ */
+ function replaceAll($className = null)
+ {
+ $out = "";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings();
+
+ $js = $this->returnGlobalEvents();
+ if (empty($_config)) {
+ if (empty($className)) {
+ $js .= "CKEDITOR.replaceAll();";
+ }
+ else {
+ $js .= "CKEDITOR.replaceAll('".$className."');";
+ }
+ }
+ else {
+ $classDetection = "";
+ $js .= "CKEDITOR.replaceAll( function(textarea, config) {\n";
+ if (!empty($className)) {
+ $js .= " var classRegex = new RegExp('(?:^| )' + '". $className ."' + '(?:$| )');\n";
+ $js .= " if (!classRegex.test(textarea.className))\n";
+ $js .= " return false;\n";
+ }
+ $js .= " CKEDITOR.tools.extend(config, ". $this->jsEncode($_config) .", true);";
+ $js .= "} );";
+
+ }
+
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Adds event listener.
+ * Events are fired by %CKEditor in various situations.
+ *
+ * @param $event (string) Event name.
+ * @param $javascriptCode (string) Javascript anonymous function or function name.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->addEventHandler('instanceReady', 'function (ev) {
+ * alert("Loaded: " + ev.editor.name);
+ * }');
+ * @endcode
+ */
+ function addEventHandler($event, $javascriptCode)
+ {
+ if (!isset($this->_events[$event])) {
+ $this->_events[$event] = array();
+ }
+ // Avoid duplicates.
+ if (!in_array($javascriptCode, $this->_events[$event])) {
+ $this->_events[$event][] = $javascriptCode;
+ }
+ }
+
+ /**
+ * Clear registered event handlers.
+ * Note: this function will have no effect on already created editor instances.
+ *
+ * @param $event (string) Event name, if not set all event handlers will be removed (optional).
+ */
+ function clearEventHandlers($event = null)
+ {
+ if (!empty($event)) {
+ $this->_events[$event] = array();
+ }
+ else {
+ $this->_events = array();
+ }
+ }
+
+ /**
+ * Adds global event listener.
+ *
+ * @param $event (string) Event name.
+ * @param $javascriptCode (string) Javascript anonymous function or function name.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->addGlobalEventHandler('dialogDefinition', 'function (ev) {
+ * alert("Loading dialog: " + ev.data.name);
+ * }');
+ * @endcode
+ */
+ function addGlobalEventHandler($event, $javascriptCode)
+ {
+ if (!isset($this->_globalEvents[$event])) {
+ $this->_globalEvents[$event] = array();
+ }
+ // Avoid duplicates.
+ if (!in_array($javascriptCode, $this->_globalEvents[$event])) {
+ $this->_globalEvents[$event][] = $javascriptCode;
+ }
+ }
+
+ /**
+ * Clear registered global event handlers.
+ * Note: this function will have no effect if the event handler has been already printed/returned.
+ *
+ * @param $event (string) Event name, if not set all event handlers will be removed (optional).
+ */
+ function clearGlobalEventHandlers($event = null)
+ {
+ if (!empty($event)) {
+ $this->_globalEvents[$event] = array();
+ }
+ else {
+ $this->_globalEvents = array();
+ }
+ }
+
+ /**
+ * Prints javascript code.
+ * \private
+ *
+ * @param string $js
+ */
+ function script($js)
+ {
+ $out = "\n";
+
+ return $out;
+ }
+
+ /**
+ * Returns the configuration array (global and instance specific settings are merged into one array).
+ * \private
+ *
+ * @param $config (array) The specific configurations to apply to editor instance.
+ * @param $events (array) Event listeners for editor instance.
+ */
+ function configSettings($config = array(), $events = array())
+ {
+ $_config = $this->config;
+ $_events = $this->_events;
+
+ if (is_array($config) && !empty($config)) {
+ $_config = array_merge($_config, $config);
+ }
+
+ if (is_array($events) && !empty($events)) {
+ foreach ($events as $eventName => $code) {
+ if (!isset($_events[$eventName])) {
+ $_events[$eventName] = array();
+ }
+ if (!in_array($code, $_events[$eventName])) {
+ $_events[$eventName][] = $code;
+ }
+ }
+ }
+
+ if (!empty($_events)) {
+ foreach($_events as $eventName => $handlers) {
+ if (empty($handlers)) {
+ continue;
+ }
+ else if (count($handlers) == 1) {
+ $_config['on'][$eventName] = '@@'.$handlers[0];
+ }
+ else {
+ $_config['on'][$eventName] = '@@function (ev){';
+ foreach ($handlers as $handler => $code) {
+ $_config['on'][$eventName] .= '('.$code.')(ev);';
+ }
+ $_config['on'][$eventName] .= '}';
+ }
+ }
+ }
+
+ return $_config;
+ }
+
+ /**
+ * Return global event handlers.
+ * \private
+ */
+ function returnGlobalEvents()
+ {
+ static $returnedEvents;
+ $out = "";
+
+ if (!isset($returnedEvents)) {
+ $returnedEvents = array();
+ }
+
+ if (!empty($this->_globalEvents)) {
+ foreach ($this->_globalEvents as $eventName => $handlers) {
+ foreach ($handlers as $handler => $code) {
+ if (!isset($returnedEvents[$eventName])) {
+ $returnedEvents[$eventName] = array();
+ }
+ // Return only new events
+ if (!in_array($code, $returnedEvents[$eventName])) {
+ $out .= ($code ? "\n" : "") . "CKEDITOR.on('". $eventName ."', $code);";
+ $returnedEvents[$eventName][] = $code;
+ }
+ }
+ }
+ }
+
+ return $out;
+ }
+
+ /**
+ * Initializes CKEditor (executed only once).
+ * \private
+ */
+ function init()
+ {
+ static $initComplete;
+ $out = "";
+
+ if (!empty($initComplete)) {
+ return "";
+ }
+
+ if ($this->initialized) {
+ $initComplete = true;
+ return "";
+ }
+
+ $args = "";
+ $ckeditorPath = $this->ckeditorPath();
+
+ if (!empty($this->timestamp) && $this->timestamp != "%"."TIMESTAMP%") {
+ $args = '?t=' . $this->timestamp;
+ }
+
+ // Skip relative paths...
+ if (strpos($ckeditorPath, '..') !== 0) {
+ $out .= $this->script("window.CKEDITOR_BASEPATH='". $ckeditorPath ."';");
+ }
+
+ $out .= "\n";
+
+ $extraCode = "";
+ if ($this->timestamp != $this->_timestamp) {
+ $extraCode .= ($extraCode ? "\n" : "") . "CKEDITOR.timestamp = '". $this->timestamp ."';";
+ }
+ if ($extraCode) {
+ $out .= $this->script($extraCode);
+ }
+
+ $initComplete = $this->initialized = true;
+
+ return $out;
+ }
+
+ /**
+ * Return path to ckeditor.js.
+ * \private
+ */
+ function ckeditorPath()
+ {
+ if (!empty($this->basePath)) {
+ return $this->basePath;
+ }
+
+ /**
+ * The absolute pathname of the currently executing script.
+ * Note: If a script is executed with the CLI, as a relative path, such as file.php or ../file.php,
+ * $_SERVER['SCRIPT_FILENAME'] will contain the relative path specified by the user.
+ */
+ if (isset($_SERVER['SCRIPT_FILENAME'])) {
+ $realPath = dirname($_SERVER['SCRIPT_FILENAME']);
+ }
+ else {
+ /**
+ * realpath — Returns canonicalized absolute pathname
+ */
+ $realPath = realpath( './' ) ;
+ }
+
+ /**
+ * The filename of the currently executing script, relative to the document root.
+ * For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar
+ * would be /test.php/foo.bar.
+ */
+ $selfPath = dirname($_SERVER['PHP_SELF']);
+ $file = str_replace("\\", "/", __FILE__);
+
+ if (!$selfPath || !$realPath || !$file) {
+ return "/ckeditor/";
+ }
+
+ $documentRoot = substr($realPath, 0, strlen($realPath) - strlen($selfPath));
+ $fileUrl = substr($file, strlen($documentRoot));
+ $ckeditorUrl = str_replace("ckeditor_php5.php", "", $fileUrl);
+
+ return $ckeditorUrl;
+ }
+
+ /**
+ * This little function provides a basic JSON support.
+ * http://php.net/manual/en/function.json-encode.php
+ * \private
+ *
+ * @param mixed $val
+ * @return string
+ */
+ function jsEncode($val)
+ {
+ if (is_null($val)) {
+ return 'null';
+ }
+ if ($val === false) {
+ return 'false';
+ }
+ if ($val === true) {
+ return 'true';
+ }
+ if (is_scalar($val))
+ {
+ if (is_float($val))
+ {
+ // Always use "." for floats.
+ $val = str_replace(",", ".", strval($val));
+ }
+
+ // Use @@ to not use quotes when outputting string value
+ if (strpos($val, '@@') === 0) {
+ return substr($val, 2);
+ }
+ else {
+ // All scalars are converted to strings to avoid indeterminism.
+ // PHP's "1" and 1 are equal for all PHP operators, but
+ // JS's "1" and 1 are not. So if we pass "1" or 1 from the PHP backend,
+ // we should get the same result in the JS frontend (string).
+ // Character replacements for JSON.
+ static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'),
+ array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
+
+ $val = str_replace($jsonReplaces[0], $jsonReplaces[1], $val);
+
+ return '"' . $val . '"';
+ }
+ }
+ $isList = true;
+ for ($i = 0, reset($val); $i < count($val); $i++, next($val))
+ {
+ if (key($val) !== $i)
+ {
+ $isList = false;
+ break;
+ }
+ }
+ $result = array();
+ if ($isList)
+ {
+ foreach ($val as $v) $result[] = $this->jsEncode($v);
+ return '[ ' . join(', ', $result) . ' ]';
+ }
+ else
+ {
+ foreach ($val as $k => $v) $result[] = $this->jsEncode($k).': '.$this->jsEncode($v);
+ return '{ ' . join(', ', $result) . ' }';
+ }
+ }
+}
diff --git a/webroot/js/ckeditor/ckeditor_php5.php b/webroot/js/ckeditor/ckeditor_php5.php
new file mode 100755
index 00000000..968a6c4d
--- /dev/null
+++ b/webroot/js/ckeditor/ckeditor_php5.php
@@ -0,0 +1,583 @@
+editor("editor1", "Initial value.
");
+ * @endcode
+ */
+class CKEditor
+{
+ /**
+ * The version of %CKEditor.
+ */
+ const version = '3.2';
+ /**
+ * A constant string unique for each release of %CKEditor.
+ */
+ const timestamp = 'A1QD';
+
+ /**
+ * URL to the %CKEditor installation directory (absolute or relative to document root).
+ * If not set, CKEditor will try to guess it's path.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->basePath = '/ckeditor/';
+ * @endcode
+ */
+ public $basePath;
+ /**
+ * An array that holds the global %CKEditor configuration.
+ * For the list of available options, see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->config['height'] = 400;
+ * // Use @@ at the beggining of a string to ouput it without surrounding quotes.
+ * $CKEditor->config['width'] = '@@screen.width * 0.8';
+ * @endcode
+ */
+ public $config = array();
+ /**
+ * A boolean variable indicating whether CKEditor has been initialized.
+ * Set it to true only if you have already included
+ * <script> tag loading ckeditor.js in your website.
+ */
+ public $initialized = false;
+ /**
+ * Boolean variable indicating whether created code should be printed out or returned by a function.
+ *
+ * Example 1: get the code creating %CKEditor instance and print it on a page with the "echo" function.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->returnOutput = true;
+ * $code = $CKEditor->editor("editor1", "Initial value.
");
+ * echo "Editor 1:
";
+ * echo $code;
+ * @endcode
+ */
+ public $returnOutput = false;
+ /**
+ * An array with textarea attributes.
+ *
+ * When %CKEditor is created with the editor() method, a HTML <textarea> element is created,
+ * it will be displayed to anyone with JavaScript disabled or with incompatible browser.
+ */
+ public $textareaAttributes = array( "rows" => 8, "cols" => 60 );
+ /**
+ * A string indicating the creation date of %CKEditor.
+ * Do not change it unless you want to force browsers to not use previously cached version of %CKEditor.
+ */
+ public $timestamp = "A1QD";
+ /**
+ * An array that holds event listeners.
+ */
+ private $events = array();
+ /**
+ * An array that holds global event listeners.
+ */
+ private $globalEvents = array();
+
+ /**
+ * Main Constructor.
+ *
+ * @param $basePath (string) URL to the %CKEditor installation directory (optional).
+ */
+ function __construct($basePath = null) {
+ if (!empty($basePath)) {
+ $this->basePath = $basePath;
+ }
+ }
+
+ /**
+ * Creates a %CKEditor instance.
+ * In incompatible browsers %CKEditor will downgrade to plain HTML <textarea> element.
+ *
+ * @param $name (string) Name of the %CKEditor instance (this will be also the "name" attribute of textarea element).
+ * @param $value (string) Initial value (optional).
+ * @param $config (array) The specific configurations to apply to this editor instance (optional).
+ * @param $events (array) Event listeners for this editor instance (optional).
+ *
+ * Example usage:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->editor("field1", "Initial value.
");
+ * @endcode
+ *
+ * Advanced example:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $config = array();
+ * $config['toolbar'] = array(
+ * array( 'Source', '-', 'Bold', 'Italic', 'Underline', 'Strike' ),
+ * array( 'Image', 'Link', 'Unlink', 'Anchor' )
+ * );
+ * $events['instanceReady'] = 'function (ev) {
+ * alert("Loaded: " + ev.editor.name);
+ * }';
+ * $CKEditor->editor("field1", "Initial value.
", $config, $events);
+ * @endcode
+ */
+ public function editor($name, $value = "", $config = array(), $events = array())
+ {
+ $attr = "";
+ foreach ($this->textareaAttributes as $key => $val) {
+ $attr.= " " . $key . '="' . str_replace('"', '"', $val) . '"';
+ }
+ $out = "" . htmlspecialchars($value) . " \n";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings($config, $events);
+
+ $js = $this->returnGlobalEvents();
+ if (!empty($_config))
+ $js .= "CKEDITOR.replace('".$name."', ".$this->jsEncode($_config).");";
+ else
+ $js .= "CKEDITOR.replace('".$name."');";
+
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Replaces a <textarea> with a %CKEditor instance.
+ *
+ * @param $id (string) The id or name of textarea element.
+ * @param $config (array) The specific configurations to apply to this editor instance (optional).
+ * @param $events (array) Event listeners for this editor instance (optional).
+ *
+ * Example 1: adding %CKEditor to <textarea name="article"></textarea> element:
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replace("article");
+ * @endcode
+ */
+ public function replace($id, $config = array(), $events = array())
+ {
+ $out = "";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings($config, $events);
+
+ $js = $this->returnGlobalEvents();
+ if (!empty($_config)) {
+ $js .= "CKEDITOR.replace('".$id."', ".$this->jsEncode($_config).");";
+ }
+ else {
+ $js .= "CKEDITOR.replace('".$id."');";
+ }
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Replace all <textarea> elements available in the document with editor instances.
+ *
+ * @param $className (string) If set, replace all textareas with class className in the page.
+ *
+ * Example 1: replace all <textarea> elements in the page.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replaceAll();
+ * @endcode
+ *
+ * Example 2: replace all <textarea class="myClassName"> elements in the page.
+ * @code
+ * $CKEditor = new CKEditor();
+ * $CKEditor->replaceAll( 'myClassName' );
+ * @endcode
+ */
+ public function replaceAll($className = null)
+ {
+ $out = "";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings();
+
+ $js = $this->returnGlobalEvents();
+ if (empty($_config)) {
+ if (empty($className)) {
+ $js .= "CKEDITOR.replaceAll();";
+ }
+ else {
+ $js .= "CKEDITOR.replaceAll('".$className."');";
+ }
+ }
+ else {
+ $classDetection = "";
+ $js .= "CKEDITOR.replaceAll( function(textarea, config) {\n";
+ if (!empty($className)) {
+ $js .= " var classRegex = new RegExp('(?:^| )' + '". $className ."' + '(?:$| )');\n";
+ $js .= " if (!classRegex.test(textarea.className))\n";
+ $js .= " return false;\n";
+ }
+ $js .= " CKEDITOR.tools.extend(config, ". $this->jsEncode($_config) .", true);";
+ $js .= "} );";
+
+ }
+
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
+ }
+
+ return $out;
+ }
+
+ /**
+ * Adds event listener.
+ * Events are fired by %CKEditor in various situations.
+ *
+ * @param $event (string) Event name.
+ * @param $javascriptCode (string) Javascript anonymous function or function name.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->addEventHandler('instanceReady', 'function (ev) {
+ * alert("Loaded: " + ev.editor.name);
+ * }');
+ * @endcode
+ */
+ public function addEventHandler($event, $javascriptCode)
+ {
+ if (!isset($this->events[$event])) {
+ $this->events[$event] = array();
+ }
+ // Avoid duplicates.
+ if (!in_array($javascriptCode, $this->events[$event])) {
+ $this->events[$event][] = $javascriptCode;
+ }
+ }
+
+ /**
+ * Clear registered event handlers.
+ * Note: this function will have no effect on already created editor instances.
+ *
+ * @param $event (string) Event name, if not set all event handlers will be removed (optional).
+ */
+ public function clearEventHandlers($event = null)
+ {
+ if (!empty($event)) {
+ $this->events[$event] = array();
+ }
+ else {
+ $this->events = array();
+ }
+ }
+
+ /**
+ * Adds global event listener.
+ *
+ * @param $event (string) Event name.
+ * @param $javascriptCode (string) Javascript anonymous function or function name.
+ *
+ * Example usage:
+ * @code
+ * $CKEditor->addGlobalEventHandler('dialogDefinition', 'function (ev) {
+ * alert("Loading dialog: " + ev.data.name);
+ * }');
+ * @endcode
+ */
+ public function addGlobalEventHandler($event, $javascriptCode)
+ {
+ if (!isset($this->globalEvents[$event])) {
+ $this->globalEvents[$event] = array();
+ }
+ // Avoid duplicates.
+ if (!in_array($javascriptCode, $this->globalEvents[$event])) {
+ $this->globalEvents[$event][] = $javascriptCode;
+ }
+ }
+
+ /**
+ * Clear registered global event handlers.
+ * Note: this function will have no effect if the event handler has been already printed/returned.
+ *
+ * @param $event (string) Event name, if not set all event handlers will be removed (optional).
+ */
+ public function clearGlobalEventHandlers($event = null)
+ {
+ if (!empty($event)) {
+ $this->globalEvents[$event] = array();
+ }
+ else {
+ $this->globalEvents = array();
+ }
+ }
+
+ /**
+ * Prints javascript code.
+ *
+ * @param string $js
+ */
+ private function script($js)
+ {
+ $out = "\n";
+
+ return $out;
+ }
+
+ /**
+ * Returns the configuration array (global and instance specific settings are merged into one array).
+ *
+ * @param $config (array) The specific configurations to apply to editor instance.
+ * @param $events (array) Event listeners for editor instance.
+ */
+ private function configSettings($config = array(), $events = array())
+ {
+ $_config = $this->config;
+ $_events = $this->events;
+
+ if (is_array($config) && !empty($config)) {
+ $_config = array_merge($_config, $config);
+ }
+
+ if (is_array($events) && !empty($events)) {
+ foreach ($events as $eventName => $code) {
+ if (!isset($_events[$eventName])) {
+ $_events[$eventName] = array();
+ }
+ if (!in_array($code, $_events[$eventName])) {
+ $_events[$eventName][] = $code;
+ }
+ }
+ }
+
+ if (!empty($_events)) {
+ foreach($_events as $eventName => $handlers) {
+ if (empty($handlers)) {
+ continue;
+ }
+ else if (count($handlers) == 1) {
+ $_config['on'][$eventName] = '@@'.$handlers[0];
+ }
+ else {
+ $_config['on'][$eventName] = '@@function (ev){';
+ foreach ($handlers as $handler => $code) {
+ $_config['on'][$eventName] .= '('.$code.')(ev);';
+ }
+ $_config['on'][$eventName] .= '}';
+ }
+ }
+ }
+
+ return $_config;
+ }
+
+ /**
+ * Return global event handlers.
+ */
+ private function returnGlobalEvents()
+ {
+ static $returnedEvents;
+ $out = "";
+
+ if (!isset($returnedEvents)) {
+ $returnedEvents = array();
+ }
+
+ if (!empty($this->globalEvents)) {
+ foreach ($this->globalEvents as $eventName => $handlers) {
+ foreach ($handlers as $handler => $code) {
+ if (!isset($returnedEvents[$eventName])) {
+ $returnedEvents[$eventName] = array();
+ }
+ // Return only new events
+ if (!in_array($code, $returnedEvents[$eventName])) {
+ $out .= ($code ? "\n" : "") . "CKEDITOR.on('". $eventName ."', $code);";
+ $returnedEvents[$eventName][] = $code;
+ }
+ }
+ }
+ }
+
+ return $out;
+ }
+
+ /**
+ * Initializes CKEditor (executed only once).
+ */
+ private function init()
+ {
+ static $initComplete;
+ $out = "";
+
+ if (!empty($initComplete)) {
+ return "";
+ }
+
+ if ($this->initialized) {
+ $initComplete = true;
+ return "";
+ }
+
+ $args = "";
+ $ckeditorPath = $this->ckeditorPath();
+
+ if (!empty($this->timestamp) && $this->timestamp != "%"."TIMESTAMP%") {
+ $args = '?t=' . $this->timestamp;
+ }
+
+ // Skip relative paths...
+ if (strpos($ckeditorPath, '..') !== 0) {
+ $out .= $this->script("window.CKEDITOR_BASEPATH='". $ckeditorPath ."';");
+ }
+
+ $out .= "\n";
+
+ $extraCode = "";
+ if ($this->timestamp != self::timestamp) {
+ $extraCode .= ($extraCode ? "\n" : "") . "CKEDITOR.timestamp = '". $this->timestamp ."';";
+ }
+ if ($extraCode) {
+ $out .= $this->script($extraCode);
+ }
+
+ $initComplete = $this->initialized = true;
+
+ return $out;
+ }
+
+ /**
+ * Return path to ckeditor.js.
+ */
+ private function ckeditorPath()
+ {
+ if (!empty($this->basePath)) {
+ return $this->basePath;
+ }
+
+ /**
+ * The absolute pathname of the currently executing script.
+ * Note: If a script is executed with the CLI, as a relative path, such as file.php or ../file.php,
+ * $_SERVER['SCRIPT_FILENAME'] will contain the relative path specified by the user.
+ */
+ if (isset($_SERVER['SCRIPT_FILENAME'])) {
+ $realPath = dirname($_SERVER['SCRIPT_FILENAME']);
+ }
+ else {
+ /**
+ * realpath — Returns canonicalized absolute pathname
+ */
+ $realPath = realpath( './' ) ;
+ }
+
+ /**
+ * The filename of the currently executing script, relative to the document root.
+ * For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar
+ * would be /test.php/foo.bar.
+ */
+ $selfPath = dirname($_SERVER['PHP_SELF']);
+ $file = str_replace("\\", "/", __FILE__);
+
+ if (!$selfPath || !$realPath || !$file) {
+ return "/ckeditor/";
+ }
+
+ $documentRoot = substr($realPath, 0, strlen($realPath) - strlen($selfPath));
+ $fileUrl = substr($file, strlen($documentRoot));
+ $ckeditorUrl = str_replace("ckeditor_php5.php", "", $fileUrl);
+
+ return $ckeditorUrl;
+ }
+
+ /**
+ * This little function provides a basic JSON support.
+ * http://php.net/manual/en/function.json-encode.php
+ *
+ * @param mixed $val
+ * @return string
+ */
+ private function jsEncode($val)
+ {
+ if (is_null($val)) {
+ return 'null';
+ }
+ if ($val === false) {
+ return 'false';
+ }
+ if ($val === true) {
+ return 'true';
+ }
+ if (is_scalar($val))
+ {
+ if (is_float($val))
+ {
+ // Always use "." for floats.
+ $val = str_replace(",", ".", strval($val));
+ }
+
+ // Use @@ to not use quotes when outputting string value
+ if (strpos($val, '@@') === 0) {
+ return substr($val, 2);
+ }
+ else {
+ // All scalars are converted to strings to avoid indeterminism.
+ // PHP's "1" and 1 are equal for all PHP operators, but
+ // JS's "1" and 1 are not. So if we pass "1" or 1 from the PHP backend,
+ // we should get the same result in the JS frontend (string).
+ // Character replacements for JSON.
+ static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'),
+ array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
+
+ $val = str_replace($jsonReplaces[0], $jsonReplaces[1], $val);
+
+ return '"' . $val . '"';
+ }
+ }
+ $isList = true;
+ for ($i = 0, reset($val); $i < count($val); $i++, next($val))
+ {
+ if (key($val) !== $i)
+ {
+ $isList = false;
+ break;
+ }
+ }
+ $result = array();
+ if ($isList)
+ {
+ foreach ($val as $v) $result[] = $this->jsEncode($v);
+ return '[ ' . join(', ', $result) . ' ]';
+ }
+ else
+ {
+ foreach ($val as $k => $v) $result[] = $this->jsEncode($k).': '.$this->jsEncode($v);
+ return '{ ' . join(', ', $result) . ' }';
+ }
+ }
+}
diff --git a/webroot/js/ckeditor/lang/cy.js b/webroot/js/ckeditor/lang/cy.js
new file mode 100755
index 00000000..97bd46bd
--- /dev/null
+++ b/webroot/js/ckeditor/lang/cy.js
@@ -0,0 +1,6 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.lang.cy={dir:'ltr',editorTitle:'Rich text editor, %1, press ALT 0 for help.',toolbar:'Toolbar',editor:'Rich Text Editor',source:'Tarddle',newPage:'Tudalen newydd',save:'Cadw',preview:'Rhagolwg',cut:'Torri',copy:'Copïo',paste:'Gludo',print:'Argraffu',underline:'Tanlinellu',bold:'Bras',italic:'Italig',selectAll:'Dewis Popeth',removeFormat:'Tynnu Fformat',strike:'Llinell Trwyddo',subscript:'Is-sgript',superscript:'Uwchsgript',horizontalrule:'Mewnosod Llinell Lorweddol',pagebreak:'Mewnosod Toriad Tudalen i Argraffu',unlink:'Datgysylltu',undo:'Dadwneud',redo:'Ailadrodd',common:{browseServer:"Pori'r Gweinydd",url:'URL',protocol:'Protocol',upload:'Lanlwytho',uploadSubmit:"Anfon i'r Gweinydd",image:'Delwedd',flash:'Flash',form:'Ffurflen',checkbox:'Blwch ticio',radio:'Botwm Radio',textField:'Maes Testun',textarea:'Ardal Testun',hiddenField:'Maes Cudd',button:'Botwm',select:'Maes Dewis',imageButton:'Botwm Delwedd',notSet:'',id:'Id',name:'Name',langDir:'Cyfeiriad Iaith',langDirLtr:"Chwith i'r Dde (LTR)",langDirRtl:"Dde i'r Chwith (RTL)",langCode:'Cod Iaith',longDescr:'URL Disgrifiad Hir',cssClass:'Dosbarth Dalen Arddull',advisoryTitle:'Teitl Cynghorol',cssStyle:'Arddull',ok:'Iawn',cancel:'Diddymu',close:'Close',preview:'Preview',generalTab:'Cyffredinol',advancedTab:'Uwch',validateNumberFailed:"Nid yw'r gwerth hwn yn rhif.",confirmNewPage:"Byddwch yn colli unrhyw newidiadau i'r cynnwys sydd heb eu cadw. A ydych am barhau i lwytho tudalen newydd?",confirmCancel:"Mae rhai o'r opsiynau wedi'u newid. A ydych wir am gau'r deialog?",options:'Options',target:'Target',targetNew:'New Window (_blank)',targetTop:'Topmost Window (_top)',targetSelf:'Same Window (_self)',targetParent:'Parent Window (_parent)',unavailable:'%1, ddim ar gael '},specialChar:{toolbar:'Mewnosod Nodau Arbennig',title:'Dewis Nod Arbennig'},link:{toolbar:'Dolen',menu:'Golygu Dolen',title:'Dolen',info:'Gwyb ar y Ddolen',target:'Targed',upload:'Lanlwytho',advanced:'Uwch',type:'Math y Ddolen',toUrl:'URL',toAnchor:'Dolen at angor yn y testun',toEmail:'E-bost',targetFrame:'',targetPopup:'',targetFrameName:'Enw Ffrâm y Targed',targetPopupName:'Enw Ffenestr Bop',popupFeatures:'Nodweddion Ffenestr Bop',popupResizable:'Ailfeintiol',popupStatusBar:'Bar Statws',popupLocationBar:'Bar Safle',popupToolbar:'Bar Offer',popupMenuBar:'Dewislen',popupFullScreen:'Sgrin Llawn (IE)',popupScrollBars:'Barrau Sgrolio',popupDependent:'Dibynnol (Netscape)',popupWidth:'Lled',popupLeft:'Safle Chwith',popupHeight:'Uchder',popupTop:'Safle Top',id:'Id',langDir:'Cyfeiriad Iaith',langDirLTR:"Chwith i'r Dde (LTR)",langDirRTL:"Dde i'r Chwith (RTL)",acccessKey:'Allwedd Mynediad',name:'Enw',langCode:'Cod Iaith',tabIndex:'Indecs Tab',advisoryTitle:'Teitl Cynghorol',advisoryContentType:'Math y Cynnwys Cynghorol',cssClasses:'Dosbarthiadau Dalen Arddull',charset:"Set nodau'r Adnodd Cysylltiedig",styles:'Arddull',selectAnchor:'Dewiswch Angor',anchorName:"Gan Enw'r Angor",anchorId:'Gan Id yr Elfen',emailAddress:'Cyfeiriad E-Bost',emailSubject:'Testun y Message Subject',emailBody:'Pwnc y Neges',noAnchors:'(Dim angorau ar gael yn y ddogfen)',noUrl:'Teipiwch URL y ddolen',noEmail:'Teipiwch gyfeiriad yr e-bost'},anchor:{toolbar:'Angor',menu:'Golygwch yr Angor',title:"Priodweddau'r Angor",name:"Enw'r Angor",errorName:"Teipiwch enw'r angor"},findAndReplace:{title:'Chwilio ac Amnewid',find:'Chwilio',replace:'Amnewid',findWhat:"Chwilio'r term:",replaceWith:'Amnewid gyda:',notFoundMsg:"Nid oedd y testun wedi'i ddarganfod.",matchCase:"Cyfateb i'r cas",matchWord:'Cyfateb gair cyfan',matchCyclic:'Cyfateb cylchol',replaceAll:'Amnewid pob un',replaceSuccessMsg:'Amnewidiwyd %1 achlysur.'},table:{toolbar:'Tabl',title:'Nodweddion Tabl',menu:'Nodweddion Tabl',deleteTable:'Dileu Tabl',rows:'Rhesi',columns:'Colofnau',border:'Maint yr Ymyl',align:'Aliniad',alignLeft:'Chwith',alignCenter:'Canol',alignRight:'Dde',width:'Lled',widthPx:'picsel',widthPc:'y cant',widthUnit:'width unit',height:'Uchder',cellSpace:"Bylchu'r gell",cellPad:"Padio'r gell",caption:'Pennawd',summary:'Crynodeb',headers:'Penynnau',headersNone:'Dim',headersColumn:'Colofn gyntaf',headersRow:'Rhes gyntaf',headersBoth:'Y Ddau',invalidRows:"Mae'n rhaid cael o leiaf un rhes.",invalidCols:"Mae'n rhaid cael o leiaf un golofn.",invalidBorder:"Mae'n rhaid i faint yr ymyl fod yn rhif.",invalidWidth:"Mae'n rhaid i led y tabl fod yn rhif.",invalidHeight:"Mae'n rhaid i uchder y tabl fod yn rhif.",invalidCellSpacing:"Mae'n rhaid i fylchiad y gell fod yn rhif.",invalidCellPadding:"Mae'n rhaid i badiad y gell fod yn rhif.",cell:{menu:'Cell',insertBefore:'Mewnosod Cell Cyn',insertAfter:'Mewnosod Cell Ar Ôl',deleteCell:'Dileu Celloedd',merge:'Cyfuno Celloedd',mergeRight:"Cyfuno i'r Dde",mergeDown:'Cyfuno i Lawr',splitHorizontal:"Hollti'r Gell yn Lorweddol",splitVertical:"Hollti'r Gell yn Fertigol",title:"Priodweddau'r Gell",cellType:'Math y Gell',rowSpan:'Rhychwant Rhesi',colSpan:'Rhychwant Colofnau',wordWrap:'Lapio Geiriau',hAlign:'Aliniad Llorweddol',vAlign:'Aliniad Fertigol',alignTop:'Top',alignMiddle:'Canol',alignBottom:'Gwaelod',alignBaseline:'Baslinell',bgColor:'Lliw Cefndir',borderColor:'Lliw Ymyl',data:'Data',header:'Pennyn',yes:'Ie',no:'Na',invalidWidth:"Mae'n rhaid i led y gell fod yn rhif.",invalidHeight:"Mae'n rhaid i uchder y gell fod yn rhif.",invalidRowSpan:"Mae'n rhaid i rychwant y rhesi fod yn gyfanrif.",invalidColSpan:"Mae'n rhaid i rychwant y colofnau fod yn gyfanrif.",chooseColor:'Choose'},row:{menu:'Rhes',insertBefore:'Mewnosod Rhes Cyn',insertAfter:'Mewnosod Rhes Ar Ôl',deleteRow:'Dileu Rhesi'},column:{menu:'Colofn',insertBefore:'Mewnosod Colofn Cyn',insertAfter:'Mewnosod Colofn Ar Ôl',deleteColumn:'Dileu Colofnau'}},button:{title:'Priodweddau Botymau',text:'Testun (Gwerth)',type:'Math',typeBtn:'Botwm',typeSbm:'Gyrru',typeRst:'Ailosod'},checkboxAndRadio:{checkboxTitle:'Priodweddau Blwch Ticio',radioTitle:'Priodweddau Botwm Radio',value:'Gwerth',selected:'Dewiswyd'},form:{title:'Priodweddau Ffurflen',menu:'Priodweddau Ffurflen',action:'Gweithred',method:'Dull',encoding:'Amgodio'},select:{title:'Priodweddau Maes Dewis',selectInfo:'Gwyb Dewis',opAvail:'Opsiynau ar Gael',value:'Gwerth',size:'Maint',lines:'llinellau',chkMulti:'Caniatàu aml-ddewisiadau',opText:'Testun',opValue:'Gwerth',btnAdd:'Ychwanegu',btnModify:'Newid',btnUp:'Lan',btnDown:'Lawr',btnSetValue:'Gosod fel gwerth a ddewiswyd',btnDelete:'Dileu'},textarea:{title:'Priodweddau Ardal Testun',cols:'Colofnau',rows:'Rhesi'},textfield:{title:'Priodweddau Maes Testun',name:'Enw',value:'Gwerth',charWidth:'Lled Nod',maxChars:'Uchafswm y Nodau',type:'Math',typeText:'Testun',typePass:'Cyfrinair'},hidden:{title:'Priodweddau Maes Cudd',name:'Enw',value:'Gwerth'},image:{title:'Priodweddau Delwedd',titleButton:'Priodweddau Botwm Delwedd',menu:'Priodweddau Delwedd',infoTab:'Gwyb Delwedd',btnUpload:"Anfon i'r Gweinydd",upload:'lanlwytho',alt:'Testun Amgen',width:'Lled',height:'Uchder',lockRatio:'Cloi Cymhareb',unlockRatio:'Unlock Ratio',resetSize:'Ailosod Maint',border:'Ymyl',hSpace:'BwlchLl',vSpace:'BwlchF',align:'Alinio',alignLeft:'Chwith',alignRight:'Dde',alertUrl:'Rhowch URL y ddelwedd',linkTab:'Dolen',button2Img:"Ydych am drawsffurfio'r botwm ddelwedd hwn ar ddelwedd syml?",img2Button:"Ydych am drawsffurfio'r ddelwedd hon ar fotwm delwedd?",urlMissing:"URL tarddle'r ddelwedd ar goll.",validateWidth:'Width must be a whole number.',validateHeight:'Height must be a whole number.',validateBorder:'Border must be a whole number.',validateHSpace:'HSpace must be a whole number.',validateVSpace:'VSpace must be a whole number.'},flash:{properties:'Priodweddau Flash',propertiesTab:'Priodweddau',title:'Priodweddau Flash',chkPlay:'AwtoChwarae',chkLoop:'Lwpio',chkMenu:'Galluogi Dewislen Flash',chkFull:'Caniatàu Sgrin Llawn',scale:'Graddfa',scaleAll:'Dangos pob',scaleNoBorder:'Dim Ymyl',scaleFit:'Ffit Union',access:'Mynediad Sgript',accessAlways:'Pob amser',accessSameDomain:"R'un parth",accessNever:'Byth',align:'Alinio',alignLeft:'Chwith',alignAbsBottom:'Gwaelod Abs',alignAbsMiddle:'Canol Abs',alignBaseline:'Baslinell',alignBottom:'Gwaelod',alignMiddle:'Canol',alignRight:'Dde',alignTextTop:'Testun Top',alignTop:'Top',quality:'Ansawdd',qualityBest:'Gorau',qualityHigh:'Uchel',qualityAutoHigh:'Uchel Awto',qualityMedium:'Canolig',qualityAutoLow:'Isel Awto',qualityLow:'Isel',windowModeWindow:'Ffenestr',windowModeOpaque:'Afloyw',windowModeTransparent:'Tryloyw',windowMode:'Modd ffenestr',flashvars:'Newidynnau ar gyfer Flash',bgcolor:'Lliw cefndir',width:'Lled',height:'Uchder',hSpace:'BwlchLl',vSpace:'BwlchF',validateSrc:'Ni all yr URL fod yn wag.',validateWidth:"Rhaid i'r Lled fod yn rhif.",validateHeight:"Rhaid i'r Uchder fod yn rhif.",validateHSpace:"Rhaid i'r BwlchLl fod yn rhif.",validateVSpace:"Rhaid i'r BwlchF fod yn rhif."},spellCheck:{toolbar:'Gwirio Sillafu',title:'Gwirio Sillafu',notAvailable:"Nid yw'r gwasanaeth hwn ar gael yn bresennol.",errorLoading:'Error loading application service host: %s.',notInDic:"Nid i'w gael yn y geiriadur",changeTo:'Newid i',btnIgnore:'Anwybyddu Un',btnIgnoreAll:'Anwybyddu Pob',btnReplace:'Amnewid Un',btnReplaceAll:'Amnewid Pob',btnUndo:'Dadwneud',noSuggestions:'- Dim awgrymiadau -',progress:'Gwirio sillafu yn ar y gweill...',noMispell:'Gwirio sillafu wedi gorffen: Dim camsillaf.',noChanges:'Gwirio sillafu wedi gorffen: Dim newidiadau',oneChange:'Gwirio sillafu wedi gorffen: Newidiwyd 1 gair',manyChanges:'Gwirio sillafu wedi gorffen: Newidiwyd %1 gair',ieSpellDownload:'Gwirydd sillafu heb ei arsefydlu. A ydych am ei lawrlwytho nawr?'},smiley:{toolbar:'Gwenoglun',title:'Mewnosod Gwenoglun'},elementsPath:{eleLabel:'Elements path',eleTitle:'Elfen %1'},numberedlist:'Mewnosod/Tynnu Rhestr Rhifol',bulletedlist:'Mewnosod/Tynnu Rhestr Bwled',indent:"Cynyddu'r Mewnoliad",outdent:"Lleihau'r Mewnoliad",justify:{left:"Alinio i'r Chwith",center:"Alinio i'r Canol",right:"Alinio i'r Dde",block:'Aliniad Bloc'},blockquote:'Dyfyniad bloc',clipboard:{title:'Gludo',cutError:"Nid yw gosodiadau diogelwch eich porwr yn caniatàu'r golygydd i gynnal 'gweithredoedd torri' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl+X).",copyError:"Nid yw gosodiadau diogelwch eich porwr yn caniatàu'r golygydd i gynnal 'gweithredoedd copïo' yn awtomatig. Defnyddiwch y bysellfwrdd (Ctrl+C).",pasteMsg:"Gludwch i mewn i'r blwch canlynol gan ddefnyddio'r bysellfwrdd (Ctrl+V ) a phwyso Iawn .",securityMsg:"Oherwydd gosodiadau diogelwch eich porwr, nid yw'r porwr yn gallu ennill mynediad i'r data ar y clipfwrdd yn uniongyrchol. Mae angen i chi ei ludo eto i'r ffenestr hon.",pasteArea:'Paste Area'},pastefromword:{confirmCleanup:'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?',toolbar:'Gludo o Word',title:'Gludo o Word',error:'It was not possible to clean up the pasted data due to an internal error'},pasteText:{button:'Gludo fel testun plaen',title:'Gludo fel Testun Plaen'},templates:{button:'Templedi',title:'Templedi Cynnwys',insertOption:'Amnewid y cynnwys go iawn',selectPromptMsg:"Dewiswch dempled i'w agor yn y golygydd",emptyListMsg:"(Dim templedi wedi'u diffinio)"},showBlocks:'Dangos Blociau',stylesCombo:{label:'Arddulliau',panelTitle:'Formatting Styles',panelTitle1:'Arddulliau Bloc',panelTitle2:'Arddulliau Mewnol',panelTitle3:'Arddulliau Gwrthrych'},format:{label:'Fformat',panelTitle:'Fformat Paragraff',tag_p:'Normal',tag_pre:"Wedi'i Fformatio",tag_address:'Cyfeiriad',tag_h1:'Pennawd 1',tag_h2:'Pennawd 2',tag_h3:'Pennawd 3',tag_h4:'Pennawd 4',tag_h5:'Pennawd 5',tag_h6:'Pennawd 6',tag_div:'Normal (DIV)'},div:{title:'Create Div Container',toolbar:'Create Div Container',cssClassInputLabel:'Stylesheet Classes',styleSelectLabel:'Style',IdInputLabel:'Id',languageCodeInputLabel:' Language Code',inlineStyleInputLabel:'Inline Style',advisoryTitleInputLabel:'Advisory Title',langDirLabel:'Language Direction',langDirLTRLabel:'Left to Right (LTR)',langDirRTLLabel:'Right to Left (RTL)',edit:'Edit Div',remove:'Remove Div'},font:{label:'Ffont',voiceLabel:'Ffont',panelTitle:"Enw'r Ffont"},fontSize:{label:'Maint',voiceLabel:'Maint y Ffont',panelTitle:'Maint y Ffont'},colorButton:{textColorTitle:'Lliw Testun',bgColorTitle:'Lliw Cefndir',panelTitle:'Colors',auto:'Awtomatig',more:'Mwy o Liwiau...'},colors:{'000':'Du',800000:'Marwn','8B4513':'Brown Cyfrwy','2F4F4F':'Llechen Tywyll','008080':'Corhwyad','000080':'Nefi','4B0082':'Indigo',696969:'Llwyd Pwl',B22222:'Bric Tân',A52A2A:'Brown',DAA520:'Rhoden Aur','006400':'Gwyrdd Tywyll','40E0D0':'Gwyrddlas','0000CD':'Glas Canolig',800080:'Porffor',808080:'Llwyd',F00:'Coch',FF8C00:'Oren Tywyll',FFD700:'Aur','008000':'Gwyrdd','0FF':'Cyan','00F':'Glas',EE82EE:'Fioled',A9A9A9:'Llwyd Tywyll',FFA07A:'Samwn Golau',FFA500:'Oren',FFFF00:'Melyn','00FF00':'Leim',AFEEEE:'Gwyrddlas Golau',ADD8E6:'Glas Golau',DDA0DD:'Eirinen',D3D3D3:'Llwyd Golau',FFF0F5:'Gwrid Lafant',FAEBD7:'Gwyn Hynafol',FFFFE0:'Melyn Golau',F0FFF0:'Melwn Gwyrdd Golau',F0FFFF:'Aswr',F0F8FF:'Glas Alys',E6E6FA:'Lafant',FFF:'Gwyn'},scayt:{title:"Gwirio'r Sillafu Wrth Deipio",enable:'Galluogi SCAYT',disable:'Analluogi SCAYT',about:'Ynghylch SCAYT',toggle:'Togl SCAYT',options:'Opsiynau',langs:'Ieithoedd',moreSuggestions:'Awgrymiadau pellach',ignore:'Anwybyddu',ignoreAll:'Anwybyddu pob',addWord:'Ychwanegu Gair',emptyDic:"Ni ddylai enw'r geiriadur fod yn wag.",optionsTab:'Opsiynau',languagesTab:'Ieithoedd',dictionariesTab:'Geiriaduron',aboutTab:'Ynghylch'},about:{title:'Ynghylch CKEditor',dlgTitle:'Ynghylch CKEditor',moreInfo:"Am wybodaeth ynghylch trwyddedau, ewch i'n gwefan:",copy:'Hawlfraint © $1. Cedwir pob hawl.'},maximize:'Mwyhau',minimize:'Lleihau',fakeobjects:{anchor:'Angor',flash:'Animeiddiant Flash',div:'Toriad Tudalen',unknown:'Gwrthrych Anhysbys'},resize:'Llusgo i ailfeintio',colordialog:{title:'Dewis lliw',highlight:'Uwcholeuo',selected:'Dewiswyd',clear:'Clirio'},toolbarCollapse:"Cyfangu'r Bar Offer",toolbarExpand:"Ehangu'r Bar Offer"};
diff --git a/webroot/js/ckeditor/lang/en-gb.js b/webroot/js/ckeditor/lang/en-gb.js
new file mode 100755
index 00000000..e4bc2862
--- /dev/null
+++ b/webroot/js/ckeditor/lang/en-gb.js
@@ -0,0 +1,6 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.lang['en-gb']={dir:'ltr',editorTitle:'Rich text editor, %1, press ALT 0 for help.',toolbar:'Toolbar',editor:'Rich Text Editor',source:'Source',newPage:'New Page',save:'Save',preview:'Preview',cut:'Cut',copy:'Copy',paste:'Paste',print:'Print',underline:'Underline',bold:'Bold',italic:'Italic',selectAll:'Select All',removeFormat:'Remove Format',strike:'Strike Through',subscript:'Subscript',superscript:'Superscript',horizontalrule:'Insert Horizontal Line',pagebreak:'Insert Page Break for Printing',unlink:'Unlink',undo:'Undo',redo:'Redo',common:{browseServer:'Browse Server',url:'URL',protocol:'Protocol',upload:'Upload',uploadSubmit:'Send it to the Server',image:'Image',flash:'Flash',form:'Form',checkbox:'Checkbox',radio:'Radio Button',textField:'Text Field',textarea:'Textarea',hiddenField:'Hidden Field',button:'Button',select:'Selection Field',imageButton:'Image Button',notSet:'',id:'Id',name:'Name',langDir:'Language Direction',langDirLtr:'Left to Right (LTR)',langDirRtl:'Right to Left (RTL)',langCode:'Language Code',longDescr:'Long Description URL',cssClass:'Stylesheet Classes',advisoryTitle:'Advisory Title',cssStyle:'Style',ok:'OK',cancel:'Cancel',close:'Close',preview:'Preview',generalTab:'General',advancedTab:'Advanced',validateNumberFailed:'This value is not a number.',confirmNewPage:'Any unsaved changes to this content will be lost. Are you sure you want to load new page?',confirmCancel:'Some of the options have been changed. Are you sure to close the dialog?',options:'Options',target:'Target',targetNew:'New Window (_blank)',targetTop:'Topmost Window (_top)',targetSelf:'Same Window (_self)',targetParent:'Parent Window (_parent)',unavailable:'%1, unavailable '},specialChar:{toolbar:'Insert Special Character',title:'Select Special Character'},link:{toolbar:'Link',menu:'Edit Link',title:'Link',info:'Link Info',target:'Target',upload:'Upload',advanced:'Advanced',type:'Link Type',toUrl:'URL',toAnchor:'Link to anchor in the text',toEmail:'E-mail',targetFrame:' ',targetPopup:'',targetFrameName:'Target Frame Name',targetPopupName:'Popup Window Name',popupFeatures:'Popup Window Features',popupResizable:'Resizable',popupStatusBar:'Status Bar',popupLocationBar:'Location Bar',popupToolbar:'Toolbar',popupMenuBar:'Menu Bar',popupFullScreen:'Full Screen (IE)',popupScrollBars:'Scroll Bars',popupDependent:'Dependent (Netscape)',popupWidth:'Width',popupLeft:'Left Position',popupHeight:'Height',popupTop:'Top Position',id:'Id',langDir:'Language Direction',langDirLTR:'Left to Right (LTR)',langDirRTL:'Right to Left (RTL)',acccessKey:'Access Key',name:'Name',langCode:'Language Code',tabIndex:'Tab Index',advisoryTitle:'Advisory Title',advisoryContentType:'Advisory Content Type',cssClasses:'Stylesheet Classes',charset:'Linked Resource Charset',styles:'Style',selectAnchor:'Select an Anchor',anchorName:'By Anchor Name',anchorId:'By Element Id',emailAddress:'E-Mail Address',emailSubject:'Message Subject',emailBody:'Message Body',noAnchors:'(No anchors available in the document)',noUrl:'Please type the link URL',noEmail:'Please type the e-mail address'},anchor:{toolbar:'Anchor',menu:'Edit Anchor',title:'Anchor Properties',name:'Anchor Name',errorName:'Please type the anchor name'},findAndReplace:{title:'Find and Replace',find:'Find',replace:'Replace',findWhat:'Find what:',replaceWith:'Replace with:',notFoundMsg:'The specified text was not found.',matchCase:'Match case',matchWord:'Match whole word',matchCyclic:'Match cyclic',replaceAll:'Replace All',replaceSuccessMsg:'%1 occurrence(s) replaced.'},table:{toolbar:'Table',title:'Table Properties',menu:'Table Properties',deleteTable:'Delete Table',rows:'Rows',columns:'Columns',border:'Border size',align:'Alignment',alignLeft:'Left',alignCenter:'Centre',alignRight:'Right',width:'Width',widthPx:'pixels',widthPc:'percent',widthUnit:'width unit',height:'Height',cellSpace:'Cell spacing',cellPad:'Cell padding',caption:'Caption',summary:'Summary',headers:'Headers',headersNone:'None',headersColumn:'First column',headersRow:'First Row',headersBoth:'Both',invalidRows:'Number of rows must be a number greater than 0.',invalidCols:'Number of columns must be a number greater than 0.',invalidBorder:'Border size must be a number.',invalidWidth:'Table width must be a number.',invalidHeight:'Table height must be a number.',invalidCellSpacing:'Cell spacing must be a number.',invalidCellPadding:'Cell padding must be a number.',cell:{menu:'Cell',insertBefore:'Insert Cell Before',insertAfter:'Insert Cell After',deleteCell:'Delete Cells',merge:'Merge Cells',mergeRight:'Merge Right',mergeDown:'Merge Down',splitHorizontal:'Split Cell Horizontally',splitVertical:'Split Cell Vertically',title:'Cell Properties',cellType:'Cell Type',rowSpan:'Rows Span',colSpan:'Columns Span',wordWrap:'Word Wrap',hAlign:'Horizontal Alignment',vAlign:'Vertical Alignment',alignTop:'Top',alignMiddle:'Middle',alignBottom:'Bottom',alignBaseline:'Baseline',bgColor:'Background Color',borderColor:'Border Color',data:'Data',header:'Header',yes:'Yes',no:'No',invalidWidth:'Cell width must be a number.',invalidHeight:'Cell height must be a number.',invalidRowSpan:'Rows span must be a whole number.',invalidColSpan:'Columns span must be a whole number.',chooseColor:'Choose'},row:{menu:'Row',insertBefore:'Insert Row Before',insertAfter:'Insert Row After',deleteRow:'Delete Rows'},column:{menu:'Column',insertBefore:'Insert Column Before',insertAfter:'Insert Column After',deleteColumn:'Delete Columns'}},button:{title:'Button Properties',text:'Text (Value)',type:'Type',typeBtn:'Button',typeSbm:'Submit',typeRst:'Reset'},checkboxAndRadio:{checkboxTitle:'Checkbox Properties',radioTitle:'Radio Button Properties',value:'Value',selected:'Selected'},form:{title:'Form Properties',menu:'Form Properties',action:'Action',method:'Method',encoding:'Encoding'},select:{title:'Selection Field Properties',selectInfo:'Select Info',opAvail:'Available Options',value:'Value',size:'Size',lines:'lines',chkMulti:'Allow multiple selections',opText:'Text',opValue:'Value',btnAdd:'Add',btnModify:'Modify',btnUp:'Up',btnDown:'Down',btnSetValue:'Set as selected value',btnDelete:'Delete'},textarea:{title:'Textarea Properties',cols:'Columns',rows:'Rows'},textfield:{title:'Text Field Properties',name:'Name',value:'Value',charWidth:'Character Width',maxChars:'Maximum Characters',type:'Type',typeText:'Text',typePass:'Password'},hidden:{title:'Hidden Field Properties',name:'Name',value:'Value'},image:{title:'Image Properties',titleButton:'Image Button Properties',menu:'Image Properties',infoTab:'Image Info',btnUpload:'Send it to the Server',upload:'Upload',alt:'Alternative Text',width:'Width',height:'Height',lockRatio:'Lock Ratio',unlockRatio:'Unlock Ratio',resetSize:'Reset Size',border:'Border',hSpace:'HSpace',vSpace:'VSpace',align:'Align',alignLeft:'Left',alignRight:'Right',alertUrl:'Please type the image URL',linkTab:'Link',button2Img:'Do you want to transform the selected image button on a simple image?',img2Button:'Do you want to transform the selected image on a image button?',urlMissing:'Image source URL is missing.',validateWidth:'Width must be a whole number.',validateHeight:'Height must be a whole number.',validateBorder:'Border must be a whole number.',validateHSpace:'HSpace must be a whole number.',validateVSpace:'VSpace must be a whole number.'},flash:{properties:'Flash Properties',propertiesTab:'Properties',title:'Flash Properties',chkPlay:'Auto Play',chkLoop:'Loop',chkMenu:'Enable Flash Menu',chkFull:'Allow Fullscreen',scale:'Scale',scaleAll:'Show all',scaleNoBorder:'No Border',scaleFit:'Exact Fit',access:'Script Access',accessAlways:'Always',accessSameDomain:'Same domain',accessNever:'Never',align:'Align',alignLeft:'Left',alignAbsBottom:'Abs Bottom',alignAbsMiddle:'Abs Middle',alignBaseline:'Baseline',alignBottom:'Bottom',alignMiddle:'Middle',alignRight:'Right',alignTextTop:'Text Top',alignTop:'Top',quality:'Quality',qualityBest:'Best',qualityHigh:'High',qualityAutoHigh:'Auto High',qualityMedium:'Medium',qualityAutoLow:'Auto Low',qualityLow:'Low',windowModeWindow:'Window',windowModeOpaque:'Opaque',windowModeTransparent:'Transparent',windowMode:'Window mode',flashvars:'Variables for Flash',bgcolor:'Background colour',width:'Width',height:'Height',hSpace:'HSpace',vSpace:'VSpace',validateSrc:'URL must not be empty.',validateWidth:'Width must be a number.',validateHeight:'Height must be a number.',validateHSpace:'HSpace must be a number.',validateVSpace:'VSpace must be a number.'},spellCheck:{toolbar:'Check Spelling',title:'Spell Check',notAvailable:'Sorry, but service is unavailable now.',errorLoading:'Error loading application service host: %s.',notInDic:'Not in dictionary',changeTo:'Change to',btnIgnore:'Ignore',btnIgnoreAll:'Ignore All',btnReplace:'Replace',btnReplaceAll:'Replace All',btnUndo:'Undo',noSuggestions:'- No suggestions -',progress:'Spell check in progress...',noMispell:'Spell check complete: No misspellings found',noChanges:'Spell check complete: No words changed',oneChange:'Spell check complete: One word changed',manyChanges:'Spell check complete: %1 words changed',ieSpellDownload:'Spell checker not installed. Do you want to download it now?'},smiley:{toolbar:'Smiley',title:'Insert a Smiley'},elementsPath:{eleLabel:'Elements path',eleTitle:'%1 element'},numberedlist:'Insert/Remove Numbered List',bulletedlist:'Insert/Remove Bulleted List',indent:'Increase Indent',outdent:'Decrease Indent',justify:{left:'Left Justify',center:'Centre Justify',right:'Right Justify',block:'Block Justify'},blockquote:'Block Quote',clipboard:{title:'Paste',cutError:"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl+X).",copyError:"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl+C).",pasteMsg:'Please paste inside the following box using the keyboard (Ctrl+V ) and hit OK',securityMsg:'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.',pasteArea:'Paste Area'},pastefromword:{confirmCleanup:'The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?',toolbar:'Paste from Word',title:'Paste from Word',error:'It was not possible to clean up the pasted data due to an internal error'},pasteText:{button:'Paste as plain text',title:'Paste as Plain Text'},templates:{button:'Templates',title:'Content Templates',insertOption:'Replace actual contents',selectPromptMsg:'Please select the template to open in the editor',emptyListMsg:'(No templates defined)'},showBlocks:'Show Blocks',stylesCombo:{label:'Styles',panelTitle:'Formatting Styles',panelTitle1:'Block Styles',panelTitle2:'Inline Styles',panelTitle3:'Object Styles'},format:{label:'Format',panelTitle:'Paragraph Format',tag_p:'Normal',tag_pre:'Formatted',tag_address:'Address',tag_h1:'Heading 1',tag_h2:'Heading 2',tag_h3:'Heading 3',tag_h4:'Heading 4',tag_h5:'Heading 5',tag_h6:'Heading 6',tag_div:'Normal (DIV)'},div:{title:'Create Div Container',toolbar:'Create Div Container',cssClassInputLabel:'Stylesheet Classes',styleSelectLabel:'Style',IdInputLabel:'Id',languageCodeInputLabel:' Language Code',inlineStyleInputLabel:'Inline Style',advisoryTitleInputLabel:'Advisory Title',langDirLabel:'Language Direction',langDirLTRLabel:'Left to Right (LTR)',langDirRTLLabel:'Right to Left (RTL)',edit:'Edit Div',remove:'Remove Div'},font:{label:'Font',voiceLabel:'Font',panelTitle:'Font Name'},fontSize:{label:'Size',voiceLabel:'Font Size',panelTitle:'Font Size'},colorButton:{textColorTitle:'Text Colour',bgColorTitle:'Background Colour',panelTitle:'Colors',auto:'Automatic',more:'More Colours...'},colors:{'000':'Black',800000:'Maroon','8B4513':'Saddle Brown','2F4F4F':'Dark Slate Gray','008080':'Teal','000080':'Navy','4B0082':'Indigo',696969:'Dim Gray',B22222:'Fire Brick',A52A2A:'Brown',DAA520:'Golden Rod','006400':'Dark Green','40E0D0':'Turquoise','0000CD':'Medium Blue',800080:'Purple',808080:'Gray',F00:'Red',FF8C00:'Dark Orange',FFD700:'Gold','008000':'Green','0FF':'Cyan','00F':'Blue',EE82EE:'Violet',A9A9A9:'Dark Gray',FFA07A:'Light Salmon',FFA500:'Orange',FFFF00:'Yellow','00FF00':'Lime',AFEEEE:'Pale Turquoise',ADD8E6:'Light Blue',DDA0DD:'Plum',D3D3D3:'Light Grey',FFF0F5:'Lavender Blush',FAEBD7:'Antique White',FFFFE0:'Light Yellow',F0FFF0:'Honeydew',F0FFFF:'Azure',F0F8FF:'Alice Blue',E6E6FA:'Lavender',FFF:'White'},scayt:{title:'Spell Check As You Type',enable:'Enable SCAYT',disable:'Disable SCAYT',about:'About SCAYT',toggle:'Toggle SCAYT',options:'Options',langs:'Languages',moreSuggestions:'More suggestions',ignore:'Ignore',ignoreAll:'Ignore All',addWord:'Add Word',emptyDic:'Dictionary name should not be empty.',optionsTab:'Options',languagesTab:'Languages',dictionariesTab:'Dictionaries',aboutTab:'About'},about:{title:'About CKEditor',dlgTitle:'About CKEditor',moreInfo:'For licensing information please visit our web site:',copy:'Copyright © $1. All rights reserved.'},maximize:'Maximize',minimize:'Minimize',fakeobjects:{anchor:'Anchor',flash:'Flash Animation',div:'Page Break',unknown:'Unknown Object'},resize:'Drag to resize',colordialog:{title:'Select color',highlight:'Highlight',selected:'Selected',clear:'Clear'},toolbarCollapse:'Collapse Toolbar',toolbarExpand:'Expand Toolbar'};
diff --git a/webroot/js/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js b/webroot/js/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
new file mode 100755
index 00000000..e0e7b79a
--- /dev/null
+++ b/webroot/js/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.dialog.add('a11yHelp',function(a){var b=a.lang.accessibilityHelp,c=CKEDITOR.tools.getNextNumber(),d={8:'BACKSPACE',9:'TAB',13:'ENTER',16:'SHIFT',17:'CTRL',18:'ALT',19:'PAUSE',20:'CAPSLOCK',27:'ESCAPE',33:'PAGE UP',34:'PAGE DOWN',35:'END',36:'HOME',37:'LEFT ARROW',38:'UP ARROW',39:'RIGHT ARROW',40:'DOWN ARROW',45:'INSERT',46:'DELETE',91:'LEFT WINDOW KEY',92:'RIGHT WINDOW KEY',93:'SELECT KEY',96:'NUMPAD 0',97:'NUMPAD 1',98:'NUMPAD 2',99:'NUMPAD 3',100:'NUMPAD 4',101:'NUMPAD 5',102:'NUMPAD 6',103:'NUMPAD 7',104:'NUMPAD 8',105:'NUMPAD 9',106:'MULTIPLY',107:'ADD',109:'SUBTRACT',110:'DECIMAL POINT',111:'DIVIDE',112:'F1',113:'F2',114:'F3',115:'F4',116:'F5',117:'F6',118:'F7',119:'F8',120:'F9',121:'F10',122:'F11',123:'F12',144:'NUM LOCK',145:'SCROLL LOCK',186:'SEMI-COLON',187:'EQUAL SIGN',188:'COMMA',189:'DASH',190:'PERIOD',191:'FORWARD SLASH',192:'GRAVE ACCENT',219:'OPEN BRACKET',220:'BACK SLASH',221:'CLOSE BRAKET',222:'SINGLE QUOTE'};d[CKEDITOR.ALT]='ALT';d[CKEDITOR.SHIFT]='SHIFT';d[CKEDITOR.CTRL]='CTRL';var e=[CKEDITOR.ALT,CKEDITOR.SHIFT,CKEDITOR.CTRL];function f(j){var k,l,m=[];for(var n=0;n1&&k<=2){j-=l;m.push(d[l]);}}m.push(d[j]||String.fromCharCode(j));return m.join('+');};var g=/\$\{(.*?)\}/g;function h(j,k){var l=a.config.keystrokes,m,n=l.length;for(var o=0;o%1'+''+b.contents+' ',k='%1 %2 ',l='%1 %2 ',m=[],n=b.legend,o=n.length;for(var p=0;p'+'.cke_accessibility_legend'+'{'+'width:600px;'+'height:400px;'+'padding-right:5px;'+'overflow-y:auto;'+'overflow-x:hidden;'+'}'+'.cke_accessibility_legend h1'+'{'+'font-size: 20px;'+'border-bottom: 1px solid #AAA;'+'margin: 5px 0px 15px;'+'}'+'.cke_accessibility_legend dl'+'{'+'margin-left: 5px;'+'}'+'.cke_accessibility_legend dt'+'{'+'font-size: 13px;'+'font-weight: bold;'+'}'+'.cke_accessibility_legend dd'+'{'+'white-space:normal;'+'margin:10px'+'}'+''}]}],buttons:[CKEDITOR.dialog.cancelButton]};
+});
diff --git a/webroot/js/ckeditor/plugins/a11yhelp/lang/en.js b/webroot/js/ckeditor/plugins/a11yhelp/lang/en.js
new file mode 100755
index 00000000..50b21a40
--- /dev/null
+++ b/webroot/js/ckeditor/plugins/a11yhelp/lang/en.js
@@ -0,0 +1,6 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.plugins.setLang('a11yhelp','en',{accessibilityHelp:{title:'Accessibility Instructions',contents:'Help Contents. To close this dialog press ESC.',legend:[{name:'General',items:[{name:'Editor Toolbar',legend:'Press ${toolbarFocus} to navigate to the toolbar. Move to next toolbar button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to activate the toolbar button.'},{name:'Editor Dialog',legend:'Inside a dialog, press TAB to navigate to next dialog field, press SHIFT + TAB to move to previous field, press ENTER to submit dialog, press ESC to cancel dialog. For dialogs that have multiple tab pages, press ALT + F10 to navigate to tab-list. Then move to next tab with TAB OR RIGTH ARROW. Move to previous tab with SHIFT + TAB or LEFT ARROW. Press SPACE or ENTER to select the tab page.'},{name:'Editor Context Menu',legend:'Press ${contextMenu} or APPLICATION KEY to open context-menu. Then move to next menu option with TAB or DOWN ARROW. Move to previous option with SHIFT+TAB or UP ARROW. Press SPACE or ENTER to select the menu option. Open sub-menu of current option wtih SPACE or ENTER or RIGHT ARROW. Go back to parent menu item with ESC or LEFT ARROW. Close context menu with ESC.'},{name:'Editor List Box',legend:'Inside a list-box, move to next list item with TAB OR DOWN ARROW. Move to previous list item with SHIFT + TAB or UP ARROW. Press SPACE or ENTER to select the list option. Press ESC to close the list-box.'},{name:'Editor Element Path Bar',legend:'Press ${elementsPathFocus} to navigate to the elements path bar. Move to next element button with TAB or RIGHT ARROW. Move to previous button with SHIFT+TAB or LEFT ARROW. Press SPACE or ENTER to select the element in editor.'}]},{name:'Commands',items:[{name:' Undo command',legend:'Press ${undo}'},{name:' Redo command',legend:'Press ${redo}'},{name:' Bold command',legend:'Press ${bold}'},{name:' Italic command',legend:'Press ${italic}'},{name:' Underline command',legend:'Press ${underline}'},{name:' Link command',legend:'Press ${link}'},{name:' Toolbar Collapse command',legend:'Press ${toolbarCollapse}'},{name:' Accessibility Help',legend:'Press ${a11yHelp}'}]}]}});
diff --git a/webroot/js/ckeditor/plugins/colordialog/dialogs/colordialog.js b/webroot/js/ckeditor/plugins/colordialog/dialogs/colordialog.js
new file mode 100755
index 00000000..4e32e7fd
--- /dev/null
+++ b/webroot/js/ckeditor/plugins/colordialog/dialogs/colordialog.js
@@ -0,0 +1,6 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.dialog.add('colordialog',function(a){var b=CKEDITOR.dom.element,c=CKEDITOR.document,d=CKEDITOR.tools,e=a.lang.colordialog,f;function g(){return{type:'html',html:' '};};var h=new b('table');k();var i=function(n){var o=new b(n.data.getTarget()).getAttribute('title');c.getById('hicolor').setStyle('background-color',o);c.getById('hicolortext').setHtml(o);},j=function(n){var o=new b(n.data.getTarget()).getAttribute('title');f.getContentElement('picker','selectedColor').setValue(o);};function k(){var n=['00','33','66','99','cc','ff'];function o(t,u){for(var v=t;v'+h.getHtml()+'',onLoad:function(){var n=CKEDITOR.document.getById(this.domId);n.on('mouseover',i);n.on('click',j);}},g(),{type:'vbox',padding:0,widths:['70%','5%','25%'],children:[{type:'html',html:''+e.highlight+' \t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t'+e.selected+' \t\t\t\t\t\t\t\t\t\t\t\t
'},{type:'text',id:'selectedColor',style:'width: 74px',onChange:function(){try{c.getById('selhicolor').setStyle('background-color',this.getValue());}catch(n){l();}}},g(),{type:'button',id:'clear',style:'margin-top: 5px',label:e.clear,onClick:l}]}]}]}]};});
diff --git a/webroot/js/ckeditor/plugins/div/dialogs/div.js b/webroot/js/ckeditor/plugins/div/dialogs/div.js
new file mode 100755
index 00000000..ff47f6d4
--- /dev/null
+++ b/webroot/js/ckeditor/plugins/div/dialogs/div.js
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function(){function a(d,e,f){if(!e.is||!e.getCustomData('block_processed')){e.is&&CKEDITOR.dom.element.setMarker(f,e,'block_processed',true);d.push(e);}};function b(d){var e=[],f=d.getChildren();for(var g=0;g1?'enable':'disable']();setTimeout(function(){q.setup(p._element);},0);});},onShow:function(){if(e=='editdiv'){var p=k(d);p&&this.setupContent(this._element=p);}},onOk:function(){if(e=='editdiv')o=[this._element];else o=j(d,true);var p=o.length;for(var q=0;qf)e=n-f;j['cke:margin']=f=n;}]])(j.style,h)||'';var l=k.attributes,m=l.style;
+h.addStyle(m);CKEDITOR.tools.extend(j,l);return true;}return false;},convertToPx:(function(){var h=CKEDITOR.dom.element.createFromHtml('
',CKEDITOR.document);CKEDITOR.document.getBody().append(h);return function(i){if(c.test(i)){h.setStyle('width',i);return h.$.clientWidth+'px';}return i;};})(),getStyleComponents:(function(){var h=CKEDITOR.dom.element.createFromHtml('
',CKEDITOR.document);CKEDITOR.document.getBody().append(h);return function(i,j,k){h.setStyle(i,j);var l={},m=k.length;for(var n=0;nr){p=new CKEDITOR.htmlParser.element(m);p.add(k);o.add(p);}else if(n3?'large':D.size<3?'small':'medium')+';';delete D.size;}C.name='span';C.addStyle(E);}},span:function(C){if(!CKEDITOR.env.gecko&&u(C.parent))return false;C.filterChildren();if(v(C)){delete C.name;return null;}if(!CKEDITOR.env.gecko&&u(C)){var D=C.firstChild(function(K){return K.value||K.name=='img';}),E=D&&(D.value||'l.'),F=E.match(/^([^\s]+?)([.)]?)$/);return r(F,E);}var G=C.children,H=C.attributes,I=H&&H.style,J=G&&G[0];if(I)H.style=n([['line-height'],[/^font-family$/,null,!A?p(k.font_style,'family'):null],[/^font-size$/,null,!A?p(k.fontSize_style,'size'):null],[/^color$/,null,!A?p(k.colorButton_foreStyle,'color'):null],[/^background-color$/,null,!A?p(k.colorButton_backStyle,'color'):null]])(I,C)||'';return null;},b:o(k.coreStyles_bold),i:o(k.coreStyles_italic),u:o(k.coreStyles_underline),s:o(k.coreStyles_strike),sup:o(k.coreStyles_superscript),sub:o(k.coreStyles_subscript),a:function(C){var D=C.attributes;if(D&&!D.href&&D.name)delete C.name;},'cke:listbullet':function(C){if(C.getAncestor(/h\d/)&&!k.pasteFromWordNumberedHeadingToList)delete C.name;}},attributeNames:[[/^onmouse(:?out|over)/,''],[/^onload$/,''],[/(?:v|o):\w+/,''],[/^lang/,'']],attributes:{style:n(B?[[/^margin$|^margin-(?!bottom|top)/,null,function(C,D,E){if(D.name in {p:1,div:1}){var F=k.contentsLangDirection=='ltr'?'margin-left':'margin-right';if(E=='margin')C=y(E,C,[F])[F];else if(E!=F)return null;if(C&&!d.test(C))return[F,C];}return null;}],[/^clear$/],[/^border.*|margin.*|vertical-align|float$/,null,function(C,D){if(D.name=='img')return C;}],[/^width|height$/,null,function(C,D){if(D.name in {table:1,td:1,th:1,img:1})return C;
+}]]:[[/^mso-/],[/-color$/,null,function(C){if(C=='transparent')return false;if(CKEDITOR.env.gecko)return C.replace(/-moz-use-text-color/g,'transparent');}],[/^margin$/,d],['text-indent','0cm'],['page-break-before'],['tab-stops'],['display','none'],A?[/font-?/]:null],B),width:function(C,D){if(D.name in i.$tableContent)return false;},border:function(C,D){if(D.name in i.$tableContent)return false;},'class':m,bgcolor:m,valign:B?m:function(C,D){D.addStyle('vertical-align',C);return false;}},comment:!CKEDITOR.env.ie?function(C,D){var E=C.match(//),F=C.match(/^\[if !supportLists\]([\s\S]*?)\[endif\]$/);if(F){var G=F[1]||E&&'l.',H=G&&G.match(/>([^\s]+?)([.)]?));return r(H,G);}if(CKEDITOR.env.gecko&&E){var I=CKEDITOR.htmlParser.fragment.fromHtml(E[0]).children[0],J=D.previous,K=J&&J.value.match(/]*o:href=['"](.*?)['"]/),L=K&&K[1];L&&(I.attributes.src=L);return I;}return false;}:m};}};var g=function(){this.dataFilter=new CKEDITOR.htmlParser.filter();};g.prototype={toHtml:function(h){var i=CKEDITOR.htmlParser.fragment.fromHtml(h,false),j=new CKEDITOR.htmlParser.basicWriter();i.writeHtml(j,this.dataFilter);return j.getHtml(true);}};CKEDITOR.cleanWord=function(h,i){if(CKEDITOR.env.gecko)h=h.replace(/(([\S\s]*?))/gi,'$1$2$3');var j=new g(),k=j.dataFilter;k.addRules(CKEDITOR.plugins.pastefromword.getRules(i));i.fire('beforeCleanWord',{filter:k});try{h=j.toHtml(h,false);}catch(l){alert(i.lang.pastefromword.error);}h=h.replace(/cke:.*?".*?"/g,'');h=h.replace(/style=""/g,'');h=h.replace(//g,'');return h;};})();
diff --git a/webroot/js/costing_dialog.js b/webroot/js/costing_dialog.js
new file mode 100644
index 00000000..f455ee78
--- /dev/null
+++ b/webroot/js/costing_dialog.js
@@ -0,0 +1,21 @@
+$(function() {
+
+
+/*
+ * Fetch the costing add form. Place it in element ID 'costingdiv'
+ *
+ * @todo - write a plugin that generalises the method. It would be handy with the cake way of doing things
+ *
+ */
+function AjaxFetchPage() {
+ $.post("/costings/", $("#LineItemQuoteId").serialize(), function (itemTable) {
+ $("#productTable").html(itemTable);
+ });
+}
+
+
+
+
+});
+
+
diff --git a/webroot/js/editLineItem.js b/webroot/js/editLineItem.js
new file mode 100644
index 00000000..34d26dad
--- /dev/null
+++ b/webroot/js/editLineItem.js
@@ -0,0 +1,106 @@
+/*
+ * editLineItem.js
+ * author: Karl Cordes
+ *
+ * 1. Watch links with class 'editLineItem'.
+ * 2. When clicked. Fetch their /edit/id page
+ * 3. update the contents of the editLineItem div
+ * 4. open a dialog box.
+ * 5. submit the form via AJAX
+ *
+ */
+
+$(function() {
+
+
+ $("#editLineItem").dialog({
+ autoOpen: false,
+ height: 800,
+ width: 800,
+ modal: true,
+ buttons: {
+ 'Add Product': function() {
+
+ $.post("/line_items/ajaxSave", $("#LineItemAddForm").serialize(), function(data) {
+
+ fetchTable();
+ $('#mydebug').html(data);
+ }
+ );
+
+ $("#LineItemAddForm").resetForm();
+ $(this).dialog('close');
+ },
+ Cancel: function() {
+ $(this).dialog('close');
+ }
+ },
+ close: function() {
+
+ },
+ open: function () {
+ $('.ckeditor').ckeditor();
+ }
+ });
+
+
+
+
+ $("a.editLink").click(function (event) {
+
+ var linkTarget = $(this).attr("href");
+
+
+ $("#editLineItem").load(linkTarget, function() {
+
+
+ $('#editLineItem').dialog('open');
+
+
+ });
+
+
+ event.preventDefault();
+ return false;
+ });
+
+
+
+
+
+});
+
+
+/**
+ * Do the simple calculation of net price after discount.
+ *
+ */
+
+
+function calcNetPrice() {
+ var discountPercent = $("#discountPercent").val();
+ var unitPrice = $('#unitPrice').val();
+
+
+ var quantity = $('#LineItemQuantity').val();
+
+
+ var grossSellPrice = quantity * unitPrice;
+
+ //Calculate the Sale Discount amount.
+ var UnitDiscountAmount = (discountPercent/100) * unitPrice;
+
+ var TotalDiscountAmount = (discountPercent/100) * grossSellPrice;
+ UnitDiscountAmount = UnitDiscountAmount.toFixed(2);
+ TotalDiscountAmount = TotalDiscountAmount.toFixed(2);
+
+ $('#total_discountAmount').val(TotalDiscountAmount);
+ $('#discountAmountEach').val(UnitDiscountAmount);
+ $('#net_price_each').val(unitPrice - UnitDiscountAmount);
+
+ $('#grossPrice').val(grossSellPrice);
+
+ var netPrice = grossSellPrice - TotalDiscountAmount;
+ $('#netPrice').val(netPrice);
+
+}
\ No newline at end of file
diff --git a/webroot/js/enquiry_table.js b/webroot/js/enquiry_table.js
new file mode 100644
index 00000000..1c125b11
--- /dev/null
+++ b/webroot/js/enquiry_table.js
@@ -0,0 +1,71 @@
+
+$(function() {
+
+ $('#$enqid').editable('/enquiries/update_status', {
+ id : 'data[Enquiry][id]',
+ name: 'data[Enquiry][status_id]',
+
+ data : '$jsonList',
+ type : 'select',
+ indicator : 'Saving...',
+ submit : 'Update Status',
+ cssclass: 'MER-inplace-select',
+ callback : function(value, settings) {
+
+ var match = /won/i.test(value);
+
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('jobwon');
+ return;
+ }
+
+ match = /lost/i.test(value);
+
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('joblost');
+ return;
+ }
+
+ match = /cancelled/i.test(value);
+
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('joblost');
+ return;
+ }
+
+ match = /information sent/i.test(value);
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('informationsent');
+ return;
+ }
+
+ match = /issued/i.test(value);
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('quoted');
+ return;
+ }
+
+ match = /request for quotation/i.test(value);
+ if(match == true) {
+ $('#row$enqid').removeClass().addClass('requestforquote');
+ return;
+ }
+
+ match = /assigned/i.test(value);
+ if(match == true) {
+ $('#row$enqid').removeClass();
+ return;
+ }
+
+ }
+
+ });
+
+
+}
+
+
+function makeEditable(selectedID) {
+
+
+}