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');?> +
+
+ +
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');?> +
+
+ +
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) + )); + ?>

+ + + + + + + + + + + + + + + + > + + + + + + + "; + } + else { + echo "PAID"; + echo ""; + echo ""; + } + + + + ?> + + + + + + + +
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 ""; + 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'));?> +
+
+ +
+ + \ 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'])); ?> +   + +
+
+
+ +
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');?> +
+
+ +
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');?> +
+
+ +
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'));?> +
+
+ +
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 @@ +
+

+
+ > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + + > + > + +   + +
+
+
+ +
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 +

+ +
+ +
+
+

+ This sample shows how to use the CKeditor JavaScript API to interact with the editor + at runtime.

+ + + + +
+
+ +
+ + + 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 +

+ +
+ +
+
+

+ In this sample the editor is configured to edit entire HTML pages, from the <html> + tag to </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 +

+ +
+ +
+ +
+

+
+ +

+

+ +

+
+ + + 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 +

+ +
+ +
+ +
+ Output +
+

+
+

+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("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 +

+ +
+ +
+ +
+ Output +
+

+
+

+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("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 +

+ +
+ +
+ +
+ Output +
+

+
+ +

+

+ +

+
+
+ + 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 +

+ +
+ +
+ +
+ Output +
+

+
+ +

+

+
+ +

+

+ +

+
+
+ + 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 +

+ +
+ +
+ +
+ Output +
+

+
+

+

+ 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 +

+ +
+ +
+
+
+
+

+
+ +

+

+
+ +

+

+
+ +

+

+
+ +

+

+ +

+
+
+
+ + + + 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 : '' + table.getHtml() + '
', + 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.
  • level1
    1. level2
  • => + // 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]+?)([.)]?) 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 = "\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 = "\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]+?)([.)]?)]*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) { + + +}