Browse Source

Merge branch '1.11.x' of https://github.com/chamilo/chamilo-lms into socialTest

José Loguercio 8 years ago
parent
commit
a3e86a2ad7
100 changed files with 4235 additions and 524 deletions
  1. 5 0
      .htaccess
  2. 22 1
      .scrutinizer.yml
  3. 19 16
      .travis.yml
  4. 2 1
      README.md
  5. 5 0
      app/Migrations/Schema/V110/Version110.php
  6. 5 5
      app/Migrations/Schema/V110/Version20150603181728.php
  7. 1 1
      app/Migrations/Schema/V110/Version20151101082200.php
  8. 14 1
      app/Migrations/Schema/V110/Version20151101082300.php
  9. 155 1
      app/Migrations/Schema/V111/Version111.php
  10. 46 0
      app/Migrations/Schema/V111/Version20160603113100.php
  11. 92 0
      app/Migrations/Schema/V111/Version20160610142700.php
  12. 36 0
      app/Migrations/Schema/V111/Version20160623143200.php
  13. 47 0
      app/Migrations/Schema/V111/Version20160628220000.php
  14. 39 0
      app/Migrations/Schema/V111/Version20160701110000.php
  15. 5 5
      app/Resources/public/assets/blueimp-tmpl/.bower.json
  16. 7 9
      app/Resources/public/assets/blueimp-tmpl/README.md
  17. 2 3
      app/Resources/public/assets/blueimp-tmpl/js/compile.js
  18. 1 1
      app/Resources/public/assets/blueimp-tmpl/package.json
  19. 20 20
      app/Resources/public/assets/ckeditor/plugins/scayt/CHANGELOG.md
  20. 28 28
      app/Resources/public/assets/ckeditor/plugins/scayt/LICENSE.md
  21. 25 0
      app/Resources/public/assets/ckeditor/plugins/scayt/README.md
  22. 573 19
      app/Resources/public/assets/ckeditor/plugins/scayt/dialogs/options.js
  23. 71 71
      app/Resources/public/assets/ckeditor/plugins/scayt/dialogs/toolbar.css
  24. BIN
      app/Resources/public/assets/ckeditor/plugins/scayt/icons/hidpi/scayt.png
  25. BIN
      app/Resources/public/assets/ckeditor/plugins/scayt/icons/scayt.png
  26. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/af.js
  27. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ar.js
  28. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/bg.js
  29. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/bn.js
  30. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/bs.js
  31. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ca.js
  32. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/cs.js
  33. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/cy.js
  34. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/da.js
  35. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/de.js
  36. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/el.js
  37. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-au.js
  38. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-ca.js
  39. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-gb.js
  40. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/en.js
  41. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/eo.js
  42. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/es.js
  43. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/et.js
  44. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/eu.js
  45. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/fa.js
  46. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/fi.js
  47. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/fo.js
  48. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/fr-ca.js
  49. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/fr.js
  50. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/gl.js
  51. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/gu.js
  52. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/he.js
  53. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/hi.js
  54. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/hr.js
  55. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/hu.js
  56. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/is.js
  57. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/it.js
  58. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ja.js
  59. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ka.js
  60. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/km.js
  61. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ko.js
  62. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ku.js
  63. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/lt.js
  64. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/lv.js
  65. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/mk.js
  66. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/mn.js
  67. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ms.js
  68. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/nb.js
  69. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/nl.js
  70. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/no.js
  71. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/pl.js
  72. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/pt-br.js
  73. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/pt.js
  74. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ro.js
  75. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ru.js
  76. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/sk.js
  77. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/sl.js
  78. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/sr-latn.js
  79. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/sr.js
  80. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/sv.js
  81. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/th.js
  82. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/tr.js
  83. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/ug.js
  84. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/uk.js
  85. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/vi.js
  86. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/zh-cn.js
  87. 13 0
      app/Resources/public/assets/ckeditor/plugins/scayt/lang/zh.js
  88. 1877 0
      app/Resources/public/assets/ckeditor/plugins/scayt/plugin.js
  89. 5 5
      app/Resources/public/assets/jquery-file-upload/.bower.json
  90. 1 1
      app/Resources/public/assets/jquery-file-upload/bower.json
  91. 2 2
      app/Resources/public/assets/jquery-file-upload/js/jquery.fileupload-process.js
  92. 6 6
      app/Resources/public/assets/jquery-file-upload/js/jquery.fileupload.js
  93. 5 5
      app/Resources/public/assets/mediaelement/.bower.json
  94. BIN
      app/Resources/public/assets/mediaelement/build/flashmediaelement-cdn.swf
  95. BIN
      app/Resources/public/assets/mediaelement/build/flashmediaelement-debug.swf
  96. BIN
      app/Resources/public/assets/mediaelement/build/flashmediaelement.swf
  97. 172 180
      app/Resources/public/assets/mediaelement/build/mediaelement-and-player.js
  98. 0 0
      app/Resources/public/assets/mediaelement/build/mediaelement-and-player.min.js
  99. 141 143
      app/Resources/public/assets/mediaelement/build/mediaelement.js
  100. 0 0
      app/Resources/public/assets/mediaelement/build/mediaelement.min.js

+ 5 - 0
.htaccess

@@ -45,3 +45,8 @@ RewriteRule ^badge/(\d{1,}) main/badge/issued.php?issue=$1 [L]
 RewriteRule ^skill/(\d{1,})/user/(\d{1,}) main/badge/issued_all.php?skill=$1&user=$2 [L]
 # Support deprecated URL (avoid 404)
 RewriteRule ^badge/(\d{1,})/user/(\d{1,}) main/badge/issued_all.php?skill=$1&user=$2 [L]
+
+# Support old URLs using the exercice (with a c) folder rather than exercise
+RewriteRule ^main/exercice/(.*)$ main/exercise/$1 [QSA,L]
+# Support old URLs using the newscorm folder rather than lp
+RewriteRule ^main/newscorm/(.*)$ main/lp/$1 [QSA,L]

+ 22 - 1
.scrutinizer.yml

@@ -1,6 +1,9 @@
 # .scrutinizer.yml - see https://scrutinizer-ci.com/docs/guides/php/continuous-integration-deployment for doc
+# Excludes go for things do not contain code, are not managed well by Scrutinizer or are external libraries that
+# Chamilo includes but that we cannot update without patching upstream.
 build:
     environment:
+        mysql: 5.5
         php:
             version: 5.6.0
             ini:
@@ -9,8 +12,10 @@ build:
         hosts:
             my.chamilodev.net: '127.0.0.1'
     dependencies:
+        override:
+            - true
         before:
-            - composer -v update
+            - php -d memory_limit=2G /usr/bin/composer.phar -v update
 filter:
     excluded_paths:
         - tests/*
@@ -21,6 +26,22 @@ filter:
         - web/*
         - vendor/*
         - main/admin/db.php
+        - app/Migrations/*
+        - main/inc/lib/browser/*
+        - main/inc/lib/elfinder/*
+        - main/inc/lib/freemindflashbrowser/*
+        - main/inc/lib/kses-0.2.2/*
+        - main/inc/lib/mimetex/*
+        - main/inc/lib/nanogong/*
+        - main/inc/lib/pclzip/*
+        - main/inc/lib/pear/*
+        - main/inc/lib/phpmailer/*
+        - main/inc/lib/phpseclib/*
+        - main/inc/lib/svg-edit/*
+        - main/inc/lib/swfobject/*
+        - main/inc/lib/wami-recorder/*
+        - main/inc/lib/xajax/*
+        - main/auth/cas/lib/CAS/*
 checks:
     php:
         code_rating: true

+ 19 - 16
.travis.yml

@@ -12,6 +12,18 @@ before_install:
   - sudo apt-get update -qq
   - sudo apt-get install -qq mysql-server
   - sudo apt-get install -qq apache2 libapache2-mod-fastcgi
+  # enable php-fpm
+  - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
+  - sudo a2enmod rewrite actions fastcgi alias
+  - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - echo "memory_limit = 2G" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - echo "phar.readonly = 0" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - echo "date.timezone = Europe/Paris" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
+  # configure apache virtual hosts
+  - sudo cp -f tests/travis-apache /etc/apache2/sites-available/default
+  - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/default
+  - sudo service apache2 restart
   # Install additional PHP packages (check http://docs.travis-ci.com/user/ci-environment/#CI-environment-OS
   # for pre-installed packages)
   #- sudo apt-get install -qq php5-imagick
@@ -19,12 +31,12 @@ before_install:
   # php is compiled with --enable-fpm, so no install of FPM is needed.
   # However, not installing it generates errors with service php5-fpm restart
   # further down (need to use php-fpm without 5)
-  - sudo apt-get install -qq php5-cli php5-fpm
+  #- sudo apt-get install -qq php5-cli php5-fpm
 
 before_script:
-  - php5 -v
-  - php5 -m
-  - composer self-update
+  #- which composer
+  #- php -d memory_limit=2G /usr/bin/composer update
+  #- php -d memory_limit=2G /home/travis/.phpenv/shims/composer update
   # Previously, fxp/composer-asset-plugin was required but was causing a lot of trouble updating. Now it's disabled.
   #- composer global require "fxp/composer-asset-plugin:1.0.3"
   # You can either use the composer install method and face the Github limit
@@ -43,23 +55,14 @@ before_script:
   # Continue...
   - phpenv config-add tests/travis-php-config.ini
   # enable php-fpm
-  - sudo /etc/init.d/php5-fpm stop
-  - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
-  - sudo a2enmod rewrite actions fastcgi alias
-  - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-  - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
   # configure apache virtual hosts
-  - sudo cp -f tests/travis-apache /etc/apache2/sites-available/default
-  - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/default
-  - sudo service apache2 restart
-  - sudo service php5-fpm restart
-  - php5 -v
+  - php -v
   # install Chash, a database, and then install Chamilo
   - git clone https://github.com/chamilo/chash
   - cd chash
   - composer install
   - composer update
-  - php5 -d phar.readonly=0 createPhar.php
+  - php -d phar.readonly=0 createPhar.php
   - chmod +x chash.phar
   - sudo mv chash.phar /usr/local/bin/chash
   #- cd ..
@@ -74,7 +77,7 @@ before_script:
   - cd /home/travis/build/chamilo/chamilo-lms
   # There's an issue with Chash, starting in version 1.10, whereby PHP CLI on Travis-ci is PHP5.3, whatever the version you ask for.
   # This effectively breaks the installer and renders these tests useless. We are looking for a solution (for example using containers)
-  - sudo chash chash:chamilo_install --no-interaction --sitename="Chamilo" --site_url="http://localhost/" --institution="Chamilo" --institution_url="https://chamilo.org" --encrypt_method="sha1" --firstname="John" --lastname="Doe" --language="english" --driver="mysqlnd" --host="localhost" --port="3306" --dbname="chamilo" --dbuser="root" --permissions_for_new_directories="0777" --permissions_for_new_files="0666" --linux-user="www-data" --linux-group="www-data" --username="admin" --password="admin" --email="admin@example.com" --phone="555-5555" 1.10.x
+  - sudo chash chash:chamilo_install --no-interaction --sitename="Chamilo" --site_url="http://localhost/" --institution="Chamilo" --institution_url="https://chamilo.org" --encrypt_method="sha1" --firstname="John" --lastname="Doe" --language="english" --driver="pdo_mysql" --host="localhost" --port="3306" --dbname="chamilo" --dbuser="root" --permissions_for_new_directories="0777" --permissions_for_new_files="0666" --linux-user="www-data" --linux-group="www-data" --username="admin" --password="admin" --email="admin@example.com" --phone="555-5555" 1.10.x
 
 script:
   # - phpunit -c tests/phpunit

+ 2 - 1
README.md

@@ -5,6 +5,7 @@
 [![Code Coverage](https://scrutinizer-ci.com/g/chamilo/chamilo-lms/badges/coverage.png?b=1.11.x)](https://scrutinizer-ci.com/g/chamilo/chamilo-lms/?branch=1.11.x)
 [![Bountysource](https://www.bountysource.com/badge/team?team_id=12439&style=raised)](https://www.bountysource.com/teams/chamilo?utm_source=chamilo&utm_medium=shield&utm_campaign=raised)
 [![Code Consistency](https://squizlabs.github.io/PHP_CodeSniffer/analysis/chamilo/chamilo-lms/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/chamilo/chamilo-lms/)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/166/badge)](https://bestpractices.coreinfrastructure.org/projects/166)
 
 ## Installation
 
@@ -164,7 +165,7 @@ php bin/doctrine.php migrations:execute 20150527120703 --up --configuration=app/
 
 You can also print the differences between your database and what it should be by issuing the following command from the Chamilo base folder:
 ```
-php bin/doctrine.php orm:schema:update --dump-sql
+php bin/doctrine.php orm:schema-tool:update --dump-sql
 ```
 
 ## Contributing

+ 5 - 0
app/Migrations/Schema/V110/Version110.php

@@ -153,7 +153,9 @@ class Version110 extends AbstractMigrationChamilo
         $this->addSql("ALTER TABLE session_rel_course ADD COLUMN category varchar(255) default ''");
         $this->addSql("ALTER TABLE session_rel_course ADD COLUMN c_id int unsigned");
         $this->addSql("ALTER TABLE session_rel_course CHANGE id_session session_id int");
+        $this->addSql('DELETE FROM session_rel_course WHERE session_id NOT IN (SELECT id FROM session)');
 
+        $this->addSql("DELETE course_rel_user WHERE course_code NOT IN (SELECT code FROM course)");
         $this->addSql("UPDATE course_rel_user SET c_id = (SELECT id FROM course WHERE code = course_code)");
 
         // Add iid
@@ -417,6 +419,7 @@ class Version110 extends AbstractMigrationChamilo
 
         $this->addSql("ALTER TABLE session_rel_user CHANGE id_session session_id int");
         $this->addSql("ALTER TABLE session_rel_user CHANGE id_user user_id int");
+        $this->addSql("DELETE FROM session_rel_user WHERE user_id NOT IN (SELECT user_id FROM user)");
         $this->addSql("ALTER TABLE session_rel_user ADD COLUMN id int NOT NULL PRIMARY KEY AUTO_INCREMENT");
 
         $this->addSql("ALTER TABLE c_item_property CHANGE id_session session_id int");
@@ -511,8 +514,10 @@ class Version110 extends AbstractMigrationChamilo
         $this->addSql("UPDATE track_e_attempt SET c_id = (SELECT id FROM course WHERE code = course_code)");
         $this->addSql("UPDATE course_field_values SET c_id = (SELECT id FROM course WHERE code = course_code)");
         $this->addSql("UPDATE session_rel_course_rel_user SET c_id = (SELECT id FROM course WHERE code = course_code)");
+        $this->addSql('DELETE FROM session_rel_course WHERE course_code NOT IN (SELECT code FROM course)');
         $this->addSql("UPDATE session_rel_course SET c_id = (SELECT id FROM course WHERE code = course_code)");
 
+        $this->addSql("DELETE access_url_rel_course WHERE course_code NOT IN (SELECT code FROM course)");
         $this->addSql("UPDATE access_url_rel_course SET c_id = (SELECT id FROM course WHERE code = course_code)");
 
         $this->addSql("ALTER TABLE settings_current DROP INDEX unique_setting");

+ 5 - 5
app/Migrations/Schema/V110/Version20150603181728.php

@@ -49,9 +49,9 @@ class Version20150603181728 extends AbstractMigrationChamilo
             MODIFY session_id INT DEFAULT NULL,
             MODIFY to_user_id INT NULL
         ');
-        $this->addSql("UPDATE c_item_property SET session_id = NULL WHERE session_id = 0");
-        $this->addSql("UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0");
-        $this->addSql("UPDATE c_item_property SET to_user_id = NULL WHERE to_user_id = 0");
+        $this->addSql("UPDATE c_item_property SET session_id = NULL WHERE session_id NOT IN (SELECT id FROM session)");
+        $this->addSql("UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id NOT IN (SELECT iid FROM c_group_info)");
+        $this->addSql("UPDATE c_item_property SET to_user_id = NULL WHERE to_user_id NOT IN (SELECT user_id FROM user)");
         $this->addSql("UPDATE c_item_property SET start_visible = NULL WHERE start_visible = '0000-00-00 00:00:00'");
         $this->addSql("UPDATE c_item_property SET end_visible = NULL WHERE end_visible = '0000-00-00 00:00:00'");
         $this->addSql("UPDATE c_item_property SET to_user_id = NULL WHERE to_user_id NOT IN (SELECT id FROM user)");
@@ -59,9 +59,9 @@ class Version20150603181728 extends AbstractMigrationChamilo
         $this->addSql("UPDATE c_item_property SET session_id = NULL WHERE session_id NOT IN (SELECT id FROM session)");
 
         // Remove inconsistencies about non-existing courses
-        $this->addSql("DELETE FROM c_item_property WHERE c_id = 0");
+        $this->addSql("DELETE FROM c_item_property WHERE c_id NOT IN (SELECT user_id FROM user)");
         // Remove inconsistencies about non-existing users
-        $this->addSql("DELETE FROM course_rel_user WHERE user_id = 0");
+        $this->addSql("DELETE FROM course_rel_user WHERE user_id NOT IN (SELECT user_id FROM user)");
 
         $this->addSql("DELETE FROM c_item_property WHERE c_id NOT IN (SELECT id FROM course)");
         $this->addSql("DELETE FROM c_item_property WHERE to_group_id NOT IN (SELECT id FROM c_group_info)");

+ 1 - 1
app/Migrations/Schema/V110/Version20151101082200.php

@@ -29,7 +29,7 @@ class Version20151101082200 extends AbstractMigrationChamilo
         $this->addSql("ALTER TABLE session_rel_course_rel_user DROP PRIMARY KEY");
         $this->addSql("ALTER TABLE session MODIFY session_category_id INT NULL");
 
-        $this->addSql("UPDATE session SET session_category_id = NULL WHERE session_category_id = 0");
+        $this->addSql("UPDATE session SET session_category_id = NULL WHERE session_category_id NOT IN (SELECT id FROM session_category)");
     }
 
     /**

+ 14 - 1
app/Migrations/Schema/V110/Version20151101082300.php

@@ -20,6 +20,8 @@ class Version20151101082300 extends AbstractMigrationChamilo
         $accessUrl = $schema->getTable('access_url');
         $accessUrl->getColumn('id')->setUnsigned(false);
 
+        $this->connection->executeQuery('UPDATE access_url_rel_course SET access_url_id = NULL WHERE access_url_id NOT IN (SELECT id FROM access_url)');
+
         $accessUrlRelCourse = $schema->getTable('access_url_rel_course');
         $accessUrlRelCourse->getColumn('access_url_id')->setUnsigned(false);
         $accessUrlRelCourse->addForeignKeyConstraint('access_url', ['access_url_id'], ['id']);
@@ -223,6 +225,8 @@ class Version20151101082300 extends AbstractMigrationChamilo
         $session->addForeignKeyConstraint('session_category', ['session_category_id'], ['id']);
         $session->addForeignKeyConstraint('user', ['id_coach'], ['id']);
 
+        $this->connection->executeQuery('UPDATE session_category SET access_url_id = 1 WHERE access_url_id NOT IN (SELECT id FROM access_url)');
+
         $sessionCategory = $schema->getTable('session_category');
         $sessionCategory->addIndex(['access_url_id']);
         $sessionCategory->addForeignKeyConstraint('access_url', ['access_url_id'], ['id']);
@@ -237,6 +241,10 @@ class Version20151101082300 extends AbstractMigrationChamilo
         $sessionRelCourse->addForeignKeyConstraint('course', ['c_id'], ['id']);
         $sessionRelCourse->addForeignKeyConstraint('session', ['session_id'], ['id']);
 
+        $this->connection->executeQuery('DELETE FROM session_rel_course_rel_user WHERE c_id NOT IN (SELECT id FROM course)');
+        $this->connection->executeQuery('DELETE FROM session_rel_course_rel_user WHERE session_id NOT IN (SELECT id FROM session)');
+        $this->connection->executeQuery('DELETE FROM session_rel_course_rel_user WHERE user_id NOT IN (SELECT id FROM user)');
+
         $sessionRelCourseRelUser = $schema->getTable('session_rel_course_rel_user');
         $sessionRelCourseRelUser->dropColumn('course_code');
         $sessionRelCourseRelUser->addColumn('id', Type::INTEGER)->setAutoincrement(true);
@@ -248,11 +256,13 @@ class Version20151101082300 extends AbstractMigrationChamilo
         $sessionRelCourseRelUser->addForeignKeyConstraint('session', ['session_id'], ['id']);
         $sessionRelCourseRelUser->addForeignKeyConstraint('user', ['user_id'], ['id']);
 
+        $this->connection->executeQuery('DELETE FROM session_rel_user WHERE user_id NOT IN (SELECT id FROM user)');
+        $this->connection->executeQuery('DELETE FROM session_rel_user WHERE session_id NOT IN (SELECT id FROM session)');
+
         $sessionRelUser = $schema->getTable('session_rel_user');
         $sessionRelUser->addColumn('moved_to', Type::INTEGER)->setNotnull(false);
         $sessionRelUser->addColumn('moved_status', Type::INTEGER)->setNotnull(false);
         $sessionRelUser->addColumn('moved_at', Type::DATETIME)->setNotnull(false);
-
         $sessionRelUser->addIndex(['session_id']);
         $sessionRelUser->addIndex(['user_id']);
         $sessionRelUser->addIndex(['user_id', 'moved_to']);
@@ -283,6 +293,9 @@ class Version20151101082300 extends AbstractMigrationChamilo
         $schema->getTable('track_e_uploads')->addIndex(['c_id']);
         $schema->getTable('user')->addUniqueIndex(['username_canonical']);
 
+        $this->connection->executeQuery('DELETE FROM usergroup_rel_user WHERE user_id NOT IN (SELECT id FROM user)');
+        $this->connection->executeQuery('DELETE FROM usergroup_rel_user WHERE usergroup_id NOT IN (SELECT id FROM usergroup)');
+
         $usergroupRelUSer = $schema->getTable('usergroup_rel_user');
         $usergroupRelUSer->addIndex(['user_id']);
         $usergroupRelUSer->addIndex(['usergroup_id']);

+ 155 - 1
app/Migrations/Schema/V111/Version111.php

@@ -144,8 +144,162 @@ class Version111 extends AbstractMigrationChamilo
             $this->addSql('UPDATE plugin_ticket_ticket t INNER JOIN plugin_ticket_message as m  ON(t.ticket_id = m.ticket_id and message_id =1)  SET t.subject = m.subject');
             $this->addSql('UPDATE plugin_ticket_ticket t INNER JOIN plugin_ticket_message as m  ON(t.ticket_id = m.ticket_id and message_id =1)  SET t.message = m.message');
             $this->addSql('DELETE FROM plugin_ticket_message WHERE message_id = 1');
+
+            $this->addSql('RENAME TABLE plugin_ticket_assigned_log TO ticket_assigned_log');
+            $this->addSql('RENAME TABLE plugin_ticket_category TO ticket_category');
+            $this->addSql('RENAME TABLE plugin_ticket_category_rel_user TO ticket_category_rel_user');
+            $this->addSql('RENAME TABLE plugin_ticket_message TO ticket_message');
+            $this->addSql('RENAME TABLE plugin_ticket_message_attachments TO ticket_message_attachments');
+            $this->addSql('RENAME TABLE plugin_ticket_priority TO ticket_priority');
+            $this->addSql('RENAME TABLE plugin_ticket_project TO ticket_project');
+            $this->addSql('RENAME TABLE plugin_ticket_status TO ticket_status');
+            $this->addSql('RENAME TABLE plugin_ticket_ticket TO ticket_ticket');
+
+            $this->addSql('UPDATE ticket_project SET sys_insert_user_id = 1 WHERE sys_insert_user_id IS NULL');
+            $this->addSql('UPDATE ticket_project SET sys_insert_datetime = NOW() WHERE sys_insert_datetime IS NULL');
+            $this->addSql('ALTER TABLE ticket_project DROP project_id, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE description description LONGTEXT DEFAULT NULL, CHANGE email email VARCHAR(255) DEFAULT NULL, CHANGE other_area other_area INT DEFAULT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL;');
+
+            $this->addSql('ALTER TABLE ticket_status ADD code VARCHAR(255) NOT NULL, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE description description LONGTEXT DEFAULT NULL;');
+            $this->addSql('UPDATE ticket_status SET code = status_id ');
+            $this->addSql('ALTER TABLE ticket_status DROP status_id');
+            $this->addSql('ALTER TABLE ticket_category_rel_user CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE category_id category_id INT DEFAULT NULL, CHANGE user_id user_id INT DEFAULT NULL;');
+
+
+            $this->addSql('UPDATE ticket_category SET sys_insert_user_id = 1 WHERE sys_insert_user_id IS NULL');
+            $this->addSql('UPDATE ticket_category SET sys_insert_datetime = NOW() WHERE sys_insert_datetime IS NULL');
+            $this->addSql('UPDATE ticket_category SET course_required = 0 WHERE course_required IS NULL OR course_required = ""');
+
+            $this->addSql('UPDATE ticket_category SET project_id = 1 WHERE project_id IS NULL OR project_id = ""');
+
+            $this->addSql('ALTER TABLE ticket_category DROP category_id, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE project_id project_id INT DEFAULT NULL, CHANGE name name VARCHAR(255) NOT NULL, CHANGE description description LONGTEXT DEFAULT NULL, CHANGE total_tickets total_tickets INT NOT NULL, CHANGE course_required course_required TINYINT(1) NOT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL;');
+            $this->addSql('ALTER TABLE ticket_category ADD CONSTRAINT FK_8325E540166D1F9C FOREIGN KEY (project_id) REFERENCES ticket_project (id);');
+            $this->addSql('CREATE INDEX IDX_8325E540166D1F9C ON ticket_category (project_id);');
+
+            $this->addSql('ALTER TABLE ticket_category_rel_user ADD CONSTRAINT FK_5B8A98712469DE2 FOREIGN KEY (category_id) REFERENCES ticket_category (id);');
+            $this->addSql('ALTER TABLE ticket_category_rel_user ADD CONSTRAINT FK_5B8A987A76ED395 FOREIGN KEY (user_id) REFERENCES user (id);');
+
+            $this->addSql('CREATE INDEX IDX_5B8A98712469DE2 ON ticket_category_rel_user (category_id);');
+            $this->addSql('CREATE INDEX IDX_5B8A987A76ED395 ON ticket_category_rel_user (user_id);');
+
+            $this->addSql('ALTER TABLE ticket_message_attachments DROP message_attch_id, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE message_id message_id INT DEFAULT NULL, CHANGE ticket_id ticket_id INT DEFAULT NULL, CHANGE filename filename LONGTEXT NOT NULL, CHANGE size size INT NOT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL;');
+
+            // missing
+            $this->addSql('ALTER TABLE ticket_message_attachments ADD CONSTRAINT FK_70BF9E26700047D2 FOREIGN KEY (ticket_id) REFERENCES ticket_ticket (id);');
+            $this->addSql('CREATE INDEX IDX_70BF9E26700047D2 ON ticket_message_attachments (ticket_id);');
+            $this->addSql('ALTER TABLE ticket_message_attachments RENAME INDEX ticket_message_id_fk TO IDX_70BF9E26537A1329;');
+
+
+            $this->addSql('UPDATE ticket_priority SET sys_insert_user_id = 1 WHERE sys_insert_user_id IS NULL');
+            $this->addSql('UPDATE ticket_priority SET sys_insert_datetime = NOW() WHERE sys_insert_datetime IS NULL');
+
+            $this->addSql('ALTER TABLE ticket_priority ADD code VARCHAR(255) NOT NULL, ADD name VARCHAR(255) NOT NULL, ADD description LONGTEXT DEFAULT NULL, ADD color VARCHAR(255) NOT NULL, ADD urgency VARCHAR(255) NOT NULL, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL;');
+
+            $this->addSql('UPDATE ticket_priority SET code = priority_id');
+            $this->addSql('UPDATE ticket_priority SET name = priority');
+            $this->addSql('UPDATE ticket_priority SET description = priority_desc');
+            $this->addSql('UPDATE ticket_priority SET color = priority_color');
+            $this->addSql('UPDATE ticket_priority SET urgency = priority_urgency');
+
+            $this->addSql('ALTER TABLE ticket_priority DROP priority_id, DROP priority, DROP priority_desc, DROP priority_color, DROP priority_urgency');
+
+
+            $this->addSql('ALTER TABLE ticket_ticket MODIFY ticket_id INT UNSIGNED NOT NULL;');
+            $this->addSql('DROP INDEX UN_ticket_code ON ticket_ticket;');
+            $this->addSql('DROP INDEX FK_ticket_category ON ticket_ticket;');
+            $this->addSql('ALTER TABLE ticket_ticket DROP PRIMARY KEY;');
+
+            $this->addSql('UPDATE ticket_ticket t SET priority_id = (SELECT id FROM ticket_priority t2 WHERE t2.code = t.priority_id)');
+            $this->addSql('UPDATE ticket_ticket t SET status_id = (SELECT id FROM ticket_status t2 WHERE t2.code = t.status_id)');
+
+            $this->addSql('ALTER TABLE ticket_ticket ADD id INT NOT NULL, ADD code VARCHAR(255) NOT NULL, CHANGE project_id project_id INT DEFAULT NULL, CHANGE priority_id priority_id INT DEFAULT NULL, CHANGE course_id course_id INT DEFAULT NULL, CHANGE session_id session_id INT DEFAULT NULL, CHANGE personal_email personal_email VARCHAR(255) NOT NULL, CHANGE assigned_last_user assigned_last_user INT DEFAULT NULL, CHANGE status_id status_id INT DEFAULT NULL, CHANGE total_messages total_messages INT NOT NULL, CHANGE keyword keyword VARCHAR(255) DEFAULT NULL, CHANGE source source VARCHAR(255) DEFAULT NULL, CHANGE start_date start_date DATETIME DEFAULT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL, CHANGE subject subject VARCHAR(255) NOT NULL, CHANGE message message LONGTEXT DEFAULT NULL;');
+
+            $this->addSql('UPDATE ticket_ticket SET code = ticket_code');
+            $this->addSql('UPDATE ticket_ticket SET id = ticket_id');
+            $this->addSql('ALTER TABLE ticket_ticket DROP ticket_id, DROP ticket_code, DROP request_user');
+            $this->addSql('ALTER TABLE ticket_ticket MODIFY COLUMN id INT NOT NULL PRIMARY KEY AUTO_INCREMENT');
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C768497B19F9 FOREIGN KEY (priority_id) REFERENCES ticket_priority (id);');
+
+            $this->addSql('UPDATE ticket_ticket SET project_id = 1 WHERE project_id is NULL or project_id = 0');
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C768166D1F9C FOREIGN KEY (project_id) REFERENCES ticket_project (id);');
+
+            $this->addSql('UPDATE ticket_ticket SET course_id = NULL WHERE course_id = 0');
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C768591CC992 FOREIGN KEY (course_id) REFERENCES course (id);');
+
+            $this->addSql('UPDATE ticket_ticket SET session_id = NULL WHERE session_id = 0');
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C768613FECDF FOREIGN KEY (session_id) REFERENCES session (id);');
+
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C7686BF700BD FOREIGN KEY (status_id) REFERENCES ticket_status (id);');
+            $this->addSql('CREATE INDEX IDX_EDE2C768166D1F9C ON ticket_ticket (project_id);');
+            $this->addSql('CREATE INDEX IDX_EDE2C768591CC992 ON ticket_ticket (course_id);');
+            $this->addSql('CREATE INDEX IDX_EDE2C768613FECDF ON ticket_ticket (session_id);');
+            $this->addSql('CREATE INDEX IDX_EDE2C7686BF700BD ON ticket_ticket (status_id);');
+
+            $this->addSql('ALTER TABLE ticket_ticket RENAME INDEX fk_ticket_priority TO IDX_EDE2C768497B19F9;');
+            $this->addSql('ALTER TABLE ticket_assigned_log CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE ticket_id ticket_id INT DEFAULT NULL, CHANGE user_id user_id INT DEFAULT NULL, CHANGE assigned_date assigned_date DATETIME NOT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL;');
+            $this->addSql('ALTER TABLE ticket_assigned_log ADD CONSTRAINT FK_54B65868700047D2 FOREIGN KEY (ticket_id) REFERENCES ticket_ticket (id);');
+
+            $this->addSql('DELETE FROM ticket_assigned_log WHERE user_id = 0 OR user_id IS NULL');
+
+            $this->addSql('ALTER TABLE ticket_assigned_log ADD CONSTRAINT FK_54B65868A76ED395 FOREIGN KEY (user_id) REFERENCES user (id);');
+            $this->addSql('CREATE INDEX IDX_54B65868A76ED395 ON ticket_assigned_log (user_id);');
+            $this->addSql('ALTER TABLE ticket_assigned_log RENAME INDEX fk_ticket_assigned_log TO IDX_54B65868700047D2;');
+
+            $this->addSql('ALTER TABLE ticket_category_rel_user RENAME INDEX fk_5b8a98712469de2 TO IDX_5B8A98712469DE2;');
+            $this->addSql('ALTER TABLE ticket_category_rel_user RENAME INDEX fk_5b8a987a76ed395 TO IDX_5B8A987A76ED395;');
+
+            $this->addSql('ALTER TABLE ticket_message DROP message_id, CHANGE id id INT AUTO_INCREMENT NOT NULL, CHANGE ticket_id ticket_id INT DEFAULT NULL, CHANGE subject subject VARCHAR(255) DEFAULT NULL, CHANGE message message LONGTEXT DEFAULT NULL, CHANGE status status VARCHAR(255) NOT NULL, CHANGE ip_address ip_address VARCHAR(255) NOT NULL, CHANGE sys_insert_user_id sys_insert_user_id INT NOT NULL, CHANGE sys_insert_datetime sys_insert_datetime DATETIME NOT NULL, CHANGE sys_lastedit_user_id sys_lastedit_user_id INT DEFAULT NULL;');
+
+            $this->addSql('ALTER TABLE ticket_message ADD CONSTRAINT FK_BA71692D700047D2 FOREIGN KEY (ticket_id) REFERENCES ticket_ticket (id);');
+            $this->addSql('ALTER TABLE ticket_message RENAME INDEX fk_tick_message TO IDX_BA71692D700047D2;');
+            $this->addSql('ALTER TABLE ticket_ticket CHANGE category_id category_id INT DEFAULT NULL;');
+            $this->addSql('ALTER TABLE ticket_ticket ADD CONSTRAINT FK_EDE2C76812469DE2 FOREIGN KEY (category_id) REFERENCES ticket_category (id);');
+            $this->addSql('CREATE INDEX IDX_EDE2C76812469DE2 ON ticket_ticket (category_id);');
+
+            $this->addSql('ALTER TABLE ticket_message_attachments ADD CONSTRAINT FK_70BF9E26537A1329 FOREIGN KEY (message_id) REFERENCES ticket_message (id);');
+            $this->addSql('DELETE FROM settings_current WHERE title = "Ticket"');
         }
-}    /**
+
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('ticket_allow_student_add', NULL, 'radio','Ticket', 'false','TicketAllowStudentAddTitle','TicketAllowStudentAddComment',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('ticket_allow_category_edition', NULL, 'radio','Ticket', 'false','TicketAllowCategoryEditionTitle','TicketAllowCategoryEditionComment',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('ticket_send_warning_to_all_admins', NULL, 'radio','Ticket', 'false','TicketSendWarningToAllAdminsTitle','TicketSendWarningToAllAdminsComment',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('ticket_warn_admin_no_user_in_category', NULL, 'radio','Ticket', 'false','TicketWarnAdminNoUserInCategoryTitle','TicketWarnAdminNoUserInCategoryComment',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('load_term_conditions_section', NULL, 'radio','Platform', 'login','LoadTermConditionsSectionTitle','LoadTermConditionsSectionDescription',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('show_terms_if_profile_completed', NULL, 'radio','Ticket', 'false','ShowTermsIfProfileCompletedTitle','ShowTermsIfProfileCompletedComment',NULL,NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('show_link_ticket_notification', NULL, 'radio', 'Platform', 'false', 'ShowLinkTicketNotificationTitle', 'ShowLinkTicketNotificationComment', NULL, NULL, 0)");
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, access_url) VALUES ('sso_authentication_subclass', NULL, 'textfield', 'Security', '', 'SSOSubclassTitle', 'SSOSubclassComment', 1)");
+
+
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('ticket_allow_student_add', 'true', 'Yes'), ('ticket_allow_student_add', 'false', 'No')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('ticket_allow_category_edition', 'true', 'Yes'), ('ticket_allow_category_edition', 'false', 'No')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('ticket_send_warning_to_all_admins', 'true', 'Yes'), ('ticket_send_warning_to_all_admins', 'false', 'No')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('ticket_warn_admin_no_user_in_category', 'true', 'Yes'), ('ticket_warn_admin_no_user_in_category', 'false', 'No')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('load_term_conditions_section', 'login', 'Login'), ('load_term_conditions_section', 'course', 'Course')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_terms_if_profile_completed', 'true', 'Yes'), ('show_terms_if_profile_completed', 'false', 'No')");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('show_link_ticket_notification', 'true', 'Yes'), ('show_link_ticket_notification', 'false', 'No')");
+
+        $this->addSql("ALTER TABLE c_quiz_question_rel_category ADD INDEX idx_qqrc_qid (question_id)");
+        $this->addSql("ALTER TABLE c_quiz_answer ADD INDEX idx_cqa_q (question_id)");
+        $this->addSql("ALTER TABLE c_student_publication ADD INDEX idx_csp_u (user_id)");
+
+        $this->addSql('ALTER TABLE legal DROP PRIMARY KEY;');
+        $this->addSql('ALTER TABLE legal ADD id INT');
+        $this->addSql('UPDATE legal SET id = legal_id');
+        $this->addSql('UPDATE legal SET id = 1 WHERE id = 0');
+        $this->addSql('ALTER TABLE legal MODIFY COLUMN language_id INT NOT NULL');
+        $this->addSql('ALTER TABLE legal DROP legal_id');
+        $this->addSql('ALTER TABLE legal CHANGE id id INT AUTO_INCREMENT NOT NULL PRIMARY KEY;');
+
+        $this->addSql('ALTER TABLE user ADD profile_completed TINYINT(1) DEFAULT NULL;');
+        $this->addSql('ALTER TABLE extra_field_options CHANGE display_text display_text VARCHAR(255) DEFAULT NULL');
+        $this->addSql('ALTER TABLE extra_field CHANGE variable variable VARCHAR(255) NOT NULL');
+        $this->addSql('ALTER TABLE c_course_setting MODIFY COLUMN value TEXT');
+
+        if (!$schema->hasTable('version')) {
+            $this->addSql('CREATE TABLE version (version varchar(255), PRIMARY KEY(version));');
+        }
+    }
+
+    /**
      * @param Schema $schema
      */
     public function postUp(Schema $schema)

+ 46 - 0
app/Migrations/Schema/V111/Version20160603113100.php

@@ -0,0 +1,46 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V111;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * Class Version20160603113100
+ * Add association mapping for Language class
+ * @package Application\Migrations\Schema\V111
+ */
+class Version20160603113100 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function up(Schema $schema)
+    {
+        $languageTable = $schema->getTable('language');
+        $languageTable
+            ->getColumn('parent_id')
+            ->setType(Type::getType(Type::INTEGER))
+            ->setNotnull(false);
+        $languageTable->addForeignKeyConstraint('language', ['parent_id'], ['id'], [], 'language_parent');
+    }
+
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function down(Schema $schema)
+    {
+        $languageTable = $schema->getTable('language');
+        $languageTable->removeForeignKey('language_parent');
+        $languageTable
+            ->getColumn('parent_id')
+            ->setType(Type::getType(Type::BOOLEAN))
+            ->setNotnull(false);
+    }
+}

+ 92 - 0
app/Migrations/Schema/V111/Version20160610142700.php

@@ -0,0 +1,92 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V111;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * Class Version20160610142700
+ * Integrate the Skype plugin and create new settings current to enable it
+ * @package Application\Migrations\Schema\V111
+ */
+class Version20160610142700 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function up(Schema $schema)
+    {
+        $dataList = $this
+            ->connection
+            ->executeQuery("
+                SELECT id FROM extra_field
+                WHERE variable = 'skype' AND extra_field_type = 1 
+            ")
+            ->fetchAll();
+
+        if (empty($dataList)) {
+            $this->addSql("
+                INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, visible, changeable, created_at)
+                VALUES (1, 1, 'skype', 'Skype', 1, 1, now())
+            ");
+        }
+
+        $this->addSql("
+            INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, visible, changeable, created_at)
+            VALUES (1, 1, 'linkedin_url', 'LinkedInUrl', 1, 1, now())
+        ");
+
+        $this->addSettingCurrent(
+            'allow_show_skype_account',
+            null,
+            'radio',
+            'Platform',
+            'true',
+            'AllowShowSkypeAccountTitle',
+            'AllowShowSkypeAccountComment',
+            null,
+            null,
+            1,
+            true,
+            false,
+            [
+                ['value' => 'false', 'text' => 'No'],
+                ['value' => 'true', 'text' => 'Yes']
+            ]
+        );
+
+        $this->addSettingCurrent(
+            'allow_show_linkedin_url',
+            null,
+            'radio',
+            'Platform',
+            'true',
+            'AllowShowLinkedInUrlTitle',
+            'AllowShowLinkedInUrlComment',
+            null,
+            null,
+            1,
+            true,
+            false,
+            [
+                ['value' => 'false', 'text' => 'No'],
+                ['value' => 'true', 'text' => 'Yes']
+            ]
+        );
+    }
+
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function down(Schema $schema)
+    {
+
+    }
+}

+ 36 - 0
app/Migrations/Schema/V111/Version20160623143200.php

@@ -0,0 +1,36 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V111;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * Class Version20160623143200
+ * Remove chatcall_date, chatcall_text, chatcall_user_id from User table
+ * @package Application\Migrations\Schema\V111
+ */
+class Version20160623143200 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function up(Schema $schema)
+    {
+        $schema
+            ->getTable('user')
+            ->dropColumn('chatcall_user_id')
+            ->dropColumn('chatcall_date')
+            ->dropColumn('chatcall_text');
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function down(Schema $schema)
+    {
+    }
+}

+ 47 - 0
app/Migrations/Schema/V111/Version20160628220000.php

@@ -0,0 +1,47 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V111;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * Class Version20160628220000
+ * Integrate the Skype plugin and create new settings current to enable it
+ * @package Application\Migrations\Schema\V111
+ */
+class Version20160628220000 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function up(Schema $schema)
+    {
+        $this
+            ->connection
+            ->executeQuery("UPDATE c_lp_item SET item_type = 'dir' WHERE item_type = 'dokeos_chapter'");
+        $this
+            ->connection
+            ->executeQuery("UPDATE c_lp_item SET item_type = 'dir' WHERE item_type = 'dokeos_module'");
+        $this
+            ->connection
+            ->executeQuery("UPDATE c_lp_item SET item_type = 'dir' WHERE item_type = 'chapter'");
+        $this
+            ->connection
+            ->executeQuery("UPDATE c_lp_item SET item_type = 'dir' WHERE item_type = 'module'");
+    }
+
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function down(Schema $schema)
+    {
+
+    }
+}

+ 39 - 0
app/Migrations/Schema/V111/Version20160701110000.php

@@ -0,0 +1,39 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Application\Migrations\Schema\V111;
+
+use Application\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * Class Version20160701110000
+ * Add option to remove splash screen on course creation
+ * @package Application\Migrations\Schema\V111
+ */
+class Version20160701110000 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function up(Schema $schema)
+    {
+        $this->addSql("INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('course_creation_splash_screen',NULL,'radio','Course','true','CourseCreationSplashScreenTitle','CourseCreationSplashScreenComment','',NULL, 1)");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('course_creation_splash_screen','true','Yes') ");
+        $this->addSql("INSERT INTO settings_options (variable, value, display_text) VALUES ('course_creation_splash_screen','false','No') ");
+    }
+
+    /**
+     * @param Schema $schema
+     * @throws \Doctrine\DBAL\DBALException
+     * @throws \Doctrine\DBAL\Schema\SchemaException
+     */
+    public function down(Schema $schema)
+    {
+        $this->addSql("DELETE FROM settings_current WHERE variable = 'course_creation_splash_screen'");
+        $this->addSql("DELETE FROM settings_options WHERE variable = 'course_creation_splash_screen'");
+    }
+}

+ 5 - 5
app/Resources/public/assets/blueimp-tmpl/.bower.json

@@ -1,14 +1,14 @@
 {
   "name": "blueimp-tmpl",
   "homepage": "https://github.com/blueimp/JavaScript-Templates",
-  "version": "3.3.0",
-  "_release": "3.3.0",
+  "version": "3.4.0",
+  "_release": "3.4.0",
   "_resolution": {
     "type": "version",
-    "tag": "v3.3.0",
-    "commit": "f09f47c368e0dc7871be35119ef3eab9bb25bdf2"
+    "tag": "v3.4.0",
+    "commit": "dcb7a7b44c733c5df0b6000e777bc6942646607e"
   },
-  "_source": "git://github.com/blueimp/JavaScript-Templates.git",
+  "_source": "https://github.com/blueimp/JavaScript-Templates.git",
   "_target": ">=2.5.4",
   "_originalSource": "blueimp-tmpl"
 }

+ 7 - 9
app/Resources/public/assets/blueimp-tmpl/README.md

@@ -352,20 +352,18 @@ Use **include(str, obj)** to include content from a different template:
 ## Compiled templates
 The JavaScript Templates project comes with a compilation script, that allows
 you to compile your templates into JavaScript code and combine them with a
-minimal Templates runtime into one minified JavaScript file.
+minimal Templates runtime into one combined JavaScript file.
 
-The compilation script is built for [node.js](http://nodejs.org/) and also
-requires [UglifyJS](https://github.com/mishoo/UglifyJS).  
-To use it, first install both the JavaScript Templates project and UglifyJS via
+The compilation script is built for [node.js](http://nodejs.org/).  
+To use it, first install the JavaScript Templates project via
 [npm](https://www.npmjs.org/):
 
 ```sh
-npm install uglify-js blueimp-tmpl
+npm install blueimp-tmpl
 ```
 
-This will put the executables **uglifyjs** and **tmpl.js** into the folder
-**node_modules/.bin**. It will also make them available on your PATH if you
-install the packages globally
+This will put the executable **tmpl.js** into the folder **node_modules/.bin**.
+It will also make it available on your PATH if you install the package globally
 (by adding the **-g** flag to the install command).
 
 The **tmpl.js** executable accepts the paths to one or multiple template files
@@ -374,7 +372,7 @@ console output. The following command line shows you how to store the generated
 code in a new JavaScript file that can be included in your project:
 
 ```sh
-tmpl.js templates/upload.html templates/download.html > tmpl.min.js
+tmpl.js index.html > tmpl.js
 ```
 
 The files given as command line arguments to **tmpl.js** can either be pure

+ 2 - 3
app/Resources/public/assets/blueimp-tmpl/js/compile.js

@@ -17,7 +17,6 @@
   var path = require('path')
   var tmpl = require(path.join(__dirname, 'tmpl.js'))
   var fs = require('fs')
-  var uglifyJS = require('uglify-js')
   // Retrieve the content of the minimal runtime:
   var runtime = fs.readFileSync(path.join(__dirname, 'runtime.js'), 'utf8')
   // A regular expression to parse templates from script tags in a HTML page:
@@ -78,6 +77,6 @@
   }
   // Combine the generated functions as cache of the minimal runtime:
   code = runtime.replace('{}', '{' + list.join(',') + '}')
-  // Generate the minified code and print it to the console output:
-  console.log(uglifyJS.minify(code, {fromString: true}).code)
+  // Print the resulting code to the console output:
+  console.log(code)
 }())

+ 1 - 1
app/Resources/public/assets/blueimp-tmpl/package.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-tmpl",
-  "version": "3.3.0",
+  "version": "3.4.0",
   "title": "JavaScript Templates",
   "description": "1KB lightweight, fast & powerful JavaScript templating engine with zero dependencies. Compatible with server-side environments like Node.js, module loaders like RequireJS, Browserify or webpack and all web browsers.",
   "keywords": [

+ 20 - 20
app/Resources/public/assets/ckeditor/plugins/scayt/CHANGELOG.md

@@ -1,20 +1,20 @@
-SCAYT plugin for CKEditor 4 Changelog
-====================
-### CKEditor 4.5.6
-
-New Features:
-* CKEditor [language addon](http://ckeditor.com/addon/language) support
-* CKEditor [placeholder addon](http://ckeditor.com/addon/placeholder) support
-* Drag and Drop support
-* *Experimental* GRAYT functionality http://www.webspellchecker.net/samples/scayt-ckeditor-plugin.html#25
-
-Fixed issues:
-* [#98](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/98) SCAYT Affects Dialog Double Click. Fixed in SCAYT Core.
-* [#102](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/102) SCAYT Core performance enhancements
-* [#104](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/104) SCAYT's spans leak into the clipboard and after pasting
-* [#105](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/105) Javascript error fired in case of multiple instances of CKEditor in one page
-* [#107](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/107) SCAYT should not check non-editable parts of content
-* [#108](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/108) Latest SCAYT copies id of editor element to the iframe
-* SCAYT stops working when CKEditor Undo plug-in not enabled
-* Issue with pasting SCAYT markup in CKEditor
-* [#32](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/32) SCAYT stops working after pressing Cancel button in WSC dialog
+SCAYT plugin for CKEditor 4 Changelog
+====================
+### CKEditor 4.5.6
+
+New Features:
+* CKEditor [language addon](http://ckeditor.com/addon/language) support
+* CKEditor [placeholder addon](http://ckeditor.com/addon/placeholder) support
+* Drag and Drop support
+* *Experimental* GRAYT functionality http://www.webspellchecker.net/samples/scayt-ckeditor-plugin.html#25
+
+Fixed issues:
+* [#98](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/98) SCAYT Affects Dialog Double Click. Fixed in SCAYT Core.
+* [#102](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/102) SCAYT Core performance enhancements
+* [#104](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/104) SCAYT's spans leak into the clipboard and after pasting
+* [#105](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/105) Javascript error fired in case of multiple instances of CKEditor in one page
+* [#107](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/107) SCAYT should not check non-editable parts of content
+* [#108](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/108) Latest SCAYT copies id of editor element to the iframe
+* SCAYT stops working when CKEditor Undo plug-in not enabled
+* Issue with pasting SCAYT markup in CKEditor
+* [#32](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/32) SCAYT stops working after pressing Cancel button in WSC dialog

+ 28 - 28
app/Resources/public/assets/ckeditor/plugins/scayt/LICENSE.md

@@ -1,28 +1,28 @@
-Software License Agreement
-==========================
-
-**CKEditor SCAYT Plugin**
-Copyright &copy; 2012, [CKSource](http://cksource.com) - Frederico Knabben. All rights reserved.
-
-Licensed under the terms of any of the following licenses at your choice:
-
-*   GNU General Public License Version 2 or later (the "GPL"):
-    http://www.gnu.org/licenses/gpl.html
-
-*   GNU Lesser General Public License Version 2.1 or later (the "LGPL"):
-    http://www.gnu.org/licenses/lgpl.html
-
-*   Mozilla Public License Version 1.1 or later (the "MPL"):
-    http://www.mozilla.org/MPL/MPL-1.1.html
-
-You are not required to, but if you want to explicitly declare the license you have chosen to be bound to when using, reproducing, modifying and distributing this software, just include a text file titled "legal.txt" in your version of this software, indicating your license choice.
-
-Sources of Intellectual Property Included in this plugin
---------------------------------------------------------
-
-Where not otherwise indicated, all plugin content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, the plugin will incorporate work done by developers outside of CKSource with their express permission.
-
-Trademarks
-----------
-
-CKEditor is a trademark of CKSource - Frederico Knabben. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
+Software License Agreement
+==========================
+
+**CKEditor SCAYT Plugin**
+Copyright &copy; 2012, [CKSource](http://cksource.com) - Frederico Knabben. All rights reserved.
+
+Licensed under the terms of any of the following licenses at your choice:
+
+*   GNU General Public License Version 2 or later (the "GPL"):
+    http://www.gnu.org/licenses/gpl.html
+
+*   GNU Lesser General Public License Version 2.1 or later (the "LGPL"):
+    http://www.gnu.org/licenses/lgpl.html
+
+*   Mozilla Public License Version 1.1 or later (the "MPL"):
+    http://www.mozilla.org/MPL/MPL-1.1.html
+
+You are not required to, but if you want to explicitly declare the license you have chosen to be bound to when using, reproducing, modifying and distributing this software, just include a text file titled "legal.txt" in your version of this software, indicating your license choice.
+
+Sources of Intellectual Property Included in this plugin
+--------------------------------------------------------
+
+Where not otherwise indicated, all plugin content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, the plugin will incorporate work done by developers outside of CKSource with their express permission.
+
+Trademarks
+----------
+
+CKEditor is a trademark of CKSource - Frederico Knabben. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.

+ 25 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/README.md

@@ -0,0 +1,25 @@
+CKEditor SCAYT Plugin
+=====================
+
+This plugin brings Spell Check As You Type (SCAYT) into up to CKEditor 4+.
+
+SCAYT is a "installation-less", using the web-services of [WebSpellChecker.net](http://www.webspellchecker.net/). It's an out of the box solution.
+
+Installation
+------------
+
+1. Clone/copy this repository contents in a new "plugins/scayt" folder in your CKEditor installation.
+2. Enable the "scayt" plugin in the CKEditor configuration file (config.js):
+
+        config.extraPlugins = 'scayt';
+
+That's all. SCAYT will appear on the editor toolbar and will be ready to use.
+
+License
+-------
+
+Licensed under the terms of any of the following licenses at your choice: [GPL](http://www.gnu.org/licenses/gpl.html), [LGPL](http://www.gnu.org/licenses/lgpl.html) and [MPL](http://www.mozilla.org/MPL/MPL-1.1.html).
+
+See LICENSE.md for more information.
+
+Developed in cooperation with [WebSpellChecker.net](http://www.webspellchecker.net/).

+ 573 - 19
app/Resources/public/assets/ckeditor/plugins/scayt/dialogs/options.js

@@ -1,19 +1,573 @@
-CKEDITOR.dialog.add("scaytDialog",function(c){var f=c.scayt,q='\x3cp\x3e\x3cimg src\x3d"'+f.getLogo()+'" /\x3e\x3c/p\x3e\x3cp\x3e'+f.getLocal("version")+f.getVersion()+"\x3c/p\x3e\x3cp\x3e"+f.getLocal("text_copyrights")+"\x3c/p\x3e",r=CKEDITOR.document,n={isChanged:function(){return null===this.newLang||this.currentLang===this.newLang?!1:!0},currentLang:f.getLang(),newLang:null,reset:function(){this.currentLang=f.getLang();this.newLang=null},id:"lang"},q=[{id:"options",label:f.getLocal("tab_options"),
-onShow:function(){},elements:[{type:"vbox",id:"scaytOptions",children:function(){var a=f.getApplicationConfig(),b=[],g={"ignore-all-caps-words":"label_allCaps","ignore-domain-names":"label_ignoreDomainNames","ignore-words-with-mixed-cases":"label_mixedCase","ignore-words-with-numbers":"label_mixedWithDigits"},e;for(e in a)a={type:"checkbox"},a.id=e,a.label=f.getLocal(g[e]),b.push(a);return b}(),onShow:function(){this.getChild();for(var a=c.scayt,b=0;b<this.getChild().length;b++)this.getChild()[b].setValue(a.getApplicationConfig()[this.getChild()[b].id])}}]},
-{id:"langs",label:f.getLocal("tab_languages"),elements:[{id:"leftLangColumn",type:"vbox",align:"left",widths:["100"],children:[{type:"html",id:"langBox",style:"overflow: hidden; white-space: normal;margin-bottom:15px;",html:'\x3cdiv\x3e\x3cdiv style\x3d"float:left;width:45%;margin-left:5px;" id\x3d"left-col-'+c.name+'"\x3e\x3c/div\x3e\x3cdiv style\x3d"float:left;width:45%;margin-left:15px;" id\x3d"right-col-'+c.name+'"\x3e\x3c/div\x3e\x3c/div\x3e',onShow:function(){var a=c.scayt.getLang();r.getById("scaytLang_"+
-c.name+"_"+a).$.checked=!0}},{type:"html",id:"graytLanguagesHint",html:'\x3cdiv style\x3d"margin:5px auto; width:95%;white-space:normal;" id\x3d"'+c.name+'graytLanguagesHint"\x3e\x3cspan style\x3d"width:10px;height:10px;display: inline-block; background:#02b620;vertical-align:top;margin-top:2px;"\x3e\x3c/span\x3e - This languages are supported by Grammar As You Type(GRAYT).\x3c/div\x3e',onShow:function(){var a=r.getById(c.name+"graytLanguagesHint");c.config.grayt_autoStartup||(a.$.style.display="none")}}]}]},
-{id:"dictionaries",label:f.getLocal("tab_dictionaries"),elements:[{type:"vbox",id:"rightCol_col__left",children:[{type:"html",id:"dictionaryNote",html:""},{type:"text",id:"dictionaryName",label:f.getLocal("label_fieldNameDic")||"Dictionary name",onShow:function(a){var b=a.sender,g=c.scayt;setTimeout(function(){b.getContentElement("dictionaries","dictionaryNote").getElement().setText("");null!=g.getUserDictionaryName()&&""!=g.getUserDictionaryName()&&b.getContentElement("dictionaries","dictionaryName").setValue(g.getUserDictionaryName())},
-0)}},{type:"hbox",id:"notExistDic",align:"left",style:"width:auto;",widths:["50%","50%"],children:[{type:"button",id:"createDic",label:f.getLocal("btn_createDic"),title:f.getLocal("btn_createDic"),onClick:function(){var a=this.getDialog(),b=p,g=c.scayt,e=a.getContentElement("dictionaries","dictionaryName").getValue();g.createUserDictionary(e,function(d){d.error||b.toggleDictionaryButtons.call(a,!0);d.dialog=a;d.command="create";d.name=e;c.fire("scaytUserDictionaryAction",d)},function(d){d.dialog=
-a;d.command="create";d.name=e;c.fire("scaytUserDictionaryActionError",d)})}},{type:"button",id:"restoreDic",label:f.getLocal("btn_restoreDic"),title:f.getLocal("btn_restoreDic"),onClick:function(){var a=this.getDialog(),b=c.scayt,g=p,e=a.getContentElement("dictionaries","dictionaryName").getValue();b.restoreUserDictionary(e,function(d){d.dialog=a;d.error||g.toggleDictionaryButtons.call(a,!0);d.command="restore";d.name=e;c.fire("scaytUserDictionaryAction",d)},function(d){d.dialog=a;d.command="restore";
-d.name=e;c.fire("scaytUserDictionaryActionError",d)})}}]},{type:"hbox",id:"existDic",align:"left",style:"width:auto;",widths:["50%","50%"],children:[{type:"button",id:"removeDic",label:f.getLocal("btn_deleteDic"),title:f.getLocal("btn_deleteDic"),onClick:function(){var a=this.getDialog(),b=c.scayt,g=p,e=a.getContentElement("dictionaries","dictionaryName"),d=e.getValue();b.removeUserDictionary(d,function(b){e.setValue("");b.error||g.toggleDictionaryButtons.call(a,!1);b.dialog=a;b.command="remove";
-b.name=d;c.fire("scaytUserDictionaryAction",b)},function(b){b.dialog=a;b.command="remove";b.name=d;c.fire("scaytUserDictionaryActionError",b)})}},{type:"button",id:"renameDic",label:f.getLocal("btn_renameDic"),title:f.getLocal("btn_renameDic"),onClick:function(){var a=this.getDialog(),b=c.scayt,g=a.getContentElement("dictionaries","dictionaryName").getValue();b.renameUserDictionary(g,function(b){b.dialog=a;b.command="rename";b.name=g;c.fire("scaytUserDictionaryAction",b)},function(b){b.dialog=a;b.command=
-"rename";b.name=g;c.fire("scaytUserDictionaryActionError",b)})}}]},{type:"html",id:"dicInfo",html:'\x3cdiv id\x3d"dic_info_editor1" style\x3d"margin:5px auto; width:95%;white-space:normal;"\x3e'+f.getLocal("text_descriptionDic")+"\x3c/div\x3e"}]}]},{id:"about",label:f.getLocal("tab_about"),elements:[{type:"html",id:"about",style:"margin: 5px 5px;",html:'\x3cdiv\x3e\x3cdiv id\x3d"scayt_about_"\x3e'+q+"\x3c/div\x3e\x3c/div\x3e"}]}];c.on("scaytUserDictionaryAction",function(a){var b=SCAYT.prototype.UILib,
-g=a.data.dialog,e=g.getContentElement("dictionaries","dictionaryNote").getElement(),d=a.editor.scayt,c;void 0===a.data.error?(c=d.getLocal("message_success_"+a.data.command+"Dic"),c=c.replace("%s",a.data.name),e.setText(c),b.css(e.$,{color:"blue"})):(""===a.data.name?e.setText(d.getLocal("message_info_emptyDic")):(c=d.getLocal("message_error_"+a.data.command+"Dic"),c=c.replace("%s",a.data.name),e.setText(c)),b.css(e.$,{color:"red"}),null!=d.getUserDictionaryName()&&""!=d.getUserDictionaryName()?g.getContentElement("dictionaries",
-"dictionaryName").setValue(d.getUserDictionaryName()):g.getContentElement("dictionaries","dictionaryName").setValue(""))});c.on("scaytUserDictionaryActionError",function(a){var b=SCAYT.prototype.UILib,c=a.data.dialog,e=c.getContentElement("dictionaries","dictionaryNote").getElement(),d=a.editor.scayt,f;""===a.data.name?e.setText(d.getLocal("message_info_emptyDic")):(f=d.getLocal("message_error_"+a.data.command+"Dic"),f=f.replace("%s",a.data.name),e.setText(f));b.css(e.$,{color:"red"});null!=d.getUserDictionaryName()&&
-""!=d.getUserDictionaryName()?c.getContentElement("dictionaries","dictionaryName").setValue(d.getUserDictionaryName()):c.getContentElement("dictionaries","dictionaryName").setValue("")});var p={title:f.getLocal("text_title"),resizable:CKEDITOR.DIALOG_RESIZE_BOTH,minWidth:340,minHeight:260,onLoad:function(){if(0!=c.config.scayt_uiTabs[1]){var a=p,b=a.getLangBoxes.call(this);b.getParent().setStyle("white-space","normal");a.renderLangList(b);this.definition.minWidth=this.getSize().width;this.resize(this.definition.minWidth,
-this.definition.minHeight)}},onCancel:function(){n.reset()},onHide:function(){c.unlockSelection()},onShow:function(){c.fire("scaytDialogShown",this);if(0!=c.config.scayt_uiTabs[2]){var a=c.scayt,b=this.getContentElement("dictionaries","dictionaryName"),g=this.getContentElement("dictionaries","existDic").getElement().getParent(),e=this.getContentElement("dictionaries","notExistDic").getElement().getParent();g.hide();e.hide();null!=a.getUserDictionaryName()&&""!=a.getUserDictionaryName()?(this.getContentElement("dictionaries",
-"dictionaryName").setValue(a.getUserDictionaryName()),g.show()):(b.setValue(""),e.show())}},onOk:function(){var a=p,b=c.scayt;this.getContentElement("options","scaytOptions");a=a.getChangedOption.call(this);b.commitOption({changedOptions:a})},toggleDictionaryButtons:function(a){var b=this.getContentElement("dictionaries","existDic").getElement().getParent(),c=this.getContentElement("dictionaries","notExistDic").getElement().getParent();a?(b.show(),c.hide()):(b.hide(),c.show())},getChangedOption:function(){var a=
-{};if(1==c.config.scayt_uiTabs[0])for(var b=this.getContentElement("options","scaytOptions").getChild(),g=0;g<b.length;g++)b[g].isChanged()&&(a[b[g].id]=b[g].getValue());n.isChanged()&&(a[n.id]=c.config.scayt_sLang=n.currentLang=n.newLang);return a},buildRadioInputs:function(a,b,g){var e=new CKEDITOR.dom.element("div"),d="scaytLang_"+c.name+"_"+b,f=CKEDITOR.dom.element.createFromHtml('\x3cinput id\x3d"'+d+'" type\x3d"radio"  value\x3d"'+b+'" name\x3d"scayt_lang" /\x3e'),m=new CKEDITOR.dom.element("label"),
-k=c.scayt;e.setStyles({"white-space":"normal",position:"relative","padding-bottom":"2px"});f.on("click",function(a){n.newLang=a.sender.getValue()});m.appendText(a);m.setAttribute("for",d);g&&c.config.grayt_autoStartup&&m.setStyles({color:"#02b620"});e.append(f);e.append(m);b===k.getLang()&&(f.setAttribute("checked",!0),f.setAttribute("defaultChecked","defaultChecked"));return e},renderLangList:function(a){var b=a.find("#left-col-"+c.name).getItem(0);a=a.find("#right-col-"+c.name).getItem(0);var g=
-f.getScaytLangList(),e=f.getGraytLangList(),d={},l=[],m=0,k=!1,h;for(h in g.ltr)d[h]=g.ltr[h];for(h in g.rtl)d[h]=g.rtl[h];for(h in d)l.push([h,d[h]]);l.sort(function(a,b){var c=0;a[1]>b[1]?c=1:a[1]<b[1]&&(c=-1);return c});d={};for(k=0;k<l.length;k++)d[l[k][0]]=l[k][1];l=Math.round(l.length/2);for(h in d)m++,k=h in e.ltr||h in e.rtl,this.buildRadioInputs(d[h],h,k).appendTo(m<=l?b:a)},getLangBoxes:function(){return this.getContentElement("langs","langBox").getElement()},contents:function(a,b){var c=
-[],e=b.config.scayt_uiTabs;if(e){for(var d in e)1==e[d]&&c.push(a[d]);c.push(a[a.length-1])}else return a;return c}(q,c)};return p});
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.dialog.add( 'scaytDialog', function( editor ) {
+	var scayt_instance =  editor.scayt;
+
+	var aboutTabDefinition = '<p><img src="' + scayt_instance.getLogo() + '" /></p>' +
+				'<p>' + scayt_instance.getLocal('version') + scayt_instance.getVersion() + '</p>' +
+				'<p>' + scayt_instance.getLocal('text_copyrights') + '</p>';
+
+	var doc = CKEDITOR.document;
+
+	var optionGenerator = function() {
+		var scayt_instance_ = editor.scayt,
+			applicationConfig = scayt_instance.getApplicationConfig(),
+			optionArrayUiCheckboxes = [],
+			optionLocalizationList = {
+				"ignore-all-caps-words" 		: "label_allCaps",
+				"ignore-domain-names" 			: "label_ignoreDomainNames",
+				"ignore-words-with-mixed-cases" : "label_mixedCase",
+				"ignore-words-with-numbers" 	: "label_mixedWithDigits"
+			};
+
+		for(var option in applicationConfig) {
+
+			var checkboxConfig = {
+				type: "checkbox"
+			};
+
+			checkboxConfig.id  = option;
+			checkboxConfig.label  = scayt_instance.getLocal(optionLocalizationList[option]);
+
+			optionArrayUiCheckboxes.push(checkboxConfig);
+		}
+
+		return optionArrayUiCheckboxes;
+	};
+
+	var languageModelState = {
+		isChanged : function() {
+			return (this.newLang === null || this.currentLang === this.newLang) ? false : true;
+		},
+		currentLang: scayt_instance.getLang(),
+		newLang: null,
+		reset: function() {
+			this.currentLang = scayt_instance.getLang();
+			this.newLang = null;
+		},
+		id: 'lang'
+	};
+
+	var generateDialogTabs = function(tabsList, editor) {
+		var tabs = [],
+			uiTabs = editor.config.scayt_uiTabs;
+
+		if(!uiTabs) {
+			return tabsList;
+		} else {
+			for(var i in uiTabs) {
+				(uiTabs[i] == 1) && tabs.push(tabsList[i]);
+			}
+
+			tabs.push(tabsList[tabsList.length - 1]);
+		}
+
+		return tabs;
+	};
+
+	var dialogTabs = [{
+		id : 'options',
+		label : scayt_instance.getLocal('tab_options'),
+		onShow: function() {
+			// console.log("tab show");
+		},
+		elements : [
+			{
+				type: 'vbox',
+				id: 'scaytOptions',
+				children: optionGenerator(),
+				onShow: function() {
+					var optionsTab = this.getChild(),
+						scayt_instance =  editor.scayt;
+					for(var i = 0; i < this.getChild().length; i++) {
+						this.getChild()[i].setValue(scayt_instance.getApplicationConfig()[this.getChild()[i].id]);
+					}
+
+				}
+			}
+
+		]
+	},
+	{
+		id : 'langs',
+		label : scayt_instance.getLocal('tab_languages'),
+		elements : [
+			{
+				id: "leftLangColumn",
+				type: 'vbox',
+				align: 'left',
+				widths: ['100'],
+				children: [
+					{
+						type: 'html',
+						id: 'langBox',
+						style: 'overflow: hidden; white-space: normal;margin-bottom:15px;',
+						html: '<div><div style="float:left;width:45%;margin-left:5px;" id="left-col-' + editor.name + '"></div><div style="float:left;width:45%;margin-left:15px;" id="right-col-' + editor.name + '"></div></div>',
+						onShow: function() {
+							var scayt_instance =  editor.scayt;
+							var lang = scayt_instance.getLang(),
+								prefix_id = "scaytLang_",
+								radio = doc.getById(prefix_id + editor.name + '_' + lang);
+
+							radio.$.checked = true;
+						}
+					},
+					{
+						type: 'html',
+						id: 'graytLanguagesHint',
+						html: '<div style="margin:5px auto; width:95%;white-space:normal;" id="' + editor.name + 'graytLanguagesHint"><span style="width:10px;height:10px;display: inline-block; background:#02b620;vertical-align:top;margin-top:2px;"></span> - This languages are supported by Grammar As You Type(GRAYT).</div>',
+						onShow: function() {
+							var graytLanguagesHint = doc.getById(editor.name + 'graytLanguagesHint');
+
+							if (!editor.config.grayt_autoStartup) {
+								graytLanguagesHint.$.style.display = 'none';
+							}
+						}
+					}
+				]
+			}
+		]
+	},
+	{
+		id : 'dictionaries',
+		label : scayt_instance.getLocal('tab_dictionaries'),
+		elements : [
+			{
+				type: 'vbox',
+				id: 'rightCol_col__left',
+				children: [
+					{
+						type: 'html',
+						id: 'dictionaryNote',
+						html: ''
+					},
+					{
+						type: 'text',
+						id: 'dictionaryName',
+						label: scayt_instance.getLocal('label_fieldNameDic') || 'Dictionary name',
+						onShow: function(data) {
+							var dialog = data.sender,
+								scayt_instance = editor.scayt;
+
+							// IE7 specific fix
+							setTimeout(function() {
+								// clear dictionaryNote field
+								dialog.getContentElement("dictionaries", "dictionaryNote").getElement().setText('');
+
+								// restore/clear dictionaryName field
+								if(scayt_instance.getUserDictionaryName() != null && scayt_instance.getUserDictionaryName() != '') {
+									dialog.getContentElement("dictionaries", "dictionaryName").setValue(scayt_instance.getUserDictionaryName());
+								}
+							}, 0);
+						}
+					},
+					{
+						type: 'hbox',
+						id: 'notExistDic',
+						align: 'left',
+						style: 'width:auto;',
+						widths: [ '50%', '50%' ],
+						children: [
+							{
+								type: 'button',
+								id: 'createDic',
+								label: scayt_instance.getLocal('btn_createDic'),
+								title: scayt_instance.getLocal('btn_createDic'),
+								onClick: function() {
+									var dialog = this.getDialog(),
+										self = dialogDefinition,
+										scayt_instance = editor.scayt,
+										name = dialog.getContentElement("dictionaries", "dictionaryName").getValue();
+
+									scayt_instance.createUserDictionary(name, function(response) {
+										if(!response.error) {
+											self.toggleDictionaryButtons.call(dialog, true);
+										}
+										response.dialog = dialog;
+										response.command = "create";
+										response.name = name;
+										editor.fire("scaytUserDictionaryAction", response);
+									}, function(error) {
+										error.dialog = dialog;
+										error.command = "create";
+										error.name = name;
+										editor.fire("scaytUserDictionaryActionError", error);
+									});
+								}
+							},
+							{
+								type: 'button',
+								id: 'restoreDic',
+								label: scayt_instance.getLocal('btn_restoreDic'),
+								title: scayt_instance.getLocal('btn_restoreDic'),
+								onClick: function() {
+									var dialog = this.getDialog(),
+										scayt_instance = editor.scayt,
+										self = dialogDefinition,
+										name = dialog.getContentElement("dictionaries", "dictionaryName").getValue();
+
+									scayt_instance.restoreUserDictionary(name, function(response) {
+										response.dialog = dialog;
+										if(!response.error) {
+											self.toggleDictionaryButtons.call(dialog, true);
+										}
+										response.command = "restore";
+										response.name = name;
+										editor.fire("scaytUserDictionaryAction", response);
+									}, function(error) {
+										error.dialog = dialog;
+										error.command = "restore";
+										error.name = name;
+										editor.fire("scaytUserDictionaryActionError", error);
+									});
+								}
+							}
+						]
+					},
+					{
+						type: 'hbox',
+						id: 'existDic',
+						align: 'left',
+						style: 'width:auto;',
+						widths: [ '50%', '50%' ],
+						children: [
+							{
+								type: 'button',
+								id: 'removeDic',
+								label: scayt_instance.getLocal('btn_deleteDic'),
+								title: scayt_instance.getLocal('btn_deleteDic'),
+								onClick: function() {
+									var dialog = this.getDialog(),
+										scayt_instance = editor.scayt,
+										self = dialogDefinition,
+										dictionaryNameField = dialog.getContentElement("dictionaries", "dictionaryName"),
+										name = dictionaryNameField.getValue();
+
+									scayt_instance.removeUserDictionary(name, function(response) {
+										dictionaryNameField.setValue("");
+										if(!response.error) {
+											self.toggleDictionaryButtons.call(dialog, false);
+										}
+										response.dialog = dialog;
+										response.command = "remove";
+										response.name = name;
+										editor.fire("scaytUserDictionaryAction", response);
+									}, function(error) {
+										error.dialog = dialog;
+										error.command = "remove";
+										error.name = name;
+										editor.fire("scaytUserDictionaryActionError", error);
+									});
+								}
+							},
+							{
+								type: 'button',
+								id: 'renameDic',
+								label: scayt_instance.getLocal('btn_renameDic'),
+								title: scayt_instance.getLocal('btn_renameDic'),
+								onClick: function() {
+									var dialog = this.getDialog(),
+										scayt_instance = editor.scayt,
+										name = dialog.getContentElement("dictionaries", "dictionaryName").getValue();
+
+									scayt_instance.renameUserDictionary(name, function(response) {
+										response.dialog = dialog;
+										response.command = "rename";
+										response.name = name;
+										editor.fire("scaytUserDictionaryAction", response);
+									}, function(error) {
+										error.dialog = dialog;
+										error.command = "rename";
+										error.name = name;
+										editor.fire("scaytUserDictionaryActionError", error);
+									});
+								}
+							}
+						]
+					},
+					{
+						type: 'html',
+						id: 'dicInfo',
+						html: '<div id="dic_info_editor1" style="margin:5px auto; width:95%;white-space:normal;">' + scayt_instance.getLocal('text_descriptionDic')  + '</div>'
+					}
+				]
+			}
+		]
+	},
+	{
+		id : 'about',
+		label : scayt_instance.getLocal('tab_about'),
+		elements : [
+			{
+				type : 'html',
+				id : 'about',
+				style : 'margin: 5px 5px;',
+				html : '<div><div id="scayt_about_">' +
+						aboutTabDefinition +
+						'</div></div>'
+			}
+		]
+	}];
+
+	editor.on("scaytUserDictionaryAction", function(event) {
+		var UILib = SCAYT.prototype.UILib,
+			dialog = event.data.dialog,
+			dictionaryNote = dialog.getContentElement("dictionaries", "dictionaryNote").getElement(),
+			scayt_instance =  event.editor.scayt,
+			messageTemplate;
+
+		if(event.data.error === undefined) {
+
+			// success message
+			messageTemplate = scayt_instance.getLocal("message_success_" + event.data.command + "Dic");
+			messageTemplate = messageTemplate.replace('%s', event.data.name);
+			dictionaryNote.setText(messageTemplate);
+			UILib.css(dictionaryNote.$, {color: 'blue'});
+		} else {
+
+			// error message
+			if(event.data.name === '') {
+
+				// empty dictionary name
+				dictionaryNote.setText(scayt_instance.getLocal('message_info_emptyDic'));
+			} else {
+				messageTemplate = scayt_instance.getLocal("message_error_" + event.data.command + "Dic");
+				messageTemplate = messageTemplate.replace('%s', event.data.name);
+				dictionaryNote.setText(messageTemplate);
+			}
+			UILib.css(dictionaryNote.$, {color: 'red'});
+
+			if(scayt_instance.getUserDictionaryName() != null && scayt_instance.getUserDictionaryName() != '') {
+				dialog.getContentElement("dictionaries", "dictionaryName").setValue(scayt_instance.getUserDictionaryName());
+			} else {
+				dialog.getContentElement("dictionaries", "dictionaryName").setValue("");
+			}
+		}
+	});
+
+	editor.on("scaytUserDictionaryActionError", function(event) {
+		var UILib = SCAYT.prototype.UILib,
+			dialog = event.data.dialog,
+			dictionaryNote = dialog.getContentElement("dictionaries", "dictionaryNote").getElement(),
+			scayt_instance =  event.editor.scayt,
+			messageTemplate;
+
+		if(event.data.name === '') {
+
+			// empty dictionary name
+			dictionaryNote.setText(scayt_instance.getLocal('message_info_emptyDic'));
+		} else {
+			messageTemplate = scayt_instance.getLocal("message_error_" + event.data.command + "Dic");
+			messageTemplate = messageTemplate.replace('%s', event.data.name);
+			dictionaryNote.setText(messageTemplate);
+		}
+		UILib.css(dictionaryNote.$, {color: 'red'});
+
+
+		if(scayt_instance.getUserDictionaryName() != null && scayt_instance.getUserDictionaryName() != '') {
+			dialog.getContentElement("dictionaries", "dictionaryName").setValue(scayt_instance.getUserDictionaryName());
+		} else {
+			dialog.getContentElement("dictionaries", "dictionaryName").setValue("");
+		}
+
+	});
+
+	var plugin = CKEDITOR.plugins.scayt;
+
+	var dialogDefinition = {
+		title:          scayt_instance.getLocal('text_title'),
+		resizable:      CKEDITOR.DIALOG_RESIZE_BOTH,
+		minWidth: 		340,
+		minHeight: 		260,
+		onLoad: function() {
+			if(editor.config.scayt_uiTabs[1] == 0) {
+				return;
+			}
+
+			var dialog = this,
+				self = dialogDefinition,
+				langBoxes = self.getLangBoxes.call(dialog);
+
+			langBoxes.getParent().setStyle("white-space", "normal");
+
+			//dialog.data = editor.fire( 'scaytDialog', {} );
+			self.renderLangList(langBoxes);
+
+			var scayt_instance = editor.scayt;
+
+			this.definition.minWidth = this.getSize().width;
+			this.resize(this.definition.minWidth, this.definition.minHeight);
+		},
+		onCancel: function() {
+			languageModelState.reset();
+		},
+		onHide: function() {
+			editor.unlockSelection();
+		},
+		onShow: function() {
+			editor.fire("scaytDialogShown", this);
+
+			if(editor.config.scayt_uiTabs[2] == 0) {
+				return;
+			}
+
+			var scayt_instance = editor.scayt,
+				self = dialogDefinition,
+				dialog = this,
+				dictionaryNameField = dialog.getContentElement("dictionaries", "dictionaryName"),
+				existance = dialog.getContentElement("dictionaries", "existDic").getElement().getParent(),
+				notExistance = dialog.getContentElement("dictionaries", "notExistDic").getElement().getParent();
+
+			existance.hide();
+			notExistance.hide();
+
+			if(scayt_instance.getUserDictionaryName() != null && scayt_instance.getUserDictionaryName() != '') {
+				dialog.getContentElement("dictionaries", "dictionaryName").setValue(scayt_instance.getUserDictionaryName());
+				existance.show();
+			} else {
+				dictionaryNameField.setValue("");
+				notExistance.show();
+			}
+		},
+		onOk: function() {
+			var dialog = this,
+				self = dialogDefinition,
+				scayt_instance =  editor.scayt,
+				scaytOptions = dialog.getContentElement("options", "scaytOptions"),
+				changedOptions = self.getChangedOption.call(dialog);
+
+			scayt_instance.commitOption({ changedOptions: changedOptions });
+		},
+		toggleDictionaryButtons: function(exist) {
+			var existance = this.getContentElement("dictionaries", "existDic").getElement().getParent(),
+				notExistance = this.getContentElement("dictionaries", "notExistDic").getElement().getParent();
+
+			if(exist) {
+				existance.show();
+				notExistance.hide();
+			} else {
+				existance.hide();
+				notExistance.show();
+			}
+
+		},
+		getChangedOption: function() {
+			var changedOption = {};
+
+			if(editor.config.scayt_uiTabs[0] == 1) {
+				var dialog = this,
+					scaytOptions = dialog.getContentElement("options", "scaytOptions").getChild();
+
+				for(var i = 0; i < scaytOptions.length; i++) {
+					if(scaytOptions[i].isChanged()) {
+						changedOption[scaytOptions[i].id] = scaytOptions[i].getValue();
+					}
+				}
+			}
+
+			if(languageModelState.isChanged()) {
+				changedOption[languageModelState.id] = editor.config.scayt_sLang = languageModelState.currentLang = languageModelState.newLang;
+			}
+
+			return changedOption;
+		},
+		buildRadioInputs: function(key, value, isSupportedByGrayt) {
+			var divContainer = new CKEDITOR.dom.element( 'div' ),
+				doc = CKEDITOR.document,
+				id = "scaytLang_" + editor.name + '_' + value,
+				radio = CKEDITOR.dom.element.createFromHtml( '<input id="' +
+					id + '" type="radio" ' +
+					' value="' + value + '" name="scayt_lang" />' ),
+
+				radioLabel = new CKEDITOR.dom.element( 'label' ),
+				scayt_instance = editor.scayt;
+
+			divContainer.setStyles({
+				"white-space": "normal",
+				'position': 'relative',
+				'padding-bottom': '2px'
+			});
+
+			radio.on( 'click', function(data) {
+				languageModelState.newLang = data.sender.getValue();
+			});
+
+			radioLabel.appendText(key);
+			radioLabel.setAttribute("for", id);
+
+			if(isSupportedByGrayt && editor.config.grayt_autoStartup) {
+				radioLabel.setStyles({
+					'color': '#02b620'
+				});
+			}
+
+			divContainer.append(radio);
+			divContainer.append(radioLabel);
+
+			if(value === scayt_instance.getLang()) {
+				radio.setAttribute("checked", true);
+				radio.setAttribute('defaultChecked', 'defaultChecked');
+			}
+
+			return divContainer;
+		},
+		renderLangList: function(langBoxes) {
+			var dialog = this,
+				leftCol = langBoxes.find('#left-col-' + editor.name).getItem(0),
+				rightCol = langBoxes.find('#right-col-' + editor.name).getItem(0),
+				scaytLangList = scayt_instance.getScaytLangList(),
+				graytLangList = scayt_instance.getGraytLangList(),
+				mergedLangList = {},
+				sortable = [],
+				counter = 0,
+				isSupportedByGrayt = false,
+				half, lang;
+
+			for(lang in scaytLangList.ltr) {
+				mergedLangList[lang] = scaytLangList.ltr[lang];
+			}
+
+			for(lang in scaytLangList.rtl) {
+				mergedLangList[lang] = scaytLangList.rtl[lang];
+			}
+
+			// sort alphabetically lang list
+			for(lang in mergedLangList) {
+				sortable.push([lang, mergedLangList[lang]]);
+			}
+			sortable.sort(function(a, b) {
+				var result = 0;
+				if(a[1] > b[1]) {
+					result = 1;
+				} else if(a[1] < b[1]) {
+					result = -1;
+				}
+				return result;
+			});
+			mergedLangList = {};
+			for(var i = 0; i < sortable.length; i++) {
+				mergedLangList[sortable[i][0]] = sortable[i][1];
+			}
+
+			half = Math.round(sortable.length / 2);
+
+			for(lang in mergedLangList) {
+				counter++;
+				isSupportedByGrayt = (lang in graytLangList.ltr) || (lang in graytLangList.rtl);
+				dialog.buildRadioInputs(mergedLangList[lang], lang, isSupportedByGrayt).appendTo(counter <= half ? leftCol : rightCol);
+			}
+		},
+		getLangBoxes: function() {
+			var dialog = this,
+				langboxes = dialog.getContentElement("langs", "langBox").getElement();
+
+			return langboxes;
+		},
+		contents: generateDialogTabs(dialogTabs, editor)
+	};
+
+	return dialogDefinition;
+});

+ 71 - 71
app/Resources/public/assets/ckeditor/plugins/scayt/dialogs/toolbar.css

@@ -1,71 +1,71 @@
-a
-{
-	text-decoration:none;
-	padding: 2px 4px 4px 6px;
-	display : block;
-	border-width: 1px;
-	border-style: solid;
-	margin : 0px;
-}
-
-a.cke_scayt_toogle:hover,
-a.cke_scayt_toogle:focus,
-a.cke_scayt_toogle:active
-{
-	border-color: #316ac5;
-	background-color: #dff1ff;
-	color : #000;
-	cursor: pointer;
-	margin : 0px;
-}
-a.cke_scayt_toogle {
-	color : #316ac5;
-	border-color: #fff;
-}
-.scayt_enabled a.cke_scayt_item {
-	color : #316ac5;
-	border-color: #fff;
-	margin : 0px;
-}
-.scayt_disabled a.cke_scayt_item {
-	color : gray;
-	border-color : #fff;
-}
-.scayt_enabled a.cke_scayt_item:hover,
-.scayt_enabled a.cke_scayt_item:focus,
-.scayt_enabled a.cke_scayt_item:active
-{
-	border-color: #316ac5;
-	background-color: #dff1ff;
-	color : #000;
-	cursor: pointer;
-}
-.scayt_disabled a.cke_scayt_item:hover,
-.scayt_disabled a.cke_scayt_item:focus,
-.scayt_disabled a.cke_scayt_item:active
-{
-	border-color: gray;
-	background-color: #dff1ff;
-	color : gray;
-	cursor: no-drop;
-}
-.cke_scayt_set_on, .cke_scayt_set_off
-{
-	display: none;
-}
-.scayt_enabled .cke_scayt_set_on
-{
-	display: none;
-}
-.scayt_disabled .cke_scayt_set_on
-{
-	display: inline;
-}
-.scayt_disabled .cke_scayt_set_off
-{
-	display: none;
-}
-.scayt_enabled  .cke_scayt_set_off
-{
-	display: inline;
-}
+a
+{
+	text-decoration:none;
+	padding: 2px 4px 4px 6px;
+	display : block;
+	border-width: 1px;
+	border-style: solid;
+	margin : 0px;
+}
+
+a.cke_scayt_toogle:hover,
+a.cke_scayt_toogle:focus,
+a.cke_scayt_toogle:active
+{
+	border-color: #316ac5;
+	background-color: #dff1ff;
+	color : #000;
+	cursor: pointer;
+	margin : 0px;
+}
+a.cke_scayt_toogle {
+	color : #316ac5;
+	border-color: #fff;
+}
+.scayt_enabled a.cke_scayt_item {
+	color : #316ac5;
+	border-color: #fff;
+	margin : 0px;
+}
+.scayt_disabled a.cke_scayt_item {
+	color : gray;
+	border-color : #fff;
+}
+.scayt_enabled a.cke_scayt_item:hover,
+.scayt_enabled a.cke_scayt_item:focus,
+.scayt_enabled a.cke_scayt_item:active
+{
+	border-color: #316ac5;
+	background-color: #dff1ff;
+	color : #000;
+	cursor: pointer;
+}
+.scayt_disabled a.cke_scayt_item:hover,
+.scayt_disabled a.cke_scayt_item:focus,
+.scayt_disabled a.cke_scayt_item:active
+{
+	border-color: gray;
+	background-color: #dff1ff;
+	color : gray;
+	cursor: no-drop;
+}
+.cke_scayt_set_on, .cke_scayt_set_off
+{
+	display: none;
+}
+.scayt_enabled .cke_scayt_set_on
+{
+	display: none;
+}
+.scayt_disabled .cke_scayt_set_on
+{
+	display: inline;
+}
+.scayt_disabled .cke_scayt_set_off
+{
+	display: none;
+}
+.scayt_enabled  .cke_scayt_set_off
+{
+	display: inline;
+}

BIN
app/Resources/public/assets/ckeditor/plugins/scayt/icons/hidpi/scayt.png


BIN
app/Resources/public/assets/ckeditor/plugins/scayt/icons/scayt.png


+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/af.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'af', {
+	btn_about: 'SCAYT info',
+	btn_dictionaries: 'Woordeboeke',
+	btn_disable: 'SCAYT af',
+	btn_enable: 'SCAYT aan',
+	btn_langs:'Tale',
+	btn_options: 'Opsies',
+	text_title:  'Speltoets terwyl u tik'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ar.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ar', {
+	btn_about: 'عن SCAYT',
+	btn_dictionaries: 'قواميس',
+	btn_disable: 'تعطيل SCAYT',
+	btn_enable: 'تفعيل SCAYT',
+	btn_langs:'لغات',
+	btn_options: 'خيارات',
+	text_title:  'تدقيق إملائي أثناء الكتابة'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/bg.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'bg', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Речници',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/bn.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'bn', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/bs.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'bs', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ca.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ca', {
+	btn_about: 'Quant a l\'SCAYT',
+	btn_dictionaries: 'Diccionaris',
+	btn_disable: 'Deshabilita SCAYT',
+	btn_enable: 'Habilitat l\'SCAYT',
+	btn_langs:'Idiomes',
+	btn_options: 'Opcions',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/cs.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'cs', {
+	btn_about: 'O aplikaci SCAYT',
+	btn_dictionaries: 'Slovníky',
+	btn_disable: 'Vypnout SCAYT',
+	btn_enable: 'Zapnout SCAYT',
+	btn_langs:'Jazyky',
+	btn_options: 'Nastavení',
+	text_title:  'Kontrola pravopisu během psaní (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/cy.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'cy', {
+	btn_about: 'Ynghylch SCAYT',
+	btn_dictionaries: 'Geiriaduron',
+	btn_disable: 'Analluogi SCAYT',
+	btn_enable: 'Galluogi SCAYT',
+	btn_langs:'Ieithoedd',
+	btn_options: 'Opsiynau',
+	text_title:  'Gwirio\'r Sillafu Wrth Deipio'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/da.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'da', {
+	btn_about: 'Om SCAYT',
+	btn_dictionaries: 'Ordbøger',
+	btn_disable: 'Deaktivér SCAYT',
+	btn_enable: 'Aktivér SCAYT',
+	btn_langs:'Sprog',
+	btn_options: 'Indstillinger',
+	text_title: 'Stavekontrol mens du skriver'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/de.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'de', {
+	btn_about: 'Über SCAYT',
+	btn_dictionaries: 'Wörterbücher',
+	btn_disable: 'SCAYT ausschalten',
+	btn_enable: 'SCAYT einschalten',
+	btn_langs:'Sprachen',
+	btn_options: 'Optionen',
+	text_title: 'Rechtschreibprüfung während der Texteingabe (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/el.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'el', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Λεξικά',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Γλώσσες',
+	btn_options: 'Επιλογές',
+	text_title: 'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-au.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'en-au', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title: 'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-ca.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'en-ca', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title: 'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/en-gb.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'en-gb', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title: 'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/en.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'en', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title: 'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/eo.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'eo', {
+	btn_about: 'Pri OKDVT',
+	btn_dictionaries: 'Vortaroj',
+	btn_disable: 'Malebligi OKDVT',
+	btn_enable: 'Ebligi OKDVT',
+	btn_langs:'Lingvoj',
+	btn_options: 'Opcioj',
+	text_title:  'OrtografiKontrolado Dum Vi Tajpas (OKDVT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/es.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'es', {
+	btn_about: 'Acerca de Corrector',
+	btn_dictionaries: 'Diccionarios',
+	btn_disable: 'Desactivar Corrector',
+	btn_enable: 'Activar Corrector',
+	btn_langs:'Idiomas',
+	btn_options: 'Opciones',
+	text_title: 'Comprobar Ortografía Mientras Escribe'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/et.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'et', {
+	btn_about: 'SCAYT-ist lähemalt',
+	btn_dictionaries: 'Sõnaraamatud',
+	btn_disable: 'SCAYT keelatud',
+	btn_enable: 'SCAYT lubatud',
+	btn_langs:'Keeled',
+	btn_options: 'Valikud',
+	text_title:  'Õigekirjakontroll kirjutamise ajal'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/eu.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'eu', {
+	btn_about: 'SCAYTi buruz',
+	btn_dictionaries: 'Hiztegiak',
+	btn_disable: 'Desgaitu SCAYT',
+	btn_enable: 'Gaitu SCAYT',
+	btn_langs:'Hizkuntzak',
+	btn_options: 'Aukerak',
+	text_title:  'Ortografia Zuzenketa Idatzi Ahala (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/fa.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'fa', {
+	btn_about: 'درباره SCAYT',
+	btn_dictionaries: 'دیکشنریها',
+	btn_disable: 'غیرفعالسازی SCAYT',
+	btn_enable: 'فعالسازی SCAYT',
+	btn_langs:'زبانها',
+	btn_options: 'گزینهها',
+	text_title:  'بررسی املای تایپ شما'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/fi.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'fi', {
+	btn_about: 'Tietoja oikoluvusta kirjoitetaessa',
+	btn_dictionaries: 'Sanakirjat',
+	btn_disable: 'Poista käytöstä oikoluku kirjoitetaessa',
+	btn_enable: 'Ota käyttöön oikoluku kirjoitettaessa',
+	btn_langs:'Kielet',
+	btn_options: 'Asetukset',
+	text_title: 'Oikolue kirjoitettaessa'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/fo.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'fo', {
+	btn_about: 'Um SCAYT',
+	btn_dictionaries: 'Orðabøkur',
+	btn_disable: 'Nokta SCAYT',
+	btn_enable: 'Loyv SCAYT',
+	btn_langs:'Tungumál',
+	btn_options: 'Uppseting',
+	text_title:  'Kanna stavseting, meðan tú skrivar'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/fr-ca.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'fr-ca', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/fr.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'fr', {
+	btn_about: 'A propos de SCAYT',
+	btn_dictionaries: 'Dictionnaires',
+	btn_disable: 'Désactiver SCAYT',
+	btn_enable: 'Activer SCAYT',
+	btn_langs:'Langues',
+	btn_options: 'Options',
+	text_title: 'Vérification de l\'Orthographe en Cours de Frappe (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/gl.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'gl', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/gu.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'gu', {
+	btn_about: 'SCAYT વિષે',
+	btn_dictionaries: 'શબ્દકોશ',
+	btn_disable: 'SCAYT ડિસેબલ કરવું',
+	btn_enable: 'SCAYT એનેબલ કરવું',
+	btn_langs:'ભાષાઓ',
+	btn_options: 'વિકલ્પો',
+	text_title:  'ટાઈપ કરતા સ્પેલ તપાસો'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/he.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'he', {
+	btn_about: 'אודות SCAYT',
+	btn_dictionaries: 'מילון',
+	btn_disable: 'בטל SCAYT',
+	btn_enable: 'אפשר SCAYT',
+	btn_langs:'שפות',
+	btn_options: 'אפשרויות',
+	text_title:  'בדיקת איות בזמן כתיבה (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/hi.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'hi', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/hr.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'hr', {
+	btn_about: 'O SCAYT',
+	btn_dictionaries: 'Rječnici',
+	btn_disable: 'Onemogući SCAYT',
+	btn_enable: 'Omogući SCAYT',
+	btn_langs:'Jezici',
+	btn_options: 'Opcije',
+	text_title:  'Provjeri pravopis tijekom tipkanja (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/hu.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'hu', {
+	btn_about: 'SCAYT névjegy',
+	btn_dictionaries: 'Szótár',
+	btn_disable: 'SCAYT letiltása',
+	btn_enable: 'SCAYT engedélyezése',
+	btn_langs:'Nyelvek',
+	btn_options: 'Beállítások',
+	text_title:  'Helyesírás ellenőrzés gépelés közben'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/is.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'is', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/it.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'it', {
+	btn_about: 'About COMS',
+	btn_dictionaries: 'Dizionari',
+	btn_disable: 'Disabilita COMS',
+	btn_enable: 'Abilita COMS',
+	btn_langs:'Lingue',
+	btn_options: 'Opzioni',
+	text_title: 'Controllo Ortografico Mentre Scrivi'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ja.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ja', {
+	btn_about: 'SCAYTバージョン',
+	btn_dictionaries: '辞書',
+	btn_disable: 'SCAYT無効',
+	btn_enable: 'SCAYT有効',
+	btn_langs:'言語',
+	btn_options: 'オプション',
+	text_title:  'スペルチェック設定(SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ka.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ka', {
+	btn_about: 'SCAYT-ის შესახებ',
+	btn_dictionaries: 'ლექსიკონები',
+	btn_disable: 'SCAYT-ის გამორთვა',
+	btn_enable: 'SCAYT-ის ჩართვა',
+	btn_langs:'ენები',
+	btn_options: 'პარამეტრები',
+	text_title:  'მართლწერის შემოწმება კრეფისას'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/km.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'km', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ko.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ko', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ku.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ku', {
+	btn_about: 'دهربارهی SCAYT',
+	btn_dictionaries: 'فهرههنگهکان',
+	btn_disable: 'ناچالاککردنی SCAYT',
+	btn_enable: 'چالاککردنی SCAYT',
+	btn_langs:'زمانهکان',
+	btn_options: 'ههڵبژارده',
+	text_title:  'پشکنینی نووسه لهکاتی نووسین'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/lt.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'lt', {
+	btn_about: 'Apie SCAYT',
+	btn_dictionaries: 'Žodynai',
+	btn_disable: 'Išjungti SCAYT',
+	btn_enable: 'Įjungti SCAYT',
+	btn_langs:'Kalbos',
+	btn_options: 'Parametrai',
+	text_title:  'Tikrinti klaidas kai rašoma'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/lv.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'lv', {
+	btn_about: 'Par SCAYT',
+	btn_dictionaries: 'Vārdnīcas',
+	btn_disable: 'Atslēgt SCAYT',
+	btn_enable: 'Ieslēgt SCAYT',
+	btn_langs:'Valodas',
+	btn_options: 'Uzstādījumi',
+	text_title:  'Pārbaudīt gramatiku rakstot'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/mk.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'mk', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/mn.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'mn', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Толь бичгүүд',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Хэлүүд',
+	btn_options: 'Сонголт',
+	text_title:  'Spell Check As You Type'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ms.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ms', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/nb.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'nb', {
+	btn_about: 'Om SCAYT',
+	btn_dictionaries: 'Ordbøker',
+	btn_disable: 'Slå av SCAYT',
+	btn_enable: 'Slå på SCAYT',
+	btn_langs:'Språk',
+	btn_options: 'Valg',
+	text_title:  'Stavekontroll mens du skriver'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/nl.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'nl', {
+	btn_about: 'Over SCAYT',
+	btn_dictionaries: 'Woordenboeken',
+	btn_disable: 'SCAYT uitschakelen',
+	btn_enable: 'SCAYT inschakelen',
+	btn_langs:'Talen',
+	btn_options: 'Opties',
+	text_title: 'Controleer de spelling tijdens het typen'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/no.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'no', {
+	btn_about: 'Om SCAYT',
+	btn_dictionaries: 'Ordbøker',
+	btn_disable: 'Slå av SCAYT',
+	btn_enable: 'Slå på SCAYT',
+	btn_langs:'Språk',
+	btn_options: 'Valg',
+	text_title: 'Stavekontroll mens du skriver'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/pl.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'pl', {
+	btn_about: 'Informacje o SCAYT',
+	btn_dictionaries: 'Słowniki',
+	btn_disable: 'Wyłącz SCAYT',
+	btn_enable: 'Włącz SCAYT',
+	btn_langs:'Języki',
+	btn_options: 'Opcje',
+	text_title:  'Sprawdź pisownię podczas pisania (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/pt-br.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'pt-br', {
+	btn_about: 'Sobre a correção ortográfica durante a digitação',
+	btn_dictionaries: 'Dicionários',
+	btn_disable: 'Desabilitar correção ortográfica durante a digitação',
+	btn_enable: 'Habilitar correção ortográfica durante a digitação',
+	btn_langs:'Idiomas',
+	btn_options: 'Opções',
+	text_title: 'Correção ortográfica durante a digitação'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/pt.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'pt', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title: 'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ro.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ro', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ru.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ru', {
+	btn_about: 'О SCAYT',
+	btn_dictionaries: 'Словари',
+	btn_disable: 'Отключить SCAYT',
+	btn_enable: 'Включить SCAYT',
+	btn_langs:'Языки',
+	btn_options: 'Настройки',
+	text_title: 'Проверка орфографии по мере ввода (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/sk.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'sk', {
+	btn_about: 'O KPPP (Kontrola pravopisu počas písania)',
+	btn_dictionaries: 'Slovníky',
+	btn_disable: 'Zakázať  KPPP (Kontrola pravopisu počas písania)',
+	btn_enable: 'Povoliť KPPP (Kontrola pravopisu počas písania)',
+	btn_langs:'Jazyky',
+	btn_options: 'Možnosti',
+	text_title:  'Kontrola pravopisu počas písania'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/sl.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'sl', {
+	btn_about: 'O storitvi SCAYT',
+	btn_dictionaries: 'Slovarji',
+	btn_disable: 'Onemogoči SCAYT',
+	btn_enable: 'Omogoči SCAYT',
+	btn_langs:'Jeziki',
+	btn_options: 'Možnosti',
+	text_title:  'Črkovanje med tipkanjem'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/sr-latn.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'sr-latn', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/sr.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'sr', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/sv.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'sv', {
+	btn_about: 'Om SCAYT',
+	btn_dictionaries: 'Ordlistor',
+	btn_disable: 'Inaktivera SCAYT',
+	btn_enable: 'Aktivera SCAYT',
+	btn_langs:'Språk',
+	btn_options: 'Inställningar',
+	text_title: 'Stavningskontroll medan du skriver'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/th.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'th', {
+	btn_about: 'About SCAYT',
+	btn_dictionaries: 'Dictionaries',
+	btn_disable: 'Disable SCAYT',
+	btn_enable: 'Enable SCAYT',
+	btn_langs:'Languages',
+	btn_options: 'Options',
+	text_title:  'Spell Check As You Type' // MISSING
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/tr.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'tr', {
+	btn_about: 'SCAYT\'ı hakkında',
+	btn_dictionaries: 'Sözlükler',
+	btn_disable: 'SCAYT\'ı pasifleştir',
+	btn_enable: 'SCAYT\'ı etkinleştir',
+	btn_langs:'Diller',
+	btn_options: 'Seçenekler',
+	text_title:  'Girmiş olduğunuz kelime denetimi'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/ug.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'ug', {
+	btn_about: 'شۇئان ئىملا تەكشۈرۈش ھەققىدە',
+	btn_dictionaries: 'لۇغەت',
+	btn_disable: 'شۇئان ئىملا تەكشۈرۈشنى چەكلە',
+	btn_enable: 'شۇئان ئىملا تەكشۈرۈشنى قوزغات',
+	btn_langs:'تىل',
+	btn_options: 'تاللانما',
+	text_title:  'شۇئان ئىملا تەكشۈر'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/uk.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'uk', {
+	btn_about: 'Про SCAYT',
+	btn_dictionaries: 'Словники',
+	btn_disable: 'Вимкнути SCAYT',
+	btn_enable: 'Ввімкнути SCAYT',
+	btn_langs:'Мови',
+	btn_options: 'Опції',
+	text_title:  'Перефірка орфографії по мірі набору'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/vi.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'vi', {
+	btn_about: 'Thông tin về SCAYT',
+	btn_dictionaries: 'Từ điển',
+	btn_disable: 'Tắt SCAYT',
+	btn_enable: 'Bật SCAYT',
+	btn_langs:'Ngôn ngữ',
+	btn_options: 'Tùy chọn',
+	text_title:  'Kiểm tra chính tả ngay khi gõ chữ (SCAYT)'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/zh-cn.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'zh-cn', {
+	btn_about: '关于即时拼写检查',
+	btn_dictionaries: '字典',
+	btn_disable: '禁用即时拼写检查',
+	btn_enable: '启用即时拼写检查',
+	btn_langs:'语言',
+	btn_options: '选项',
+	text_title:  '即时拼写检查'
+});

+ 13 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/lang/zh.js

@@ -0,0 +1,13 @@
+/*
+Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'scayt', 'zh', {
+	btn_about: '關於即時拼寫檢查',
+	btn_dictionaries: '字典',
+	btn_disable: '關閉即時拼寫檢查',
+	btn_enable: '啟用即時拼寫檢查',
+	btn_langs: '語言',
+	btn_options: '選項',
+	text_title:  '即時拼寫檢查'
+});

+ 1877 - 0
app/Resources/public/assets/ckeditor/plugins/scayt/plugin.js

@@ -0,0 +1,1877 @@
+'use strict';
+CKEDITOR.plugins.add('scayt', {
+
+	//requires : ['menubutton', 'dialog'],
+	requires: 'menubutton,dialog',
+	lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en-au,en-ca,en-gb,en,eo,es,et,eu,fa,fi,fo,fr-ca,fr,gl,gu,he,hi,hr,hu,is,it,ja,ka,km,ko,lt,lv,mk,mn,ms,nb,nl,no,pl,pt-br,pt,ro,ru,sk,sl,sr-latn,sr,sv,th,tr,ug,uk,vi,zh-cn,zh', // %REMOVE_LINE_CORE%
+	icons: 'scayt', // %REMOVE_LINE_CORE%
+	hidpi: true, // %REMOVE_LINE_CORE%
+	tabToOpen : null,
+	dialogName: 'scaytDialog',
+	init: function(editor) {
+		var self = this,
+			plugin = CKEDITOR.plugins.scayt;
+
+		this.bindEvents(editor);
+		this.parseConfig(editor);
+		this.addRule(editor);
+
+		// source mode
+		CKEDITOR.dialog.add(this.dialogName, CKEDITOR.getUrl(this.path + 'dialogs/options.js'));
+		// end source mode
+
+		this.addMenuItems(editor);
+		var config = editor.config,
+			lang = editor.lang.scayt,
+			env = CKEDITOR.env;
+
+		editor.ui.add('Scayt', CKEDITOR.UI_MENUBUTTON, {
+			label : lang.text_title,
+			title : ( editor.plugins.wsc ? editor.lang.wsc.title : lang.text_title ),
+			// SCAYT doesn't work in IE Compatibility Mode and IE (8 & 9) Quirks Mode
+			modes : {wysiwyg: !(env.ie && ( env.version < 8 || env.quirks ) ) },
+			toolbar: 'spellchecker,20',
+			refresh: function() {
+				var buttonState = editor.ui.instances.Scayt.getState();
+
+				// check if scayt is created
+				if(editor.scayt) {
+					// check if scayt is enabled
+					if(plugin.state.scayt[editor.name]) {
+						buttonState = CKEDITOR.TRISTATE_ON;
+					} else {
+						buttonState = CKEDITOR.TRISTATE_OFF;
+					}
+				}
+
+				editor.fire('scaytButtonState', buttonState);
+			},
+			onRender: function() {
+				var that = this;
+
+				editor.on('scaytButtonState', function(ev) {
+					if(typeof ev.data !== undefined) {
+						that.setState(ev.data);
+					}
+				});
+			},
+			onMenu : function() {
+				var scaytInstance = editor.scayt;
+
+				editor.getMenuItem('scaytToggle').label = editor.lang.scayt[(scaytInstance ? plugin.state.scayt[editor.name] : false) ? 'btn_disable' : 'btn_enable'];
+
+				// If UI tab is disabled we shouldn't show menu item
+				var menuDefinition = {
+					scaytToggle  : CKEDITOR.TRISTATE_OFF,
+					scaytOptions : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
+					scaytLangs   : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
+					scaytDict    : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
+					scaytAbout   : scaytInstance ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED,
+					WSC          : editor.plugins.wsc ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED
+				};
+
+				if(!editor.config.scayt_uiTabs[0]) {
+					delete menuDefinition.scaytOptions;
+				}
+
+				if(!editor.config.scayt_uiTabs[1]) {
+					delete menuDefinition.scaytLangs;
+				}
+
+				if(!editor.config.scayt_uiTabs[2]) {
+					delete menuDefinition.scaytDict;
+				}
+
+				return menuDefinition;
+			}
+		});
+
+		// If the 'contextmenu' plugin is loaded, register the listeners.
+		if(editor.contextMenu && editor.addMenuItems) {
+			editor.contextMenu.addListener(function(element, selection) {
+				var scaytInstance = editor.scayt,
+					result, selectionNode;
+
+				if(scaytInstance) {
+					selectionNode = scaytInstance.getSelectionNode();
+
+					// SCAYT shouldn't build context menu if instance isnot created or word is without misspelling or grammar problem
+					if(selectionNode) {
+						var items = self.menuGenerator(editor, selectionNode);
+
+						scaytInstance.showBanner('.' + editor.contextMenu._.definition.panel.className.split(' ').join(' .'));
+						result = items;
+					}
+				}
+
+				return result;
+			});
+
+			editor.contextMenu._.onHide = CKEDITOR.tools.override(editor.contextMenu._.onHide, function(org) {
+				return function() {
+					var scaytInstance = editor.scayt;
+
+					if(scaytInstance) {
+						scaytInstance.hideBanner();
+					}
+
+					return org.apply(this);
+				};
+			});
+		}
+	},
+	addMenuItems: function(editor) {
+		var self = this,
+			plugin = CKEDITOR.plugins.scayt,
+			graytGroups = ['grayt_description', 'grayt_suggest', 'grayt_control'],
+			menuGroup = 'scaytButton';
+
+		editor.addMenuGroup(menuGroup);
+
+		var items_order = editor.config.scayt_contextMenuItemsOrder.split('|');
+
+		for(var pos = 0 ; pos < items_order.length ; pos++) {
+			items_order[pos] = 'scayt_' + items_order[pos];
+		}
+		items_order = graytGroups.concat(items_order);
+
+		if(items_order && items_order.length) {
+			for(var pos = 0 ; pos < items_order.length ; pos++) {
+				editor.addMenuGroup(items_order[pos], pos - 10);
+			}
+		}
+
+		editor.addCommand( 'scaytToggle', {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt;
+
+				plugin.state.scayt[editor.name] = !plugin.state.scayt[editor.name];
+
+				if(plugin.state.scayt[editor.name] === true) {
+					if(!scaytInstance) {
+						plugin.createScayt(editor);
+					}
+				} else {
+					if(scaytInstance) {
+						plugin.destroy(editor);
+					}
+				}
+			}
+		} );
+
+		editor.addCommand( 'scaytAbout', {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt;
+
+				scaytInstance.tabToOpen = 'about';
+				editor.lockSelection();
+				editor.openDialog(self.dialogName);
+			}
+		} );
+
+		editor.addCommand( 'scaytOptions', {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt;
+
+				scaytInstance.tabToOpen = 'options';
+				editor.lockSelection();
+				editor.openDialog(self.dialogName);
+			}
+		} );
+
+		editor.addCommand( 'scaytLangs', {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt;
+
+				scaytInstance.tabToOpen = 'langs';
+				editor.lockSelection();
+				editor.openDialog(self.dialogName);
+			}
+		} );
+
+		editor.addCommand( 'scaytDict', {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt;
+
+				scaytInstance.tabToOpen = 'dictionaries';
+				editor.lockSelection();
+				editor.openDialog(self.dialogName);
+			}
+		} );
+
+		var uiMenuItems = {
+			scaytToggle: {
+				label : editor.lang.scayt.btn_enable,
+				group : menuGroup,
+				command: 'scaytToggle'
+			},
+			scaytAbout: {
+				label : editor.lang.scayt.btn_about,
+				group : menuGroup,
+				command: 'scaytAbout'
+			},
+			scaytOptions: {
+				label : editor.lang.scayt.btn_options,
+				group : menuGroup,
+				command: 'scaytOptions'
+			},
+			scaytLangs: {
+				label : editor.lang.scayt.btn_langs,
+				group : menuGroup,
+				command: 'scaytLangs'
+			},
+			scaytDict: {
+				label : editor.lang.scayt.btn_dictionaries,
+				group : menuGroup,
+				command: 'scaytDict'
+			}
+		};
+
+		if(editor.plugins.wsc) {
+			uiMenuItems.WSC = {
+				label : editor.lang.wsc.toolbar,
+				group : menuGroup,
+				onClick: function() {
+					var inlineMode = (editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE),
+						plugin = CKEDITOR.plugins.scayt,
+						scaytInstance = editor.scayt,
+						text = inlineMode ? editor.container.getText() : editor.document.getBody().getText();
+
+					text = text.replace(/\s/g, '');
+
+					if(text) {
+						if(scaytInstance && plugin.state.scayt[editor.name] && scaytInstance.setMarkupPaused) {
+							scaytInstance.setMarkupPaused(true);
+						}
+
+						editor.lockSelection();
+						editor.execCommand('checkspell');
+					} else {
+						alert('Nothing to check!');
+					}
+				}
+			}
+		}
+
+		editor.addMenuItems(uiMenuItems);
+	},
+	bindEvents: function(editor) {
+		var self = this,
+			plugin = CKEDITOR.plugins.scayt,
+			inline_mode = (editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE);
+
+		var scaytDestroy = function() {
+			plugin.destroy(editor);
+		};
+
+		/*
+		 * Dirty fix for placeholder drag&drop
+		 * Should be fixed with next release
+		 */
+		/*
+		editor.on('drop', function(evt) {
+			var dropRange = evt.data.dropRange;
+			var b = dropRange.createBookmark(true);
+			editor.scayt.removeMarkupInSelectionNode({ selectionNode: evt.data.target.$, forceBookmark: false });
+			dropRange.moveToBookmark(b);
+
+			evt.data.dropRange = dropRange;
+			return evt;
+		}, this, null, 0); // We should be sure that we modify dropRange before CKEDITOR.plugins.clipboard calls
+		*/
+
+		var contentDomReady = function() {
+			// The event is fired when editable iframe node was reinited so we should restart our service
+			if (plugin.state.scayt[editor.name] && !editor.readOnly && !editor.scayt) {
+				plugin.createScayt(editor);
+			}
+		};
+
+		var addMarkupStateHandlers = function() {
+			var editable = editor.editable();
+
+			editable.attachListener( editable, 'focus', function( evt ) {
+				if( CKEDITOR.plugins.scayt && !editor.scayt ) {
+					setTimeout(contentDomReady, 0); // we need small timeout in order to correctly set initial 'focused' option value in SCAYT core
+				}
+
+				var pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[editor.name] && editor.scayt,
+					selectedElement, ranges, textLength, range;
+
+				if((inline_mode ? true : pluginStatus) && editor._.savedSelection) {
+					selectedElement = editor._.savedSelection.getSelectedElement();
+					ranges = !selectedElement && editor._.savedSelection.getRanges();
+
+					for(var i = 0; i < ranges.length; i++) {
+						range = ranges[i];
+						// we need to check type of node value in order to avoid error in IE when accessing 'nodeValue' property
+						if(typeof range.startContainer.$.nodeValue === 'string') {
+							textLength = range.startContainer.getText().length;
+							if(textLength < range.startOffset || textLength < range.endOffset) {
+								editor.unlockSelection(false);
+							}
+						}
+					}
+				}
+			}, this, null, -10 );	// priority "-10" is set to call SCAYT CKEDITOR.editor#unlockSelection before CKEDITOR.editor#unlockSelection call
+		};
+
+		var contentDomHandler = function() {
+			if(inline_mode) {
+
+				if (!editor.config.scayt_inlineModeImmediateMarkup) {
+					/*
+					 * Give an opportunity to CKEditor to perform all needed updates
+					 * and only after that call 'scaytDestroy' method (#72725)
+					 */
+					editor.on('blur', function () { setTimeout( scaytDestroy, 0 ); } );
+					editor.on('focus', contentDomReady);
+
+					// We need to check if editor has focus(created) right now.
+					// If editor is active - make attempt to create scayt
+					if(editor.focusManager.hasFocus) {
+						contentDomReady();
+					}
+
+				} else {
+					contentDomReady();
+				}
+
+			} else {
+				contentDomReady();
+			}
+
+			addMarkupStateHandlers();
+
+			/*
+			 * 'mousedown' handler handle widget selection (click on widget). To
+			 * fix the issue when widget#wrapper referenced to element which can
+			 * be broken after markup.
+			 */
+			var editable = editor.editable();
+			editable.attachListener(editable, 'mousedown', function( evt ) {
+				var target = evt.data.getTarget();
+				var widget = editor.widgets && editor.widgets.getByElement( target );
+				if ( widget ) {
+					widget.wrapper = target.getAscendant( function( el ) {
+						return el.hasAttribute( 'data-cke-widget-wrapper' )
+					}, true );
+				}
+			}, this, null, -10); // '-10': we need to be shure that widget#wrapper updated before any other calls
+		};
+
+		editor.on('contentDom', contentDomHandler);
+
+		editor.on('beforeCommandExec', function(ev) {
+			var scaytInstance = editor.scayt,
+				selectedLangElement = null,
+				forceBookmark = false,
+				removeMarkupInsideSelection = true;
+
+			// TODO: after switching in source mode not recreate SCAYT instance, try to just rerun markuping to don't make requests to server
+			if(ev.data.name in plugin.options.disablingCommandExec && editor.mode == 'wysiwyg') {
+				if(scaytInstance) {
+					plugin.destroy(editor);
+					editor.fire('scaytButtonState', CKEDITOR.TRISTATE_DISABLED);
+				}
+			} else if(	ev.data.name === 'bold' || ev.data.name === 'italic' || ev.data.name === 'underline' ||
+						ev.data.name === 'strike' || ev.data.name === 'subscript' || ev.data.name === 'superscript' ||
+						ev.data.name === 'enter' || ev.data.name === 'cut' || ev.data.name === 'language') {
+				if(scaytInstance) {
+					if(ev.data.name === 'cut') {
+						removeMarkupInsideSelection = false;
+						// We need to force bookmark before we remove our markup.
+						// Otherwise we will get issues with cutting text via context menu.
+						forceBookmark = true;
+					}
+
+					// We need to remove all SCAYT markup from 'lang' node before it will be deleted.
+					// We need to remove SCAYT markup from selected text before creating 'lang' node as well.
+					if(ev.data.name === 'language') {
+						selectedLangElement = editor.plugins.language.getCurrentLangElement(editor);
+						selectedLangElement = selectedLangElement && selectedLangElement.$;
+						// We need to force bookmark before we remove our markup.
+						// Otherwise we will get issues with cutting text via language plugin menu.
+						forceBookmark = true;
+					}
+
+					editor.fire('reloadMarkupScayt', {
+						removeOptions: {
+							removeInside: removeMarkupInsideSelection,
+							forceBookmark: forceBookmark,
+							selectionNode: selectedLangElement
+						},
+						timeout: 0
+					});
+				}
+			}
+		});
+
+		editor.on('beforeSetMode', function(ev) {
+			var scaytInstance;
+			// needed when we use:
+			// CKEDITOR.instances.editor_ID.setMode("source")
+			// CKEDITOR.instances.editor_ID.setMode("wysiwyg")
+			// can't be implemented in editor.on('mode', function(ev) {});
+			if (ev.data == 'source') {
+				scaytInstance = editor.scayt;
+				if(scaytInstance) {
+					plugin.destroy(editor);
+					editor.fire('scaytButtonState', CKEDITOR.TRISTATE_DISABLED);
+				}
+
+				// remove custom data from body, to prevent waste properties showing in IE8
+				if(editor.document) { //GitHub #84 : make sure that document exists(e.g. when startup mode set to 'source')
+					editor.document.getBody().removeAttribute('_jquid');
+				}
+			}
+		});
+
+		editor.on('afterCommandExec', function(ev) {
+			if(editor.mode == 'wysiwyg' && (ev.data.name == 'undo' || ev.data.name == 'redo')) {
+				setTimeout(function() {
+					var scaytInstance = editor.scayt,
+						scaytLangList = scaytInstance && scaytInstance.getScaytLangList();
+
+					/*
+					 * Checks SCAYT initialization of LangList. To prevent immediate
+					 * markup which is triggered by 'startSpellCheck' event.
+					 * E.g.: Drop into inline CKEDITOR with scayt_autoStartup = true;
+					 */
+					if (!scaytLangList || !(scaytLangList.ltr && scaytLangList.rtl)) return;
+
+					scaytInstance.fire('startSpellCheck, startGrammarCheck');
+				}, 250);
+			}
+		});
+
+		// handle readonly changes
+		editor.on('readOnly', function(ev) {
+			var scaytInstance;
+
+			if(ev) {
+				scaytInstance = editor.scayt;
+
+				if(ev.editor.readOnly === true) {
+					if(scaytInstance) {
+						scaytInstance.fire('removeMarkupInDocument', {});
+					}
+				} else {
+					if(scaytInstance) {
+						scaytInstance.fire('startSpellCheck, startGrammarCheck');
+					} else if(ev.editor.mode == 'wysiwyg' && plugin.state.scayt[ev.editor.name] === true) {
+						plugin.createScayt(editor);
+						ev.editor.fire('scaytButtonState', CKEDITOR.TRISTATE_ON);
+					}
+				}
+			}
+		});
+
+		// we need to destroy SCAYT before CK editor will be completely destroyed
+		editor.on('beforeDestroy', scaytDestroy);
+
+		//#9439 after SetData method fires contentDom event and SCAYT create additional instanse
+		// This way we should destroy SCAYT on setData event when contenteditable Iframe was re-created
+		editor.on('setData', function() {
+			scaytDestroy();
+
+			// in inline mode SetData does not fire contentDom event
+			if(editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE || editor.plugins.divarea) {
+				contentDomHandler();
+			}
+		}, this, null, 50);
+
+		/*
+		 * Main entry point to react on changes in document
+		 */
+		editor.on('reloadMarkupScayt', function(ev) {
+			var removeOptions = ev.data && ev.data.removeOptions,
+				timeout = ev.data && ev.data.timeout;
+
+			/*
+			 * Perform removeMarkupInSelectionNode and 'startSpellCheck' fire
+			 * asynchroniosly and keep CKEDITOR flow as expected
+			 */
+			setTimeout(function() {
+				var scaytInstance = editor.scayt,
+					scaytLangList = scaytInstance && scaytInstance.getScaytLangList();
+
+				/*
+				 * Checks SCAYT initialization of LangList. To prevent immediate
+				 * markup which is triggered by 'startSpellCheck' event.
+				 * E.g.: Drop into inline CKEDITOR with scayt_autoStartup = true;
+				 */
+				if (!scaytLangList || !(scaytLangList.ltr && scaytLangList.rtl)) return;
+
+				/*
+				 * CKEditor can keep \u200B character in document (with selection#selectRanges)
+				 * we need to take care about that. For this case we fire
+				 * 'keydown' [left arrow], what will trigger 'removeFillingChar' on Webkit
+				 * to cleanup the document
+				 */
+				editor.document.fire( 'keydown', new CKEDITOR.dom.event( { keyCode: 37 } ) );
+
+				/* trigger remove markup with 'startSpellCheck' */
+				scaytInstance.removeMarkupInSelectionNode(removeOptions);
+				scaytInstance.fire('startSpellCheck, startGrammarCheck');
+			}, timeout || 0 );
+		});
+
+		// Reload spell-checking for current word after insertion completed.
+		editor.on('insertElement', function() {
+			// IE bug: we need wait here to make sure that focus is returned to editor, and we can store the selection before we proceed with markup
+			editor.fire('reloadMarkupScayt', {removeOptions: {forceBookmark: true}});
+		}, this, null, 50);
+
+		editor.on('insertHtml', function() {
+			editor.fire('reloadMarkupScayt');
+		}, this, null, 50);
+
+		editor.on('insertText', function() {
+			editor.fire('reloadMarkupScayt');
+		}, this, null, 50);
+
+		// The event is listening to open necessary dialog tab
+		editor.on('scaytDialogShown', function(ev) {
+			var dialog = ev.data,
+				scaytInstance = editor.scayt;
+
+			dialog.selectPage(scaytInstance.tabToOpen);
+		});
+	},
+	parseConfig: function(editor) {
+		var plugin = CKEDITOR.plugins.scayt;
+
+		// preprocess config for backward compatibility
+		plugin.replaceOldOptionsNames(editor.config);
+
+		// Checking editor's config after initialization
+		if(typeof editor.config.scayt_autoStartup !== 'boolean') {
+			editor.config.scayt_autoStartup = false;
+		}
+		plugin.state.scayt[editor.name] = editor.config.scayt_autoStartup;
+
+		if(typeof editor.config.grayt_autoStartup !== 'boolean') {
+			editor.config.grayt_autoStartup = false;
+		}
+		if(typeof editor.config.scayt_inlineModeImmediateMarkup !== 'boolean') {
+			editor.config.scayt_inlineModeImmediateMarkup = false;
+		}
+		plugin.state.grayt[editor.name] = editor.config.grayt_autoStartup;
+
+		if(!editor.config.scayt_contextCommands) {
+			editor.config.scayt_contextCommands = 'ignore|ignoreall|add';
+		}
+
+		if(!editor.config.scayt_contextMenuItemsOrder) {
+			editor.config.scayt_contextMenuItemsOrder = 'suggest|moresuggest|control';
+		}
+
+		if(!editor.config.scayt_sLang) {
+			editor.config.scayt_sLang = 'en_US';
+		}
+
+		if(editor.config.scayt_maxSuggestions === undefined || typeof editor.config.scayt_maxSuggestions != 'number' || editor.config.scayt_maxSuggestions < 0) {
+			editor.config.scayt_maxSuggestions = 5;
+		}
+
+		if(editor.config.scayt_minWordLength === undefined || typeof editor.config.scayt_minWordLength != 'number' || editor.config.scayt_minWordLength < 1) {
+			editor.config.scayt_minWordLength = 4;
+		}
+
+		if(editor.config.scayt_customDictionaryIds === undefined || typeof editor.config.scayt_customDictionaryIds !== 'string') {
+			editor.config.scayt_customDictionaryIds = '';
+		}
+
+		if(editor.config.scayt_userDictionaryName === undefined || typeof editor.config.scayt_userDictionaryName !== 'string') {
+			editor.config.scayt_userDictionaryName = null;
+		}
+
+		if(typeof editor.config.scayt_uiTabs === 'string' && editor.config.scayt_uiTabs.split(',').length === 3) {
+			var scayt_uiTabs = [], _tempUITabs = [];
+			editor.config.scayt_uiTabs = editor.config.scayt_uiTabs.split(',');
+
+			CKEDITOR.tools.search(editor.config.scayt_uiTabs, function(value) {
+				if (Number(value) === 1 || Number(value) === 0) {
+					_tempUITabs.push(true);
+					scayt_uiTabs.push(Number(value));
+				} else {
+					_tempUITabs.push(false);
+				}
+			});
+
+			if (CKEDITOR.tools.search(_tempUITabs, false) === null) {
+				editor.config.scayt_uiTabs = scayt_uiTabs;
+			} else {
+				editor.config.scayt_uiTabs = [1,1,1];
+			}
+
+		} else {
+			editor.config.scayt_uiTabs = [1,1,1];
+		}
+
+		if(typeof editor.config.scayt_serviceProtocol != 'string') {
+			editor.config.scayt_serviceProtocol = null;
+		}
+
+		if(typeof editor.config.scayt_serviceHost != 'string') {
+			editor.config.scayt_serviceHost = null;
+		}
+
+		if(typeof editor.config.scayt_servicePort != 'string') {
+			editor.config.scayt_servicePort = null;
+		}
+
+		if(typeof editor.config.scayt_servicePath != 'string') {
+			editor.config.scayt_servicePath = null;
+		}
+
+		if(!editor.config.scayt_moreSuggestions) {
+			editor.config.scayt_moreSuggestions = 'on';
+		}
+
+		if(typeof editor.config.scayt_customerId !== 'string') {
+			editor.config.scayt_customerId = '1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';
+		}
+
+		if(typeof editor.config.scayt_srcUrl !== 'string') {
+			var protocol = document.location.protocol;
+			protocol = protocol.search(/https?:/) != -1 ? protocol : 'http:';
+
+			editor.config.scayt_srcUrl = protocol + '//svc.webspellchecker.net/spellcheck31/lf/scayt3/ckscayt/ckscayt.js';
+		}
+
+		if(typeof CKEDITOR.config.scayt_handleCheckDirty !== 'boolean') {
+			CKEDITOR.config.scayt_handleCheckDirty = true;
+		}
+
+		if(typeof CKEDITOR.config.scayt_handleUndoRedo !== 'boolean') {
+			/* set default as 'true' */
+			CKEDITOR.config.scayt_handleUndoRedo = true;
+		}
+		/* checking 'undo' plugin, if no disable SCAYT handler */
+		CKEDITOR.config.scayt_handleUndoRedo = CKEDITOR.plugins.undo ? CKEDITOR.config.scayt_handleUndoRedo : false;
+
+		if(typeof editor.config.scayt_multiLanguageMode !== 'boolean') {
+			editor.config.scayt_multiLanguageMode = false;
+		}
+
+		if(typeof editor.config.scayt_multiLanguageStyles !== 'object') {
+			editor.config.scayt_multiLanguageStyles = {};
+		}
+
+		if(editor.config.scayt_ignoreAllCapsWords && typeof editor.config.scayt_ignoreAllCapsWords !== 'boolean') {
+			editor.config.scayt_ignoreAllCapsWords = false;
+		}
+
+		if(editor.config.scayt_ignoreDomainNames && typeof editor.config.scayt_ignoreDomainNames !== 'boolean') {
+			editor.config.scayt_ignoreDomainNames = false;
+		}
+
+		if(editor.config.scayt_ignoreWordsWithMixedCases && typeof editor.config.scayt_ignoreWordsWithMixedCases !== 'boolean') {
+			editor.config.scayt_ignoreWordsWithMixedCases = false;
+		}
+
+		if(editor.config.scayt_ignoreWordsWithNumbers && typeof editor.config.scayt_ignoreWordsWithNumbers !== 'boolean') {
+			editor.config.scayt_ignoreWordsWithNumbers = false;
+		}
+
+		if( editor.config.scayt_disableOptionsStorage ) {
+			var userOptions = CKEDITOR.tools.isArray( editor.config.scayt_disableOptionsStorage ) ? editor.config.scayt_disableOptionsStorage : ( typeof editor.config.scayt_disableOptionsStorage === 'string' ) ? [ editor.config.scayt_disableOptionsStorage ] : undefined,
+				availableValue = [ 'all', 'options', 'lang', 'ignore-all-caps-words', 'ignore-domain-names', 'ignore-words-with-mixed-cases', 'ignore-words-with-numbers'],
+				valuesOption = ['lang', 'ignore-all-caps-words', 'ignore-domain-names', 'ignore-words-with-mixed-cases', 'ignore-words-with-numbers'],
+				search = CKEDITOR.tools.search,
+				indexOf = CKEDITOR.tools.indexOf;
+
+			var isValidOption = function( option ) {
+				return !!search( availableValue, option );
+			};
+
+			var makeOptionsToStorage = function( options ) {
+				var retval = [];
+
+				for (var i = 0; i < options.length; i++) {
+					var value = options[i],
+						isGroupOptionInUserOptions = !!search( options, 'options' );
+
+					if( !isValidOption( value ) || isGroupOptionInUserOptions && !!search( valuesOption, function( val ) { if( val === 'lang' ) { return false; } } ) ) {
+						return;
+					}
+
+					if( !!search( valuesOption, value ) ) {
+						valuesOption.splice( indexOf( valuesOption, value ), 1 );
+					}
+
+					if(  value === 'all' || isGroupOptionInUserOptions && !!search( options, 'lang' )) {
+						return [];
+					}
+
+					if( value === 'options' ) {
+						valuesOption = [ 'lang' ];
+					}
+				}
+
+				retval = retval.concat( valuesOption );
+
+				return retval;
+			};
+
+			editor.config.scayt_disableOptionsStorage = makeOptionsToStorage( userOptions );
+		}
+	},
+	addRule: function(editor) {
+		var plugin = CKEDITOR.plugins.scayt,
+			dataProcessor = editor.dataProcessor,
+			htmlFilter = dataProcessor && dataProcessor.htmlFilter,
+			pathFilters = editor._.elementsPath && editor._.elementsPath.filters,
+			dataFilter = dataProcessor && dataProcessor.dataFilter,
+			removeFormatFilter = editor.addRemoveFormatFilter,
+			pathFilter = function(element) {
+				var scaytInstance = editor.scayt;
+
+				if( scaytInstance && (element.hasAttribute(plugin.options.data_attribute_name) || element.hasAttribute(plugin.options.problem_grammar_data_attribute)) ) {
+					return false;
+				}
+			},
+			removeFormatFilterTemplate = function(element) {
+				var scaytInstance = editor.scayt,
+					result = true;
+
+				if( scaytInstance && (element.hasAttribute(plugin.options.data_attribute_name) || element.hasAttribute(plugin.options.problem_grammar_data_attribute)) ) {
+					result = false;
+				}
+
+				return result;
+			};
+
+		if(pathFilters) {
+			pathFilters.push(pathFilter);
+		}
+
+		if(dataFilter) {
+			var dataFilterRules = {
+				elements: {
+					span: function(element) {
+
+						var scaytState = element.hasClass(plugin.options.misspelled_word_class) && element.attributes[plugin.options.data_attribute_name],
+							graytState = element.hasClass(plugin.options.problem_grammar_class) && element.attributes[plugin.options.problem_grammar_data_attribute];
+
+						if(plugin && (scaytState || graytState)) {
+							delete element.name;
+						}
+
+						return element;
+					}
+				}
+			};
+
+			dataFilter.addRules(dataFilterRules);
+		}
+
+		if (htmlFilter) {
+			var htmlFilterRules = {
+				elements: {
+					span: function(element) {
+
+						var scaytState = element.hasClass(plugin.options.misspelled_word_class) && element.attributes[plugin.options.data_attribute_name],
+							graytState = element.hasClass(plugin.options.problem_grammar_class) && element.attributes[plugin.options.problem_grammar_data_attribute];
+
+						if(plugin && (scaytState || graytState)) {
+							delete element.name;
+						}
+
+						return element;
+					}
+				}
+			};
+
+			htmlFilter.addRules(htmlFilterRules);
+		}
+
+		if(removeFormatFilter) {
+			removeFormatFilter.call(editor, removeFormatFilterTemplate);
+		}
+	},
+	scaytMenuDefinition: function(editor) {
+		var self = this,
+			plugin = CKEDITOR.plugins.scayt,
+			scayt_instance =  editor.scayt;
+
+		return {
+			scayt: {
+				scayt_ignore: {
+					label:  scayt_instance.getLocal('btn_ignore'),
+					group : 'scayt_control',
+					order : 1,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+						scaytInstance.ignoreWord();
+					}
+				},
+				scayt_ignoreall: {
+					label : scayt_instance.getLocal('btn_ignoreAll'),
+					group : 'scayt_control',
+					order : 2,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+						scaytInstance.ignoreAllWords();
+					}
+				},
+				scayt_add: {
+					label : scayt_instance.getLocal('btn_addWord'),
+					group : 'scayt_control',
+					order : 3,
+					exec : function(editor) {
+						var scaytInstance = editor.scayt;
+
+						// @TODO: We need to add set/restore bookmark logic to 'addWordToUserDictionary' method inside dictionarymanager.
+						// Timeout is used as tmp fix for IE9, when after hitting 'Add word' menu item, document container was blurred.
+						setTimeout(function() {
+							scaytInstance.addWordToUserDictionary();
+						}, 10);
+					}
+				},
+				scayt_option: {
+					label : scayt_instance.getLocal('btn_options'),
+					group : 'scayt_control',
+					order : 4,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+
+						scaytInstance.tabToOpen = 'options';
+						editor.lockSelection();
+						editor.openDialog(self.dialogName);
+					},
+					verification: function(editor) {
+						return (editor.config.scayt_uiTabs[0] == 1) ? true : false;
+					}
+				},
+				scayt_language: {
+					label : scayt_instance.getLocal('btn_langs'),
+					group : 'scayt_control',
+					order : 5,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+
+						scaytInstance.tabToOpen = 'langs';
+						editor.lockSelection();
+						editor.openDialog(self.dialogName);
+					},
+					verification: function(editor) {
+						return (editor.config.scayt_uiTabs[1] == 1) ? true : false;
+					}
+				},
+				scayt_dictionary: {
+					label : scayt_instance.getLocal('btn_dictionaries'),
+					group : 'scayt_control',
+					order : 6,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+
+						scaytInstance.tabToOpen = 'dictionaries';
+						editor.lockSelection();
+						editor.openDialog(self.dialogName);
+					},
+					verification: function(editor) {
+						return (editor.config.scayt_uiTabs[2] == 1) ? true : false;
+					}
+				},
+				scayt_about: {
+					label : scayt_instance.getLocal('btn_about'),
+					group : 'scayt_control',
+					order : 7,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+
+						scaytInstance.tabToOpen = 'about';
+						editor.lockSelection();
+						editor.openDialog(self.dialogName);
+					}
+				}
+			},
+			grayt: {
+				grayt_problemdescription: {
+					label : 'Grammar problem description',
+					group : 'grayt_description', // look at addMenuItems method for further info
+					order : 1,
+					state : CKEDITOR.TRISTATE_DISABLED,
+					exec: function(editor) {}
+				},
+				grayt_ignore: {
+					label : scayt_instance.getLocal('btn_ignore'),
+					group : 'grayt_control',
+					order : 2,
+					exec: function(editor) {
+						var scaytInstance = editor.scayt;
+
+						scaytInstance.ignorePhrase();
+					}
+				}
+			}
+		};
+	},
+	buildSuggestionMenuItems: function(editor, suggestions, isScaytNode) {
+		var self = this,
+			itemList = {},
+			subItemList = {},
+			replaceKeyName = isScaytNode ? 'word' : 'phrase',
+			updateEventName = isScaytNode ? 'startGrammarCheck' : 'startSpellCheck',
+			plugin = CKEDITOR.plugins.scayt,
+			scayt_instance = editor.scayt;
+
+		if(suggestions.length > 0 && suggestions[0] !== 'no_any_suggestions') {
+
+			if(isScaytNode) {
+				// build SCAYT suggestions
+				for(var i = 0; i < suggestions.length; i++) {
+
+					var commandName = 'scayt_suggest_' + CKEDITOR.plugins.scayt.suggestions[i].replace(' ', '_');
+
+					editor.addCommand(commandName, self.createCommand(CKEDITOR.plugins.scayt.suggestions[i], replaceKeyName, updateEventName));
+
+					if(i < editor.config.scayt_maxSuggestions) {
+
+						// mainSuggestions
+						editor.addMenuItem(commandName, {
+							label: suggestions[i],
+							command: commandName,
+							group: 'scayt_suggest',
+							order: i + 1
+						});
+
+						itemList[commandName] = CKEDITOR.TRISTATE_OFF;
+
+					} else {
+
+						// moreSuggestions
+						editor.addMenuItem(commandName, {
+							label: suggestions[i],
+							command: commandName,
+							group: 'scayt_moresuggest',
+							order: i + 1
+						});
+
+						subItemList[commandName] = CKEDITOR.TRISTATE_OFF;
+
+						if(editor.config.scayt_moreSuggestions === 'on') {
+
+							editor.addMenuItem('scayt_moresuggest', {
+								label : scayt_instance.getLocal('btn_moreSuggestions'),
+								group : 'scayt_moresuggest',
+								order : 10,
+								getItems : function() {
+									return subItemList;
+								}
+							});
+
+							itemList['scayt_moresuggest'] = CKEDITOR.TRISTATE_OFF;
+						}
+					}
+				}
+			} else {
+				// build GRAYT suggestions
+				for(var i = 0; i < suggestions.length; i++) {
+					var commandName = 'grayt_suggest_' + CKEDITOR.plugins.scayt.suggestions[i].replace(' ', '_');
+
+					editor.addCommand(commandName, self.createCommand(CKEDITOR.plugins.scayt.suggestions[i], replaceKeyName, updateEventName));
+
+					// mainSuggestions
+					editor.addMenuItem(commandName, {
+						label: suggestions[i],
+						command: commandName,
+						group: 'grayt_suggest',
+						order: i + 1
+					});
+
+					itemList[commandName] = CKEDITOR.TRISTATE_OFF;
+				}
+			}
+		} else {
+			var noSuggestionsCommand = 'no_scayt_suggest';
+			itemList[noSuggestionsCommand] = CKEDITOR.TRISTATE_DISABLED;
+
+			editor.addCommand(noSuggestionsCommand, {
+				exec: function() {
+
+				}
+			});
+
+			editor.addMenuItem(noSuggestionsCommand, {
+				label : scayt_instance.getLocal('btn_noSuggestions') || noSuggestionsCommand,
+				command: noSuggestionsCommand,
+				group : 'scayt_suggest',
+				order : 0
+			});
+		}
+
+		return itemList;
+	},
+	menuGenerator: function(editor, selectionNode) {
+		var self = this,
+			scaytInstance = editor.scayt,
+			menuItems = this.scaytMenuDefinition(editor),
+			itemList = {},
+			allowedOption = editor.config.scayt_contextCommands.split('|'),
+			lang = selectionNode.getAttribute(scaytInstance.getLangAttribute()) || scaytInstance.getLang(),
+			word, grammarPhrase, isScaytNode, isGrammarNode, problemDescriptionText;
+
+
+		isScaytNode = scaytInstance.isScaytNode(selectionNode);
+		isGrammarNode = scaytInstance.isGraytNode(selectionNode);
+
+		if(isScaytNode) {
+			// we clicked scayt misspelling
+			// get suggestions
+			menuItems = menuItems.scayt;
+
+			word = selectionNode.getAttribute(scaytInstance.getScaytNodeAttributeName());
+
+			scaytInstance.fire('getSuggestionsList', {
+				lang: lang,
+				word: word
+			});
+
+			itemList = this.buildSuggestionMenuItems(editor, CKEDITOR.plugins.scayt.suggestions, isScaytNode);
+		} else if(isGrammarNode) {
+			// we clicked grammar problem
+			// get suggestions
+			menuItems = menuItems.grayt;
+			grammarPhrase = selectionNode.getAttribute(scaytInstance.getGraytNodeAttributeName());
+
+			// setup grammar problem description
+			problemDescriptionText = scaytInstance.getProblemDescriptionText(grammarPhrase, lang);
+			if(menuItems.grayt_problemdescription && problemDescriptionText) {
+				menuItems.grayt_problemdescription.label = problemDescriptionText;
+			}
+
+			scaytInstance.fire('getGrammarSuggestionsList', {
+				lang: lang,
+				phrase: grammarPhrase
+			});
+
+			itemList = this.buildSuggestionMenuItems(editor, CKEDITOR.plugins.scayt.suggestions, isScaytNode);
+		}
+
+		if(isScaytNode && editor.config.scayt_contextCommands == 'off') {
+			return itemList;
+		}
+
+		for(var key in menuItems) {
+			if(isScaytNode && CKEDITOR.tools.indexOf(allowedOption, key.replace('scayt_', '')) == -1 && editor.config.scayt_contextCommands != 'all') {
+				continue;
+			}
+
+			if(typeof menuItems[key].state != 'undefined') {
+				itemList[key] = menuItems[key].state;
+			} else {
+				itemList[key] = CKEDITOR.TRISTATE_OFF;
+			}
+
+			// delete item from context menu if its state isn't verified as allowed
+			if(typeof menuItems[key].verification === 'function' && !menuItems[key].verification(editor)) {
+				// itemList[key] = (menuItems[key].verification(editor)) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
+				delete itemList[key];
+			}
+
+			editor.addCommand(key, {
+				exec: menuItems[key].exec
+			});
+
+			editor.addMenuItem(key, {
+				label : editor.lang.scayt[menuItems[key].label] || menuItems[key].label,
+				command: key,
+				group : menuItems[key].group,
+				order : menuItems[key].order
+			});
+		}
+
+		return itemList;
+	},
+	createCommand: function(suggestion, replaceKeyName, updateEventName) {
+		return {
+			exec: function(editor) {
+				var scaytInstance = editor.scayt,
+					eventObject = {};
+
+				eventObject[replaceKeyName] = suggestion;
+				scaytInstance.replaceSelectionNode(eventObject);
+
+				// we need to remove grammar markup from selection node if we just performed replace action for misspelling
+				if(updateEventName === 'startGrammarCheck') {
+					scaytInstance.removeMarkupInSelectionNode({grammarOnly: true});
+				}
+				// for grayt problem replacement we need to fire 'startSpellCheck'
+				// for scayt misspelling replacement we need to fire 'startGrammarCheck'
+				scaytInstance.fire(updateEventName);
+			}
+		};
+	}
+});
+
+CKEDITOR.plugins.scayt = {
+	state: {
+		scayt: {},
+		grayt: {}
+	},
+	suggestions: [],
+	loadingHelper: {
+		loadOrder: []
+	},
+	isLoading: false,
+	options: {
+		disablingCommandExec: {
+			source: true,
+			newpage: true,
+			templates: true
+		},
+		data_attribute_name: 'data-scayt-word',
+		misspelled_word_class: 'scayt-misspell-word',
+		problem_grammar_data_attribute: 'data-grayt-phrase',
+		problem_grammar_class: 'gramm-problem'
+	},
+	backCompatibilityMap: {
+		'scayt_service_protocol': 'scayt_serviceProtocol',
+		'scayt_service_host'  : 'scayt_serviceHost',
+		'scayt_service_port'  : 'scayt_servicePort',
+		'scayt_service_path'  : 'scayt_servicePath',
+		'scayt_customerid'    : 'scayt_customerId'
+	},
+	replaceOldOptionsNames: function(config) {
+		for(var key in config) {
+			if(key in this.backCompatibilityMap) {
+				config[this.backCompatibilityMap[key]] = config[key];
+				delete config[key];
+			}
+		}
+	},
+	createScayt : function(editor) {
+		var self = this,
+			plugin = CKEDITOR.plugins.scayt;
+
+		this.loadScaytLibrary(editor, function(_editor) {
+			var textContainer = _editor.window && _editor.window.getFrame() || _editor.editable();
+
+			// Do not create SCAYT if there is no text container for usage
+			if(!textContainer) {
+				plugin.state.scayt[_editor.name] = false;
+				return;
+			}
+
+			var scaytInstanceOptions = {
+				lang 				: _editor.config.scayt_sLang,
+				container 			: textContainer.$,
+				customDictionary 	: _editor.config.scayt_customDictionaryIds,
+				userDictionaryName 	: _editor.config.scayt_userDictionaryName,
+				localization 		: _editor.langCode,
+				customer_id 		: _editor.config.scayt_customerId,
+				debug 				: _editor.config.scayt_debug,
+				data_attribute_name : self.options.data_attribute_name,
+				misspelled_word_class: self.options.misspelled_word_class,
+				problem_grammar_data_attribute: self.options.problem_grammar_data_attribute,
+				problem_grammar_class: self.options.problem_grammar_class,
+				'options-to-restore':  _editor.config.scayt_disableOptionsStorage,
+				focused 			: _editor.editable().hasFocus, // #30260 we need to set focused=true if CKEditor is focused before SCAYT initialization
+				ignoreElementsRegex : _editor.config.scayt_elementsToIgnore,
+				minWordLength 		: _editor.config.scayt_minWordLength,
+				multiLanguageMode 	: _editor.config.scayt_multiLanguageMode,
+				multiLanguageStyles	: _editor.config.scayt_multiLanguageStyles,
+				graytAutoStartup	: plugin.state.grayt[_editor.name]
+			};
+
+			if(_editor.config.scayt_serviceProtocol) {
+				scaytInstanceOptions['service_protocol'] = _editor.config.scayt_serviceProtocol;
+			}
+
+			if(_editor.config.scayt_serviceHost) {
+				scaytInstanceOptions['service_host'] = _editor.config.scayt_serviceHost;
+			}
+
+			if(_editor.config.scayt_servicePort) {
+				scaytInstanceOptions['service_port'] = _editor.config.scayt_servicePort;
+			}
+
+			if(_editor.config.scayt_servicePath) {
+				scaytInstanceOptions['service_path'] = _editor.config.scayt_servicePath;
+			}
+
+			//predefined options
+			if(typeof _editor.config.scayt_ignoreAllCapsWords === 'boolean') {
+				scaytInstanceOptions['ignore-all-caps-words'] = _editor.config.scayt_ignoreAllCapsWords;
+			}
+
+			if(typeof _editor.config.scayt_ignoreDomainNames === 'boolean') {
+				scaytInstanceOptions['ignore-domain-names'] = _editor.config.scayt_ignoreDomainNames;
+			}
+
+			if(typeof _editor.config.scayt_ignoreWordsWithMixedCases === 'boolean') {
+				scaytInstanceOptions['ignore-words-with-mixed-cases'] = _editor.config.scayt_ignoreWordsWithMixedCases;
+			}
+
+			if(typeof _editor.config.scayt_ignoreWordsWithNumbers === 'boolean') {
+				scaytInstanceOptions['ignore-words-with-numbers'] = _editor.config.scayt_ignoreWordsWithNumbers;
+			}
+
+			var scaytInstance = new SCAYT.CKSCAYT(scaytInstanceOptions, function() {
+					// success callback
+				}, function() {
+					// error callback
+				}),
+				wordsPrefix = 'word_';
+
+			scaytInstance.subscribe('suggestionListSend', function(data) {
+				// TODO: 1. Maybe store suggestions for specific editor
+				// TODO: 2. Fix issue with suggestion duplicates on on server
+				//CKEDITOR.plugins.scayt.suggestions = data.suggestionList;
+				var _wordsCollection = {},
+					_suggestionList =[];
+
+				for (var i = 0; i < data.suggestionList.length; i++) {
+					if (!_wordsCollection[wordsPrefix + data.suggestionList[i]]) {
+						_wordsCollection[wordsPrefix + data.suggestionList[i]] = data.suggestionList[i];
+						_suggestionList.push(data.suggestionList[i]);
+					}
+				}
+
+				CKEDITOR.plugins.scayt.suggestions = _suggestionList;
+			});
+
+			// if selection has changed programmatically by SCAYT we need to react appropriately
+			scaytInstance.subscribe('selectionIsChanged', function(data) {
+				var selection = _editor.getSelection();
+
+				if(selection.isLocked) {
+					_editor.lockSelection();
+				}
+			});
+
+			scaytInstance.subscribe('graytStateChanged', function(data) {
+				plugin.state.grayt[_editor.name] = data.state;
+			});
+
+			_editor.scayt = scaytInstance;
+
+			_editor.fire('scaytButtonState', _editor.readOnly ? CKEDITOR.TRISTATE_DISABLED : CKEDITOR.TRISTATE_ON);
+		});
+	},
+	destroy: function(editor) {
+		if(editor.scayt) {
+			editor.scayt.destroy();
+		}
+
+		delete editor.scayt;
+		editor.fire('scaytButtonState', CKEDITOR.TRISTATE_OFF);
+	},
+	loadScaytLibrary: function(editor, callback) {
+		var self = this,
+			date,
+			timestamp,
+			scaytUrl;
+
+		// no need to process load requests from same editor as it can cause bugs with
+		// loading ckscayt app due to subsequent calls of some events
+		// need to be before 'if' statement, because of timing issue in CKEDITOR.scriptLoader
+		// when callback executing is delayed for a few milliseconds, and scayt can be created twise
+		// on one instance
+		if(this.loadingHelper[editor.name]) return;
+
+		if(typeof window.SCAYT === 'undefined' || typeof window.SCAYT.CKSCAYT !== 'function') {
+
+			// add onLoad callbacks for editors while SCAYT is loading
+			this.loadingHelper[editor.name] = callback;
+			this.loadingHelper.loadOrder.push(editor.name);
+
+			//creating unique timestamp for SCAYT URL
+			date = new Date();
+			timestamp = date.getTime();
+			scaytUrl = editor.config.scayt_srcUrl;
+
+			//if there already implemented timstamp for scayr_srcURL use it, if not use our timestamp
+			scaytUrl = scaytUrl + (scaytUrl.indexOf('?') >= 0 ? '' : '?' + timestamp);
+
+			if (!this.loadingHelper.ckscaytLoading) {
+				CKEDITOR.scriptLoader.load(scaytUrl, function(success) {
+					var editorName;
+
+					if ( success ) {
+						CKEDITOR.fireOnce('scaytReady');
+
+						for(var i = 0; i < self.loadingHelper.loadOrder.length; i++) {
+							editorName = self.loadingHelper.loadOrder[i];
+
+							if(typeof self.loadingHelper[editorName] === 'function') {
+								self.loadingHelper[editorName](CKEDITOR.instances[editorName]);
+							}
+
+							delete self.loadingHelper[editorName];
+						}
+						self.loadingHelper.loadOrder = [];
+					}
+				});
+				this.loadingHelper.ckscaytLoading = true;
+			}
+
+
+		} else if(window.SCAYT && typeof window.SCAYT.CKSCAYT === 'function') {
+			CKEDITOR.fireOnce('scaytReady');
+
+			if(!editor.scayt) {
+				if(typeof callback === 'function') {
+					callback(editor);
+				}
+			}
+		}
+	}
+};
+
+CKEDITOR.on('dialogDefinition', function(dialogDefinitionEvent) {
+	var dialogName = dialogDefinitionEvent.data.name,
+		dialogDefinition = dialogDefinitionEvent.data.definition,
+		dialog = dialogDefinition.dialog;
+
+	if (dialogName === 'scaytDialog') {
+		dialog.on('cancel', function(cancelEvent) {
+			return false;
+		}, this, null, -1);
+	}
+
+	if ( dialogName === 'checkspell' ) {
+		dialog.on( 'cancel', function( cancelEvent ) {
+			var editor = cancelEvent.sender && cancelEvent.sender.getParentEditor(),
+				plugin = CKEDITOR.plugins.scayt,
+				scaytInstance = editor.scayt;
+
+			if ( scaytInstance && plugin.state.scayt[ editor.name ] && scaytInstance.setMarkupPaused ) {
+				scaytInstance.setMarkupPaused( false );
+			}
+
+			editor.unlockSelection();
+		}, this, null, -2 ); // we need to call cancel callback before WSC plugin
+	}
+
+	if (dialogName === 'link') {
+		dialog.on('ok', function(okEvent) {
+			var editor = okEvent.sender && okEvent.sender.getParentEditor();
+
+			if(editor) {
+				setTimeout(function() {
+					editor.fire('reloadMarkupScayt', {
+						removeOptions: {
+							removeInside: true,
+							forceBookmark: true
+						},
+						timeout: 0
+					});
+				}, 0);
+			}
+		});
+	}
+});
+
+CKEDITOR.on('scaytReady', function() {
+
+	// Override editor.checkDirty method avoid CK checkDirty functionality to fix SCAYT issues with incorrect checkDirty behavior.
+	if(CKEDITOR.config.scayt_handleCheckDirty === true) {
+		var editorCheckDirty = CKEDITOR.editor.prototype;
+
+		editorCheckDirty.checkDirty = CKEDITOR.tools.override(editorCheckDirty.checkDirty, function(org) {
+
+			return function() {
+				var retval = null,
+					pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[this.name] && this.scayt,
+					scaytInstance = this.scayt;
+
+				if(!pluginStatus) {
+					retval = org.call(this);
+				} else {
+					retval = (this.status == 'ready');
+
+					if (retval) {
+						var currentData = scaytInstance.removeMarkupFromString(this.getSnapshot()),
+							prevData = scaytInstance.removeMarkupFromString(this._.previousValue);
+
+						retval = (retval && (prevData !== currentData))
+					}
+				}
+
+				return retval;
+			};
+		});
+
+		editorCheckDirty.resetDirty = CKEDITOR.tools.override(editorCheckDirty.resetDirty, function(org) {
+			return function() {
+				var pluginStatus = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[this.name] && this.scayt,
+					scaytInstance = this.scayt;//CKEDITOR.plugins.scayt.getScayt(this);
+
+				if(!pluginStatus) {
+					org.call(this);
+				} else {
+					this._.previousValue = scaytInstance.removeMarkupFromString(this.getSnapshot());
+				}
+			};
+		});
+	}
+
+	if (CKEDITOR.config.scayt_handleUndoRedo === true) {
+		var undoImagePrototype = CKEDITOR.plugins.undo.Image.prototype;
+
+		// add backword compatibility for CKEDITOR 4.2. method equals was repleced on other method
+		var equalsContentMethodName = (typeof undoImagePrototype.equalsContent == "function") ? 'equalsContent' : 'equals';
+
+		undoImagePrototype[equalsContentMethodName] = CKEDITOR.tools.override(undoImagePrototype[equalsContentMethodName], function(org) {
+			return function(otherImage) {
+				var pluginState = CKEDITOR.plugins.scayt && CKEDITOR.plugins.scayt.state.scayt[otherImage.editor.name] && otherImage.editor.scayt,
+					scaytInstance = otherImage.editor.scayt,
+					thisContents = this.contents,
+					otherContents = otherImage.contents,
+					retval = null;
+
+				// Making the comparison based on content without SCAYT word markers.
+				if(pluginState) {
+					this.contents = scaytInstance.removeMarkupFromString(thisContents) || '';
+					otherImage.contents = scaytInstance.removeMarkupFromString(otherContents) || '';
+				}
+
+				var retval = org.apply(this, arguments);
+
+				this.contents = thisContents;
+				otherImage.contents = otherContents;
+
+				return retval;
+			};
+		});
+	}
+});
+
+/**
+ * Automatically enables SCAYT on editor startup. When set to `true`, this option turns on SCAYT automatically
+ * after loading the editor.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_autoStartup = true;
+ *
+ * @cfg {Boolean} [scayt_autoStartup=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables Grammar As You Type (GRAYT) on SCAYT startup. When set to `true`, this option turns on GRAYT automatically
+ * after SCAYT started.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.grayt_autoStartup = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [grayt_autoStartup=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables SCAYT initialization when inline CKEditor is not focused. When set to `true`, SCAYT markup is
+ * displayed in both inline editor states, focused and unfocused, so the SCAYT instance is not destroyed. 
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		 config.scayt_inlineModeImmediateMarkup = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [scayt_inlineModeImmediateMarkup=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Defines the number of SCAYT suggestions to show in the main context menu.
+ * Possible values are:
+ *
+ * * `0` (zero) &ndash; No suggestions are shown in the main context menu. All
+ *     entries will be listed in the "More Suggestions" sub-menu.
+ * * Positive number &ndash; The maximum number of suggestions to show in the context
+ *     menu. Other entries will be shown in the "More Suggestions" sub-menu.
+ * * Negative number &ndash; Five suggestions are shown in the main context menu. All other
+ *     entries will be listed in the "More Suggestions" sub-menu.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Examples:
+ *
+ *		// Display only three suggestions in the main context menu.
+ *		config.scayt_maxSuggestions = 3;
+ *
+ *		// Do not show the suggestions directly.
+ *		config.scayt_maxSuggestions = 0;
+ *
+ * @cfg {Number} [scayt_maxSuggestions=5]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Defines the minimum length of words that will be collected from the editor content for spell checking.
+ * Possible value is any positive number.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Examples:
+ *
+ *		// Set the minimum length of words that will be collected from editor text.
+ *		config.scayt_minWordLength = 5;
+ *
+ * @cfg {Number} [scayt_minWordLength=4]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the customer ID for SCAYT. Used for hosted users only. Required for migration from free
+ * to trial or paid versions.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Load SCAYT using my customer ID.
+ *		config.scayt_customerId  = 'your-encrypted-customer-id';
+ *
+ * @cfg {String} [scayt_customerId='1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables and disables the "More Suggestions" sub-menu in the context menu.
+ * Possible values are `'on'` and `'off'`.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Disables the "More Suggestions" sub-menu.
+ *		config.scayt_moreSuggestions = 'off';
+ *
+ * @cfg {String} [scayt_moreSuggestions='on']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Customizes the display of SCAYT context menu commands ("Add Word", "Ignore",
+ * "Ignore All", "Options", "Languages", "Dictionaries" and "About").
+ * This must be a string with one or more of the following
+ * words separated by a pipe character (`'|'`):
+ *
+ * * `off` &ndash; Disables all options.
+ * * `all` &ndash; Enables all options.
+ * * `ignore` &ndash; Enables the "Ignore" option.
+ * * `ignoreall` &ndash; Enables the "Ignore All" option.
+ * * `add` &ndash; Enables the "Add Word" option.
+ * * `option` &ndash; Enables the "Options" menu item.
+ * * `language` &ndash; Enables the "Languages" menu item.
+ * * `dictionary` &ndash; Enables the "Dictionaries" menu item.
+ * * `about` &ndash; Enables the "About" menu item.
+ *
+ * Please note that availability of the "Options", "Languages" and "Dictionaries" items
+ * also depends on the {@link CKEDITOR.config#scayt_uiTabs} option.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Example:
+ *
+ *		// Show only "Add Word" and "Ignore All" in the context menu.
+ *		config.scayt_contextCommands = 'add|ignoreall';
+ *
+ * @cfg {String} [scayt_contextCommands='ignore|ignoreall|add']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the default spell checking language for SCAYT. Possible values are:
+ * `'en_US'`, `'en_GB'`, `'pt_BR'`, `'da_DK'`,
+ * `'nl_NL'`, `'en_CA'`, `'fi_FI'`, `'fr_FR'`,
+ * `'fr_CA'`, `'de_DE'`, `'el_GR'`, `'it_IT'`,
+ * `'nb_NO'`, `'pt_PT'`, `'es_ES'`, `'sv_SE'`.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Sets SCAYT to German.
+ *		config.scayt_sLang = 'de_DE';
+ *
+ * @cfg {String} [scayt_sLang='en_US']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Customizes the SCAYT dialog and SCAYT toolbar menu to show particular tabs and items.
+ * This setting must contain a `1` (enabled) or `0`
+ * (disabled) value for each of the following entries, in this precise order,
+ * separated by a comma (`','`): `'Options'`, `'Languages'`, and `'Dictionary'`.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Hides the "Languages" tab.
+ *		config.scayt_uiTabs = '1,0,1';
+ *
+ * @cfg {String} [scayt_uiTabs='1,1,1']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the protocol for the WebSpellChecker service (`ssrv.cgi`) full path.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Defines the protocol for the WebSpellChecker service (ssrv.cgi) path.
+ *		config.scayt_serviceProtocol = 'https';
+ *
+ * @cfg {String} [scayt_serviceProtocol='http']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the host for the WebSpellChecker service (`ssrv.cgi`) full path.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Defines the host for the WebSpellChecker service (ssrv.cgi) path.
+ *		config.scayt_serviceHost = 'my-host';
+ *
+ * @cfg {String} [scayt_serviceHost='svc.webspellchecker.net']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the port for the WebSpellChecker service (`ssrv.cgi`) full path.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Defines the port for the WebSpellChecker service (ssrv.cgi) path.
+ *		config.scayt_servicePort = '2330';
+ *
+ * @cfg {String} [scayt_servicePort='80']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the path to the WebSpellChecker service (`ssrv.cgi`).
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		// Defines the path to the WebSpellChecker service (ssrv.cgi).
+ *		config.scayt_servicePath = 'my-path/ssrv.cgi';
+ *
+ * @cfg {String} [scayt_servicePath='spellcheck31/script/ssrv.cgi']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Sets the URL to SCAYT core. Required to switch to the licensed version of SCAYT.
+ *
+ * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=migration:hosredfreetolicensedck)
+ * for more details.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_srcUrl = "http://my-host/spellcheck/lf/scayt/scayt.js";
+ *
+ * @cfg {String} [scayt_srcUrl='//svc.webspellchecker.net/spellcheck31/lf/scayt3/ckscayt/ckscayt.js']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Links SCAYT to custom dictionaries. This is a string containing the dictionary IDs
+ * separated by commas (`','`). Available only for the licensed version.
+ *
+ * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:customdictionaries:licensed)
+ * for more details.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_customDictionaryIds = '3021,3456,3478';
+ *
+ * @cfg {String} [scayt_customDictionaryIds='']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Activates a User Dictionary in SCAYT. The user
+ * dictionary name must be used. Available only for the licensed version.
+ *
+ * Refer to [SCAYT documentation](http://wiki.webspellchecker.net/doku.php?id=installationandconfiguration:userdictionaries)
+ * for more details. 
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_userDictionaryName = 'MyDictionary';
+ *
+ * @cfg {String} [scayt_userDictionaryName='']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Defines the order of SCAYT context menu items by groups.
+ * This must be a string with one or more of the following
+ * words separated by a pipe character (`'|'`):
+ *
+ * * `suggest` &ndash; The main suggestion word list.
+ * * `moresuggest` &ndash; The "More suggestions" word list.
+ * * `control` &ndash; SCAYT commands, such as "Ignore" and "Add Word".
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Example:
+ *
+ *		config.scayt_contextMenuItemsOrder = 'moresuggest|control|suggest';
+ *
+ * @cfg {String} [scayt_contextMenuItemsOrder='suggest|moresuggest|control']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * If set to `true`, it overrides the {@link CKEDITOR.editor#checkDirty checkDirty} functionality of CKEditor
+ * to fix SCAYT issues with incorrect `checkDirty` behavior. If set to `false`,
+ * it provides better performance on big preloaded text.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_handleCheckDirty = 'false';
+ *
+ * @cfg {String} [scayt_handleCheckDirty='true']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Configures undo/redo behavior of SCAYT in CKEditor.
+ * If set to `true`, it overrides the undo/redo functionality of CKEditor
+ * to fix SCAYT issues with incorrect undo/redo behavior. If set to `false`,
+ * it provides better performance on text undo/redo.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_handleUndoRedo = 'false';
+ *
+ * @cfg {String} [scayt_handleUndoRedo='true']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables the "Ignore All-Caps Words" option by default.
+ * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be
+ * effective because option storage has a higher priority.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_ignoreAllCapsWords = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [scayt_ignoreAllCapsWords=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables the "Ignore Domain Names" option by default.
+ * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be
+ * effective because option storage has a higher priority.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_ignoreDomainNames = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [scayt_ignoreDomainNames=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables the "Ignore Words with Mixed Case" option by default.
+ * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be
+ * effective because option storage has a higher priority.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_ignoreWordsWithMixedCases = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [scayt_ignoreWordsWithMixedCases=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables the "Ignore Words with Numbers" option by default.
+ * You may need to {@link CKEDITOR.config#scayt_disableOptionsStorage disable option storing} for this setting to be
+ * effective because option storage has a higher priority.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_ignoreWordsWithNumbers = true;
+ *
+ * @since 4.5.6
+ * @cfg {Boolean} [scayt_ignoreWordsWithNumbers=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Disables storing of SCAYT options between sessions. Option storing will be turned off after a page refresh.
+ * The following settings can be used:
+ *
+ * * `'options'` &ndash; Disables storing of all SCAYT Ignore options.
+ * * `'ignore-all-caps-words'` &ndash; Disables storing of the "Ignore All-Caps Words" option.
+ * * `'ignore-domain-names'` &ndash; Disables storing of the "Ignore Domain Names" option.
+ * * `'ignore-words-with-mixed-cases'` &ndash; Disables storing of the "Ignore Words with Mixed Case" option.
+ * * `'ignore-words-with-numbers'` &ndash; Disables storing of the "Ignore Words with Numbers" option.
+ * * `'lang'` &ndash; Disables storing of the SCAYT spell check language.
+ * * `'all'` &ndash; Disables storing of all SCAYT options.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Example:
+ *
+ *		// Disabling one option.
+ *		config.scayt_disableOptionsStorage = 'all';
+ *
+ *		// Disabling several options.
+ *  	config.scayt_disableOptionsStorage = ['lang', 'ignore-domain-names', 'ignore-words-with-numbers'];
+ *
+ *
+ * @cfg {String|Array} [scayt_disableOptionsStorage = '']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Specifies the names of tags that will be skipped while spell checking. This is a string containing tag names
+ * separated by commas (`','`). Please note that the `'style'` tag would be added to specified tags list.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_elementsToIgnore = 'del,pre';
+ *
+ * @cfg {String} [scayt_elementsToIgnore='style']
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Enables multi-language support in SCAYT. If set to `true`, turns on SCAYT multi-language support after loading the editor.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ *		config.scayt_multiLanguageMode = true;
+ *
+ * @cfg {Boolean} [scayt_multiLanguageMode=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Defines additional styles for misspellings for specified languages. Styles will be applied only if
+ * the {@link CKEDITOR.config#scayt_multiLanguageMode} option is set to `true` and the [Language](http://ckeditor.com/addon/language) 
+ * plugin is included and loaded in the editor. By default, all misspellings will still be underlined with the red waveline.
+ *
+ * Read more in the [documentation](#!/guide/dev_spellcheck) and see the [SDK sample](http://sdk.ckeditor.com/samples/spellchecker.html).
+ *
+ * Example:
+ *
+ *		// Display misspellings in French language with green color and underlined with red waveline.
+ *		config.scayt_multiLanguageStyles = {
+ *			'fr': 'color: green'
+ *		};
+ *
+ *		// Display misspellings in Italian language with green color and underlined with red waveline
+ *		// and German misspellings with red color only.
+ *		config.scayt_multiLanguageStyles = {
+ *			'it': 'color: green',
+ *			'de': 'background-image: none; color: red'
+ *		};
+ *
+ * @cfg {Object} [scayt_multiLanguageStyles = {}]
+ * @member CKEDITOR.config
+ */

+ 5 - 5
app/Resources/public/assets/jquery-file-upload/.bower.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-file-upload",
-  "version": "9.12.1",
+  "version": "9.12.3",
   "title": "jQuery File Upload",
   "description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images.",
   "keywords": [
@@ -61,13 +61,13 @@
     "server",
     "test"
   ],
-  "_release": "9.12.1",
+  "_release": "9.12.3",
   "_resolution": {
     "type": "version",
-    "tag": "9.12.1",
-    "commit": "39a40c6c8dc9503c896ca2efac65b7340e439724"
+    "tag": "9.12.3",
+    "commit": "58188eea0e49512761263531352fa07f16de0f45"
   },
-  "_source": "git://github.com/blueimp/jQuery-File-Upload.git",
+  "_source": "https://github.com/blueimp/jQuery-File-Upload.git",
   "_target": "*",
   "_originalSource": "jquery-file-upload"
 }

+ 1 - 1
app/Resources/public/assets/jquery-file-upload/bower.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-file-upload",
-  "version": "9.12.1",
+  "version": "9.12.3",
   "title": "jQuery File Upload",
   "description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images.",
   "keywords": [

+ 2 - 2
app/Resources/public/assets/jquery-file-upload/js/jquery.fileupload-process.js

@@ -84,7 +84,7 @@
                         settings
                     );
                 };
-                chain = chain.pipe(func, settings.always && func);
+                chain = chain.then(func, settings.always && func);
             });
             chain
                 .done(function () {
@@ -151,7 +151,7 @@
                         };
                     opts.index = index;
                     that._processing += 1;
-                    that._processingQueue = that._processingQueue.pipe(func, func)
+                    that._processingQueue = that._processingQueue.then(func, func)
                         .always(function () {
                             that._processing -= 1;
                             if (that._processing === 0) {

+ 6 - 6
app/Resources/public/assets/jquery-file-upload/js/jquery.fileupload.js

@@ -652,7 +652,7 @@
             data.process = function (resolveFunc, rejectFunc) {
                 if (resolveFunc || rejectFunc) {
                     data._processQueue = this._processQueue =
-                        (this._processQueue || getPromise([this])).pipe(
+                        (this._processQueue || getPromise([this])).then(
                             function () {
                                 if (data.errorThrown) {
                                     return $.Deferred()
@@ -660,7 +660,7 @@
                                 }
                                 return getPromise(arguments);
                             }
-                        ).pipe(resolveFunc, rejectFunc);
+                        ).then(resolveFunc, rejectFunc);
                 }
                 return this._processQueue || getPromise([this]);
             };
@@ -945,9 +945,9 @@
                 if (this.options.limitConcurrentUploads > 1) {
                     slot = $.Deferred();
                     this._slots.push(slot);
-                    pipe = slot.pipe(send);
+                    pipe = slot.then(send);
                 } else {
-                    this._sequence = this._sequence.pipe(send, send);
+                    this._sequence = this._sequence.then(send, send);
                     pipe = this._sequence;
                 }
                 // Return the piped Promise object, enhanced with an abort method,
@@ -1139,7 +1139,7 @@
                 $.map(entries, function (entry) {
                     return that._handleFileTreeEntry(entry, path);
                 })
-            ).pipe(function () {
+            ).then(function () {
                 return Array.prototype.concat.apply(
                     [],
                     arguments
@@ -1208,7 +1208,7 @@
             return $.when.apply(
                 $,
                 $.map(fileInput, this._getSingleFileInputFiles)
-            ).pipe(function () {
+            ).then(function () {
                 return Array.prototype.concat.apply(
                     [],
                     arguments

+ 5 - 5
app/Resources/public/assets/mediaelement/.bower.json

@@ -23,14 +23,14 @@
     "./build/mediaelement-and-player.js",
     "./build/mediaelementplayer.css"
   ],
-  "version": "2.20.1",
-  "_release": "2.20.1",
+  "version": "2.21.1",
+  "_release": "2.21.1",
   "_resolution": {
     "type": "version",
-    "tag": "2.20.1",
-    "commit": "8d4c5ece59d93f9526f9affecb2eda982ba2e3ad"
+    "tag": "2.21.1",
+    "commit": "701dfeac106ae8373e4d14819f8b8bbf22c52f43"
   },
-  "_source": "git://github.com/johndyer/mediaelement.git",
+  "_source": "https://github.com/johndyer/mediaelement.git",
   "_target": "2.*",
   "_originalSource": "mediaelement"
 }

BIN
app/Resources/public/assets/mediaelement/build/flashmediaelement-cdn.swf


BIN
app/Resources/public/assets/mediaelement/build/flashmediaelement-debug.swf


BIN
app/Resources/public/assets/mediaelement/build/flashmediaelement.swf


+ 172 - 180
app/Resources/public/assets/mediaelement/build/mediaelement-and-player.js

@@ -16,7 +16,7 @@
 var mejs = mejs || {};
 
 // version number
-mejs.version = '2.20.1'; 
+mejs.version = '2.21.1'; 
 
 
 // player number (for missing, same id attr)
@@ -294,7 +294,13 @@ mejs.Utility = {
 			}
 			obj.parentNode.removeChild(obj);
 		}		
-	}
+	},
+    determineScheme: function(url) {
+        if (url && url.indexOf("://") != -1) {
+            return url.substr(0, url.indexOf("://")+3);
+        }
+        return "//"; // let user agent figure this out
+    }
 };
 
 
@@ -680,7 +686,9 @@ mejs.PluginMediaElement.prototype = {
 	pause: function () {
 		if (this.pluginApi != null) {
 			if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
-				this.pluginApi.pauseVideo();
+		        if( this.pluginApi.getPlayerState() == 1 ) {
+				    this.pluginApi.pauseVideo();
+                }
 			} else {
 				this.pluginApi.pauseMedia();
 			}			
@@ -887,89 +895,6 @@ mejs.PluginMediaElement.prototype = {
 	}
 };
 
-// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
-mejs.MediaPluginBridge = {
-
-	pluginMediaElements:{},
-	htmlMediaElements:{},
-
-	registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
-		this.pluginMediaElements[id] = pluginMediaElement;
-		this.htmlMediaElements[id] = htmlMediaElement;
-	},
-
-	unregisterPluginElement: function (id) {
-		delete this.pluginMediaElements[id];
-		delete this.htmlMediaElements[id];
-	},
-
-	// when Flash/Silverlight is ready, it calls out to this method
-	initPlugin: function (id) {
-
-		var pluginMediaElement = this.pluginMediaElements[id],
-			htmlMediaElement = this.htmlMediaElements[id];
-
-		if (pluginMediaElement) {
-			// find the javascript bridge
-			switch (pluginMediaElement.pluginType) {
-				case "flash":
-					pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
-					break;
-				case "silverlight":
-					pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
-					pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
-					break;
-			}
-	
-			if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
-				pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
-			}
-		}
-	},
-
-	// receives events from Flash/Silverlight and sends them out as HTML5 media events
-	// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
-	fireEvent: function (id, eventName, values) {
-
-		var
-			e,
-			i,
-			bufferedTime,
-			pluginMediaElement = this.pluginMediaElements[id];
-
-		if(!pluginMediaElement){
-            return;
-        }
-        
-		// fake event object to mimic real HTML media event.
-		e = {
-			type: eventName,
-			target: pluginMediaElement
-		};
-
-		// attach all values to element and event object
-		for (i in values) {
-			pluginMediaElement[i] = values[i];
-			e[i] = values[i];
-		}
-
-		// fake the newer W3C buffered TimeRange (loaded and total have been removed)
-		bufferedTime = values.bufferedTime || 0;
-
-		e.target.buffered = e.buffered = {
-			start: function(index) {
-				return 0;
-			},
-			end: function (index) {
-				return bufferedTime;
-			},
-			length: 1
-		};
-
-		pluginMediaElement.dispatchEvent(e);
-	}
-};
-
 /*
 Default options
 */
@@ -1068,6 +993,7 @@ mejs.HtmlMediaElementShim = {
 		// test for HTML5 and plugin capabilities
 		playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
 		playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
+        playback.scheme = mejs.Utility.determineScheme(playback.url);
 
 		if (playback.method == 'native') {
 			// second fix for android
@@ -1101,7 +1027,7 @@ mejs.HtmlMediaElementShim = {
 			l,
 			n,
 			type,
-			result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
+			result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio'), scheme: ''},
 			pluginName,
 			pluginVersions,
 			pluginInfo,
@@ -1396,8 +1322,7 @@ mejs.HtmlMediaElementShim = {
 
 		// register plugin
 		pluginMediaElement.success = options.success;
-		mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
-
+		
 		// add container (must be added to DOM before inserting HTML for IE)
 		container.className = 'me-plugin';
 		container.id = pluginid + '_container';
@@ -1407,44 +1332,100 @@ mejs.HtmlMediaElementShim = {
 		} else {
 				document.body.insertBefore(container, document.body.childNodes[0]);
 		}
-
-		// flash/silverlight vars
-		initVars = [
-			'id=' + pluginid,
-			'jsinitfunction=' + "mejs.MediaPluginBridge.initPlugin",
-			'jscallbackfunction=' + "mejs.MediaPluginBridge.fireEvent",
-			'isvideo=' + ((playback.isVideo) ? "true" : "false"),
-			'autoplay=' + ((autoplay) ? "true" : "false"),
-			'preload=' + preload,
-			'width=' + width,
-			'startvolume=' + options.startVolume,
-			'timerrate=' + options.timerRate,
-			'flashstreamer=' + options.flashStreamer,
-			'height=' + height,
-			'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
-
-		if (playback.url !== null) {
-			if (playback.method == 'flash') {
-				initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
-			} else {
-				initVars.push('file=' + playback.url);
+		
+		if (playback.method === 'flash' || playback.method === 'silverlight') {
+
+			// flash/silverlight vars
+			initVars = [
+				'id=' + pluginid,
+				'isvideo=' + ((playback.isVideo) ? "true" : "false"),
+				'autoplay=' + ((autoplay) ? "true" : "false"),
+				'preload=' + preload,
+				'width=' + width,
+				'startvolume=' + options.startVolume,
+				'timerrate=' + options.timerRate,
+				'flashstreamer=' + options.flashStreamer,
+				'height=' + height,
+				'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
+	
+			if (playback.url !== null) {
+				if (playback.method == 'flash') {
+					initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
+				} else {
+					initVars.push('file=' + playback.url);
+				}
 			}
+			if (options.enablePluginDebug) {
+				initVars.push('debug=true');
+			}
+			if (options.enablePluginSmoothing) {
+				initVars.push('smoothing=true');
+			}
+			if (options.enablePseudoStreaming) {
+				initVars.push('pseudostreaming=true');
+			}
+			if (controls) {
+				initVars.push('controls=true'); // shows controls in the plugin if desired
+			}
+			if (options.pluginVars) {
+				initVars = initVars.concat(options.pluginVars);
+			}		
+			
+			// call from plugin
+			window[pluginid + '_init'] = function() {
+				switch (pluginMediaElement.pluginType) {
+					case 'flash':
+						pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(pluginid);
+						break;
+					case 'silverlight':
+						pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
+						pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
+						break;
+				}
+	
+				if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
+					pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
+				}
+			}
+			
+			// event call from plugin
+			window[pluginid + '_event'] = function(eventName, values) {
+		
+				var
+					e,
+					i,
+					bufferedTime;
+		        
+				// fake event object to mimic real HTML media event.
+				e = {
+					type: eventName,
+					target: pluginMediaElement
+				};
+		
+				// attach all values to element and event object
+				for (i in values) {
+					pluginMediaElement[i] = values[i];
+					e[i] = values[i];
+				}
+		
+				// fake the newer W3C buffered TimeRange (loaded and total have been removed)
+				bufferedTime = values.bufferedTime || 0;
+		
+				e.target.buffered = e.buffered = {
+					start: function(index) {
+						return 0;
+					},
+					end: function (index) {
+						return bufferedTime;
+					},
+					length: 1
+				};
+		
+				pluginMediaElement.dispatchEvent(e);
+			}			
+			
+			
 		}
-		if (options.enablePluginDebug) {
-			initVars.push('debug=true');
-		}
-		if (options.enablePluginSmoothing) {
-			initVars.push('smoothing=true');
-		}
-		if (options.enablePseudoStreaming) {
-			initVars.push('pseudostreaming=true');
-		}
-		if (controls) {
-			initVars.push('controls=true'); // shows controls in the plugin if desired
-		}
-		if (options.pluginVars) {
-			initVars = initVars.concat(options.pluginVars);
-		}		
 
 		switch (playback.method) {
 			case 'silverlight':
@@ -1467,7 +1448,7 @@ mejs.HtmlMediaElementShim = {
 					specialIEContainer.outerHTML =
 '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
 'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
-'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
+'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date().getTime()) + '" />' +
 '<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
 '<param name="quality" value="high" />' +
 '<param name="bgcolor" value="#000000" />' +
@@ -1519,7 +1500,8 @@ mejs.HtmlMediaElementShim = {
 						pluginId: pluginid,
 						videoId: videoId,
 						height: height,
-						width: width	
+						width: width,
+                        scheme: playback.scheme
 					};				
 				
 				// favor iframe version of YouTube
@@ -1536,12 +1518,13 @@ mejs.HtmlMediaElementShim = {
 				var player_id = pluginid + "_player";
 				pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
 				
-				container.innerHTML ='<iframe src="//player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?api=1&portrait=0&byline=0&title=0&player_id=' + player_id + '" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim" id="' + player_id + '" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
+				container.innerHTML ='<iframe src="' + playback.scheme + 'player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?api=1&portrait=0&byline=0&title=0&player_id=' + player_id + '" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim" id="' + player_id + '" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
 				if (typeof($f) == 'function') { // froogaloop available
-					var player = $f(container.childNodes[0]);
+					var player = $f(container.childNodes[0]),
+						playerState = -1;
 					
 					player.addEvent('ready', function() {
-						
+		
 						player.playVideo = function() {
 							player.api( 'play' );
 						} 
@@ -1565,7 +1548,11 @@ mejs.HtmlMediaElementShim = {
 								player.api( 'setVolume', player.lastVolume );
 								delete player.lastVolume;
 							}
-						}						
+						}
+						// parity with YT player
+						player.getPlayerState = function() {
+							return playerState;
+						}			
 
 						function createEvent(player, pluginMediaElement, eventName, e) {
 							var event = {
@@ -1580,27 +1567,39 @@ mejs.HtmlMediaElementShim = {
 						}
 
 						player.addEvent('play', function() {
+							playerState = 1;
 							createEvent(player, pluginMediaElement, 'play');
 							createEvent(player, pluginMediaElement, 'playing');
 						});
 
 						player.addEvent('pause', function() {
+							playerState = 2;							
 							createEvent(player, pluginMediaElement, 'pause');
 						});
 
 						player.addEvent('finish', function() {
+							playerState = 0;							
 							createEvent(player, pluginMediaElement, 'ended');
 						});
 
 						player.addEvent('playProgress', function(e) {
 							createEvent(player, pluginMediaElement, 'timeupdate', e);
 						});
+						
+						player.addEvent('seek', function(e) {
+							playerState = 3;
+							createEvent(player, pluginMediaElement, 'seeked', e);
+						});	
+						
+						player.addEvent('loadProgress', function(e) {
+							playerState = 3;
+							createEvent(player, pluginMediaElement, 'progress', e);
+						});												
 
 						pluginMediaElement.pluginElement = container;
 						pluginMediaElement.pluginApi = player;
 
-						// init mejs
-						mejs.MediaPluginBridge.initPlugin(pluginid);
+						pluginMediaElement.success(pluginMediaElement, pluginMediaElement.pluginElement);						
 					});
 				}
 				else {
@@ -1612,8 +1611,6 @@ mejs.HtmlMediaElementShim = {
 		htmlMediaElement.style.display = 'none';
 		// prevent browser from autoplaying when using a plugin
 		htmlMediaElement.removeAttribute('autoplay');
-
-		// FYI: options.success will be fired by the MediaPluginBridge
 		
 		return pluginMediaElement;
 	},
@@ -1674,10 +1671,10 @@ mejs.HtmlMediaElementShim = {
 mejs.YouTubeApi = {
 	isIframeStarted: false,
 	isIframeLoaded: false,
-	loadIframeApi: function() {
+	loadIframeApi: function(yt) {
 		if (!this.isIframeStarted) {
 			var tag = document.createElement('script');
-			tag.src = "//www.youtube.com/player_api";
+			tag.src = yt.scheme + "www.youtube.com/player_api";
 			var firstScriptTag = document.getElementsByTagName('script')[0];
 			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
 			this.isIframeStarted = true;
@@ -1689,7 +1686,7 @@ mejs.YouTubeApi = {
 		if (this.isLoaded) {
 			this.createIframe(yt);
 		} else {
-			this.loadIframeApi();
+			this.loadIframeApi(yt);
 			this.iframeQueue.push(yt);
 		}
 	},
@@ -1715,7 +1712,7 @@ mejs.YouTubeApi = {
 					settings.pluginMediaElement.pluginElement = document.getElementById(settings.containerId);
 					
 					// init mejs
-					mejs.MediaPluginBridge.initPlugin(settings.pluginId);
+					pluginMediaElement.success(pluginMediaElement, pluginMediaElement.pluginElement);
 					
 					// create timer
 					setInterval(function() {
@@ -1793,7 +1790,7 @@ mejs.YouTubeApi = {
 		
 		/*
 		settings.container.innerHTML =
-			'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
+			'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + settings.scheme + 'www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
 				'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
 				'<param name="allowScriptAccess" value="sameDomain">' +
 				'<param name="wmode" value="transparent">' +
@@ -1801,13 +1798,13 @@ mejs.YouTubeApi = {
 		*/
 
 		var specialIEContainer,
-			youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
+			youtubeUrl = settings.scheme + 'www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
 			
 		if (mejs.MediaFeatures.isIE) {
 			
 			specialIEContainer = document.createElement('div');
 			settings.container.appendChild(specialIEContainer);
-			specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
+			specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="' + settings.scheme + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
 'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' +
 	'<param name="movie" value="' + youtubeUrl + '" />' +
 	'<param name="wmode" value="transparent" />' +
@@ -1834,7 +1831,8 @@ mejs.YouTubeApi = {
 		// hook up and return to MediaELementPlayer.success	
 		pluginMediaElement.pluginApi = 
 		pluginMediaElement.pluginElement = player;
-		mejs.MediaPluginBridge.initPlugin(id);
+		
+		settings.success(pluginMediaElement, pluginMediaElement.pluginElement);
 		
 		// load the youtube video
 		player.cueVideoById(settings.videoId);
@@ -2847,6 +2845,16 @@ if (typeof jQuery != 'undefined') {
 					if (duration !== this.duration) {
 						duration = this.duration;
 						mejs.Utility.calculateTimeFormat(duration, t.options, t.options.framesPerSecond || 25);
+						
+						// make sure to fill in and resize the controls (e.g., 00:00 => 01:13:15
+						if (t.updateDuration) {
+							t.updateDuration();
+						}
+						if (t.updateCurrent) {
+							t.updateCurrent();
+						}
+						t.setControlsSize();
+						
 					}
 				}, false);
 
@@ -2883,6 +2891,7 @@ if (typeof jQuery != 'undefined') {
 				//  user has to start playback directly by tapping on the iFrame.
 				if (t.media.pluginType == 'youtube' && ( mf.isiOS || mf.isAndroid ) ) {
 					t.container.find('.mejs-overlay-play').hide();
+                    t.container.find('.mejs-poster').hide();
 				}
 			}
 
@@ -3068,7 +3077,7 @@ if (typeof jQuery != 'undefined') {
 					lastControlPosition = lastControl.length ? lastControl.position() : null;
 					railWidth--;
 				}
-			} while (lastControlPosition !== null && lastControlPosition.top > 0 && railWidth > 0);
+			} while (lastControlPosition !== null && lastControlPosition.top.toFixed(2) > 0 && railWidth > 0);
 
 			t.container.trigger('controlsresize');
 		},
@@ -3246,7 +3255,8 @@ if (typeof jQuery != 'undefined') {
 
 				// listen for key presses
 				t.globalBind('keydown', function(event) {
-					player.hasFocus = $(event.target).closest('.mejs-container').length !== 0;
+					player.hasFocus = $(event.target).closest('.mejs-container').length !== 0
+						&& $(event.target).closest('.mejs-container').attr('id') === player.$media.closest('.mejs-container').attr('id');
 					return t.onkeydown(player, media, event);
 				});
 
@@ -3266,7 +3276,7 @@ if (typeof jQuery != 'undefined') {
 					for (var j = 0, jl = keyAction.keys.length; j < jl; j++) {
 						if (e.keyCode == keyAction.keys[j]) {
 							if (typeof(e.preventDefault) == "function") e.preventDefault();
-							keyAction.action(player, media, e.keyCode);
+							keyAction.action(player, media, e.keyCode, e);
 							return false;
 						}
 					}
@@ -3673,8 +3683,8 @@ if (typeof jQuery != 'undefined') {
 				});
 
 			};
-            
-            var restartPlayer = function () {
+
+				var restartPlayer = function () {
 				var now = new Date();
 				if (now - lastKeyPressTime >= 1000) {
 					media.play();
@@ -3697,20 +3707,18 @@ if (typeof jQuery != 'undefined') {
 
 				var keyCode = e.keyCode,
 					duration = media.duration,
-					seekTime = media.currentTime;
+					seekTime = media.currentTime,
+					seekForward  = player.options.defaultSeekForwardInterval(duration),
+					seekBackward = player.options.defaultSeekBackwardInterval(duration);
 
 				switch (keyCode) {
 				case 37: // left
-					seekTime -= 1;
+				case 40: // Down
+					seekTime -= seekBackward;
 					break;
 				case 39: // Right
-					seekTime += 1;
-					break;
 				case 38: // Up
-					seekTime += Math.floor(duration * 0.1);
-					break;
-				case 40: // Down
-					seekTime -= Math.floor(duration * 0.1);
+					seekTime += seekForward;
 					break;
 				case 36: // Home
 					seekTime = 0;
@@ -3718,10 +3726,8 @@ if (typeof jQuery != 'undefined') {
 				case 35: // end
 					seekTime = duration;
 					break;
-				case 10: // enter
-					media.paused ? media.play() : media.pause();
-					return;
-				case 13: // space
+				case 32: // space
+				case 13: // enter
 					media.paused ? media.play() : media.pause();
 					return;
 				default:
@@ -4130,7 +4136,7 @@ if (typeof jQuery != 'undefined') {
                 var volume = Math.floor(media.volume*100);
 
 				volumeSlider.attr({
-					'aria-label': mejs.i18n.t('volumeSlider'),
+					'aria-label': mejs.i18n.t('Volume Slider'),
 					'aria-valuemin': 0,
 					'aria-valuemax': 100,
 					'aria-valuenow': volume,
@@ -4167,10 +4173,10 @@ if (typeof jQuery != 'undefined') {
 					var volume = media.volume;
 					switch (keyCode) {
                         case 38: // Up
-                            volume += 0.1;
+                            volume = Math.min(volume + 0.1, 1);
                             break;
                         case 40: // Down
-                            volume = volume - 0.1;
+                            volume = Math.max(0, volume - 0.1);
                             break;
                         default:
                             return true;
@@ -4567,24 +4573,10 @@ if (typeof jQuery != 'undefined') {
 					setTimeout(function checkFullscreen() {
 
 						if (t.isNativeFullScreen) {
-							var zoomMultiplier = window["devicePixelRatio"] || 1,
-							// Use a percent error margin since devicePixelRatio is a float and not exact.
-								percentErrorMargin = 0.002, // 0.2%
-								windowWidth = zoomMultiplier * $(window).width(),
+							var percentErrorMargin = 0.002, // 0.2%
+								windowWidth = $(window).width(),
 								screenWidth = screen.width,
-								// ** 13twelve
-								// Screen width is sort of useless: http://www.quirksmode.org/blog/archives/2013/11/screenwidth_is.html
-								// My rMBP ignores devicePixelRatio when returning the values, so fullscreen would always fail the "suddenly not fullscreen" test
-								// Theory: the gap between reported values should give us an indication of browser behavior with screen.width and devicePixelRatio
-								zoomedWindowWidth = zoomMultiplier * windowWidth;
-								
-							if (Math.abs(screenWidth-windowWidth) > Math.abs(screenWidth-zoomedWindowWidth)) {
-								// screen.width is likely true pixels, not CSS pixels, so we need to use the zoomed window width for comparison
-								windowWidth = zoomedWindowWidth;
-							}
-							// ** / 13twelve
-
-							var absDiff = Math.abs(screenWidth - windowWidth),
+								absDiff = Math.abs(screenWidth - windowWidth),
 								marginError = screenWidth * percentErrorMargin;
 
 							// check if the video is suddenly not really fullscreen

File diff suppressed because it is too large
+ 0 - 0
app/Resources/public/assets/mediaelement/build/mediaelement-and-player.min.js


+ 141 - 143
app/Resources/public/assets/mediaelement/build/mediaelement.js

@@ -16,7 +16,7 @@
 var mejs = mejs || {};
 
 // version number
-mejs.version = '2.20.1'; 
+mejs.version = '2.21.1'; 
 
 
 // player number (for missing, same id attr)
@@ -294,7 +294,13 @@ mejs.Utility = {
 			}
 			obj.parentNode.removeChild(obj);
 		}		
-	}
+	},
+    determineScheme: function(url) {
+        if (url && url.indexOf("://") != -1) {
+            return url.substr(0, url.indexOf("://")+3);
+        }
+        return "//"; // let user agent figure this out
+    }
 };
 
 
@@ -680,7 +686,9 @@ mejs.PluginMediaElement.prototype = {
 	pause: function () {
 		if (this.pluginApi != null) {
 			if (this.pluginType == 'youtube' || this.pluginType == 'vimeo') {
-				this.pluginApi.pauseVideo();
+		        if( this.pluginApi.getPlayerState() == 1 ) {
+				    this.pluginApi.pauseVideo();
+                }
 			} else {
 				this.pluginApi.pauseMedia();
 			}			
@@ -887,89 +895,6 @@ mejs.PluginMediaElement.prototype = {
 	}
 };
 
-// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
-mejs.MediaPluginBridge = {
-
-	pluginMediaElements:{},
-	htmlMediaElements:{},
-
-	registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
-		this.pluginMediaElements[id] = pluginMediaElement;
-		this.htmlMediaElements[id] = htmlMediaElement;
-	},
-
-	unregisterPluginElement: function (id) {
-		delete this.pluginMediaElements[id];
-		delete this.htmlMediaElements[id];
-	},
-
-	// when Flash/Silverlight is ready, it calls out to this method
-	initPlugin: function (id) {
-
-		var pluginMediaElement = this.pluginMediaElements[id],
-			htmlMediaElement = this.htmlMediaElements[id];
-
-		if (pluginMediaElement) {
-			// find the javascript bridge
-			switch (pluginMediaElement.pluginType) {
-				case "flash":
-					pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
-					break;
-				case "silverlight":
-					pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
-					pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
-					break;
-			}
-	
-			if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
-				pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
-			}
-		}
-	},
-
-	// receives events from Flash/Silverlight and sends them out as HTML5 media events
-	// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
-	fireEvent: function (id, eventName, values) {
-
-		var
-			e,
-			i,
-			bufferedTime,
-			pluginMediaElement = this.pluginMediaElements[id];
-
-		if(!pluginMediaElement){
-            return;
-        }
-        
-		// fake event object to mimic real HTML media event.
-		e = {
-			type: eventName,
-			target: pluginMediaElement
-		};
-
-		// attach all values to element and event object
-		for (i in values) {
-			pluginMediaElement[i] = values[i];
-			e[i] = values[i];
-		}
-
-		// fake the newer W3C buffered TimeRange (loaded and total have been removed)
-		bufferedTime = values.bufferedTime || 0;
-
-		e.target.buffered = e.buffered = {
-			start: function(index) {
-				return 0;
-			},
-			end: function (index) {
-				return bufferedTime;
-			},
-			length: 1
-		};
-
-		pluginMediaElement.dispatchEvent(e);
-	}
-};
-
 /*
 Default options
 */
@@ -1068,6 +993,7 @@ mejs.HtmlMediaElementShim = {
 		// test for HTML5 and plugin capabilities
 		playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
 		playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
+        playback.scheme = mejs.Utility.determineScheme(playback.url);
 
 		if (playback.method == 'native') {
 			// second fix for android
@@ -1101,7 +1027,7 @@ mejs.HtmlMediaElementShim = {
 			l,
 			n,
 			type,
-			result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
+			result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio'), scheme: ''},
 			pluginName,
 			pluginVersions,
 			pluginInfo,
@@ -1396,8 +1322,7 @@ mejs.HtmlMediaElementShim = {
 
 		// register plugin
 		pluginMediaElement.success = options.success;
-		mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
-
+		
 		// add container (must be added to DOM before inserting HTML for IE)
 		container.className = 'me-plugin';
 		container.id = pluginid + '_container';
@@ -1407,44 +1332,100 @@ mejs.HtmlMediaElementShim = {
 		} else {
 				document.body.insertBefore(container, document.body.childNodes[0]);
 		}
-
-		// flash/silverlight vars
-		initVars = [
-			'id=' + pluginid,
-			'jsinitfunction=' + "mejs.MediaPluginBridge.initPlugin",
-			'jscallbackfunction=' + "mejs.MediaPluginBridge.fireEvent",
-			'isvideo=' + ((playback.isVideo) ? "true" : "false"),
-			'autoplay=' + ((autoplay) ? "true" : "false"),
-			'preload=' + preload,
-			'width=' + width,
-			'startvolume=' + options.startVolume,
-			'timerrate=' + options.timerRate,
-			'flashstreamer=' + options.flashStreamer,
-			'height=' + height,
-			'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
-
-		if (playback.url !== null) {
-			if (playback.method == 'flash') {
-				initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
-			} else {
-				initVars.push('file=' + playback.url);
+		
+		if (playback.method === 'flash' || playback.method === 'silverlight') {
+
+			// flash/silverlight vars
+			initVars = [
+				'id=' + pluginid,
+				'isvideo=' + ((playback.isVideo) ? "true" : "false"),
+				'autoplay=' + ((autoplay) ? "true" : "false"),
+				'preload=' + preload,
+				'width=' + width,
+				'startvolume=' + options.startVolume,
+				'timerrate=' + options.timerRate,
+				'flashstreamer=' + options.flashStreamer,
+				'height=' + height,
+				'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
+	
+			if (playback.url !== null) {
+				if (playback.method == 'flash') {
+					initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
+				} else {
+					initVars.push('file=' + playback.url);
+				}
 			}
+			if (options.enablePluginDebug) {
+				initVars.push('debug=true');
+			}
+			if (options.enablePluginSmoothing) {
+				initVars.push('smoothing=true');
+			}
+			if (options.enablePseudoStreaming) {
+				initVars.push('pseudostreaming=true');
+			}
+			if (controls) {
+				initVars.push('controls=true'); // shows controls in the plugin if desired
+			}
+			if (options.pluginVars) {
+				initVars = initVars.concat(options.pluginVars);
+			}		
+			
+			// call from plugin
+			window[pluginid + '_init'] = function() {
+				switch (pluginMediaElement.pluginType) {
+					case 'flash':
+						pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(pluginid);
+						break;
+					case 'silverlight':
+						pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
+						pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
+						break;
+				}
+	
+				if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
+					pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
+				}
+			}
+			
+			// event call from plugin
+			window[pluginid + '_event'] = function(eventName, values) {
+		
+				var
+					e,
+					i,
+					bufferedTime;
+		        
+				// fake event object to mimic real HTML media event.
+				e = {
+					type: eventName,
+					target: pluginMediaElement
+				};
+		
+				// attach all values to element and event object
+				for (i in values) {
+					pluginMediaElement[i] = values[i];
+					e[i] = values[i];
+				}
+		
+				// fake the newer W3C buffered TimeRange (loaded and total have been removed)
+				bufferedTime = values.bufferedTime || 0;
+		
+				e.target.buffered = e.buffered = {
+					start: function(index) {
+						return 0;
+					},
+					end: function (index) {
+						return bufferedTime;
+					},
+					length: 1
+				};
+		
+				pluginMediaElement.dispatchEvent(e);
+			}			
+			
+			
 		}
-		if (options.enablePluginDebug) {
-			initVars.push('debug=true');
-		}
-		if (options.enablePluginSmoothing) {
-			initVars.push('smoothing=true');
-		}
-		if (options.enablePseudoStreaming) {
-			initVars.push('pseudostreaming=true');
-		}
-		if (controls) {
-			initVars.push('controls=true'); // shows controls in the plugin if desired
-		}
-		if (options.pluginVars) {
-			initVars = initVars.concat(options.pluginVars);
-		}		
 
 		switch (playback.method) {
 			case 'silverlight':
@@ -1467,7 +1448,7 @@ mejs.HtmlMediaElementShim = {
 					specialIEContainer.outerHTML =
 '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
 'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
-'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
+'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date().getTime()) + '" />' +
 '<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
 '<param name="quality" value="high" />' +
 '<param name="bgcolor" value="#000000" />' +
@@ -1519,7 +1500,8 @@ mejs.HtmlMediaElementShim = {
 						pluginId: pluginid,
 						videoId: videoId,
 						height: height,
-						width: width	
+						width: width,
+                        scheme: playback.scheme
 					};				
 				
 				// favor iframe version of YouTube
@@ -1536,12 +1518,13 @@ mejs.HtmlMediaElementShim = {
 				var player_id = pluginid + "_player";
 				pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
 				
-				container.innerHTML ='<iframe src="//player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?api=1&portrait=0&byline=0&title=0&player_id=' + player_id + '" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim" id="' + player_id + '" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
+				container.innerHTML ='<iframe src="' + playback.scheme + 'player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?api=1&portrait=0&byline=0&title=0&player_id=' + player_id + '" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim" id="' + player_id + '" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
 				if (typeof($f) == 'function') { // froogaloop available
-					var player = $f(container.childNodes[0]);
+					var player = $f(container.childNodes[0]),
+						playerState = -1;
 					
 					player.addEvent('ready', function() {
-						
+		
 						player.playVideo = function() {
 							player.api( 'play' );
 						} 
@@ -1565,7 +1548,11 @@ mejs.HtmlMediaElementShim = {
 								player.api( 'setVolume', player.lastVolume );
 								delete player.lastVolume;
 							}
-						}						
+						}
+						// parity with YT player
+						player.getPlayerState = function() {
+							return playerState;
+						}			
 
 						function createEvent(player, pluginMediaElement, eventName, e) {
 							var event = {
@@ -1580,27 +1567,39 @@ mejs.HtmlMediaElementShim = {
 						}
 
 						player.addEvent('play', function() {
+							playerState = 1;
 							createEvent(player, pluginMediaElement, 'play');
 							createEvent(player, pluginMediaElement, 'playing');
 						});
 
 						player.addEvent('pause', function() {
+							playerState = 2;							
 							createEvent(player, pluginMediaElement, 'pause');
 						});
 
 						player.addEvent('finish', function() {
+							playerState = 0;							
 							createEvent(player, pluginMediaElement, 'ended');
 						});
 
 						player.addEvent('playProgress', function(e) {
 							createEvent(player, pluginMediaElement, 'timeupdate', e);
 						});
+						
+						player.addEvent('seek', function(e) {
+							playerState = 3;
+							createEvent(player, pluginMediaElement, 'seeked', e);
+						});	
+						
+						player.addEvent('loadProgress', function(e) {
+							playerState = 3;
+							createEvent(player, pluginMediaElement, 'progress', e);
+						});												
 
 						pluginMediaElement.pluginElement = container;
 						pluginMediaElement.pluginApi = player;
 
-						// init mejs
-						mejs.MediaPluginBridge.initPlugin(pluginid);
+						pluginMediaElement.success(pluginMediaElement, pluginMediaElement.pluginElement);						
 					});
 				}
 				else {
@@ -1612,8 +1611,6 @@ mejs.HtmlMediaElementShim = {
 		htmlMediaElement.style.display = 'none';
 		// prevent browser from autoplaying when using a plugin
 		htmlMediaElement.removeAttribute('autoplay');
-
-		// FYI: options.success will be fired by the MediaPluginBridge
 		
 		return pluginMediaElement;
 	},
@@ -1674,10 +1671,10 @@ mejs.HtmlMediaElementShim = {
 mejs.YouTubeApi = {
 	isIframeStarted: false,
 	isIframeLoaded: false,
-	loadIframeApi: function() {
+	loadIframeApi: function(yt) {
 		if (!this.isIframeStarted) {
 			var tag = document.createElement('script');
-			tag.src = "//www.youtube.com/player_api";
+			tag.src = yt.scheme + "www.youtube.com/player_api";
 			var firstScriptTag = document.getElementsByTagName('script')[0];
 			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
 			this.isIframeStarted = true;
@@ -1689,7 +1686,7 @@ mejs.YouTubeApi = {
 		if (this.isLoaded) {
 			this.createIframe(yt);
 		} else {
-			this.loadIframeApi();
+			this.loadIframeApi(yt);
 			this.iframeQueue.push(yt);
 		}
 	},
@@ -1715,7 +1712,7 @@ mejs.YouTubeApi = {
 					settings.pluginMediaElement.pluginElement = document.getElementById(settings.containerId);
 					
 					// init mejs
-					mejs.MediaPluginBridge.initPlugin(settings.pluginId);
+					pluginMediaElement.success(pluginMediaElement, pluginMediaElement.pluginElement);
 					
 					// create timer
 					setInterval(function() {
@@ -1793,7 +1790,7 @@ mejs.YouTubeApi = {
 		
 		/*
 		settings.container.innerHTML =
-			'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
+			'<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + settings.scheme + 'www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
 				'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
 				'<param name="allowScriptAccess" value="sameDomain">' +
 				'<param name="wmode" value="transparent">' +
@@ -1801,13 +1798,13 @@ mejs.YouTubeApi = {
 		*/
 
 		var specialIEContainer,
-			youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
+			youtubeUrl = settings.scheme + 'www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId  + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
 			
 		if (mejs.MediaFeatures.isIE) {
 			
 			specialIEContainer = document.createElement('div');
 			settings.container.appendChild(specialIEContainer);
-			specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
+			specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="' + settings.scheme + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
 'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' +
 	'<param name="movie" value="' + youtubeUrl + '" />' +
 	'<param name="wmode" value="transparent" />' +
@@ -1834,7 +1831,8 @@ mejs.YouTubeApi = {
 		// hook up and return to MediaELementPlayer.success	
 		pluginMediaElement.pluginApi = 
 		pluginMediaElement.pluginElement = player;
-		mejs.MediaPluginBridge.initPlugin(id);
+		
+		settings.success(pluginMediaElement, pluginMediaElement.pluginElement);
 		
 		// load the youtube video
 		player.cueVideoById(settings.videoId);

File diff suppressed because it is too large
+ 0 - 0
app/Resources/public/assets/mediaelement/build/mediaelement.min.js


Some files were not shown because too many files changed in this diff