Newsletter - Version 3.0.0

Version Description

  • Release
Download this release

Release Info

Developer satollo
Plugin Icon 128x128 Newsletter
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.5.2.7 to 3.0.0

Files changed (195) hide show
  1. admin.css +802 -0
  2. admin.js +53 -0
  3. api/add.php +43 -0
  4. api/delete.php +13 -0
  5. api/whatis.txt +1 -0
  6. bounce/bounce.php +60 -0
  7. bounce/index.php +19 -0
  8. commons.php +0 -439
  9. config-sample.php +12 -0
  10. diagnostic.php +394 -0
  11. do.php +0 -45
  12. do/change.php +27 -0
  13. do/confirm.php +12 -0
  14. do/profile.php +14 -0
  15. do/save.php +5 -0
  16. do/subscribe-popup.php +3 -0
  17. do/subscribe.php +11 -0
  18. do/subscription-popup.php +23 -0
  19. do/subscription.php +26 -0
  20. do/unlock.php +22 -0
  21. do/unsubscribe.php +10 -0
  22. do/unsubscription.php +12 -0
  23. do/view.php +20 -0
  24. emails-edit.php +0 -242
  25. emails.php +0 -53
  26. emails/css.php +17 -0
  27. emails/edit.php +329 -0
  28. emails/emails.php +111 -0
  29. emails/index.php +117 -0
  30. emails/new.php +164 -0
  31. emails/preview-text.php +12 -0
  32. emails/preview.php +12 -0
  33. emails/themes/blank/theme-options.php +1 -0
  34. emails/themes/blank/theme-text.php +7 -0
  35. emails/themes/blank/theme.php +6 -0
  36. emails/themes/default/theme-options.php +10 -0
  37. emails/themes/default/theme-text.php +7 -0
  38. emails/themes/default/theme.php +55 -0
  39. emails/themes/linear/images/facebook.png +0 -0
  40. emails/themes/linear/images/purple.png +0 -0
  41. emails/themes/linear/images/twitter.png +0 -0
  42. emails/themes/linear/images/youtube.png +0 -0
  43. emails/themes/linear/theme-options.php +14 -0
  44. emails/themes/linear/theme.php +93 -0
  45. emails/themes/theme-1/theme-options.php +52 -0
  46. emails/themes/theme-1/theme-text.php +46 -0
  47. emails/themes/theme-1/theme.php +102 -0
  48. {themes → emails/themes}/theme-3/header.jpg +0 -0
  49. emails/themes/theme-3/theme-options.php +52 -0
  50. {themes → emails/themes}/theme-3/theme.php +57 -11
  51. emails/themes/vimeo-like/bg_header_email.gif +0 -0
  52. emails/themes/vimeo-like/theme-options.php +64 -0
  53. emails/themes/vimeo-like/theme-text.php +9 -0
  54. emails/themes/vimeo-like/theme.php +136 -0
  55. example/base.php +73 -0
  56. example/index.php +66 -0
  57. feed/whatis.txt +1 -0
  58. header.php +20 -15
  59. images/donate.png +0 -0
  60. images/facebook.png +0 -0
  61. images/popup/bg.png +0 -0
  62. images/popup/button.png +0 -0
  63. images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  64. images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  65. images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  66. images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  67. images/ui-bg_glass_75_dadada_1x400.png +0 -0
  68. images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  69. images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  70. images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  71. images/ui-icons_222222_256x240.png +0 -0
  72. images/ui-icons_2e83ff_256x240.png +0 -0
  73. images/ui-icons_454545_256x240.png +0 -0
  74. images/ui-icons_888888_256x240.png +0 -0
  75. images/ui-icons_cd0a0a_256x240.png +0 -0
  76. import.php +0 -188
  77. includes/controls.php +450 -0
  78. includes/logger.php +68 -0
  79. includes/module.php +330 -0
  80. includes/store.php +178 -0
  81. includes/themes.php +107 -0
  82. intro.php +0 -504
  83. languages/cs_CZ.php +0 -97
  84. languages/en_US.php +0 -118
  85. languages/it_IT.php +0 -72
  86. languages/pt_PT.php +0 -53
  87. log.txt +0 -1
  88. main.php +321 -356
  89. main/languages/en_US.php +17 -0
  90. options.php +0 -338
  91. plugin-activate.inc.php +0 -152
  92. plugin-export.inc.php +0 -83
  93. plugin-head.inc.php +0 -19
  94. plugin-menu.inc.php +37 -11
  95. plugin.php +743 -610
  96. profile.php +0 -202
  97. readme.txt +130 -107
  98. statistics/1x1.gif +0 -0
  99. statistics/index.php +54 -0
  100. statistics/link.php +15 -0
  101. statistics/open.php +17 -0
  102. statistics/statistics.php +110 -0
  103. statistics/view.php +32 -0
  104. style.css +0 -128
  105. subscription/email-alternative.php +15 -0
  106. subscription/email.php +41 -0
  107. subscription/forms.php +57 -0
  108. {languages → subscription/languages}/de_DE.php +9 -19
  109. subscription/languages/en_US.php +71 -0
  110. {languages → subscription/languages}/es_ES.php +12 -21
  111. {languages → subscription/languages}/fr_FR.php +15 -23
  112. subscription/languages/it_IT.php +42 -0
  113. {languages → subscription/languages}/nl_NL.php +11 -19
  114. {languages → subscription/languages}/pl_PL.php +9 -19
  115. {languages → subscription/languages}/pt_BR.php +9 -16
  116. {languages → subscription/languages}/ru_RU.php +10 -18
  117. subscription/menu.inc.php +7 -0
  118. subscription/options.php +443 -0
  119. subscription/page-alternative.php +54 -0
  120. subscription/page-popup.php +77 -0
  121. subscription/page.php +77 -0
  122. subscription/profile.php +239 -0
  123. subscription/styles/gray.css +34 -0
  124. subscription/styles/white.css +34 -0
  125. subscription/subscription.php +848 -0
  126. themes-page/page-1/theme.php +0 -27
  127. themes/blank/theme.php +0 -1
  128. themes/empty.css +0 -1
  129. themes/theme-1/theme.php +0 -56
  130. themes/theme-2/theme-2.php +0 -120
  131. tiny_mce/langs/en.js +1 -1
  132. tiny_mce/plugins/fullscreen/editor_plugin.js +1 -1
  133. tiny_mce/plugins/fullscreen/editor_plugin_src.js +5 -5
  134. tiny_mce/plugins/inlinepopups/editor_plugin.js +1 -0
  135. tiny_mce/plugins/inlinepopups/editor_plugin_src.js +699 -0
  136. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif +0 -0
  137. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif +0 -0
  138. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif +0 -0
  139. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif +0 -0
  140. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif +0 -0
  141. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif +0 -0
  142. tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif +0 -0
  143. tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css +90 -0
  144. tiny_mce/plugins/inlinepopups/template.htm +387 -0
  145. tiny_mce/plugins/legacyoutput/editor_plugin.js +1 -0
  146. tiny_mce/plugins/legacyoutput/editor_plugin_src.js +139 -0
  147. tiny_mce/plugins/noneditable/editor_plugin.js +1 -0
  148. tiny_mce/plugins/noneditable/editor_plugin_src.js +537 -0
  149. tiny_mce/plugins/paste/editor_plugin.js +0 -1
  150. tiny_mce/plugins/paste/editor_plugin_src.js +0 -871
  151. tiny_mce/plugins/paste/js/pastetext.js +0 -36
  152. tiny_mce/plugins/paste/js/pasteword.js +0 -51
  153. tiny_mce/plugins/paste/langs/en_dlg.js +0 -1
  154. tiny_mce/plugins/paste/pastetext.htm +0 -27
  155. tiny_mce/plugins/paste/pasteword.htm +0 -21
  156. tiny_mce/plugins/table/editor_plugin.js +1 -1
  157. tiny_mce/plugins/table/editor_plugin_src.js +84 -40
  158. tiny_mce/plugins/table/js/cell.js +2 -2
  159. tiny_mce/plugins/table/js/table.js +20 -3
  160. tiny_mce/plugins/xhtmlxtras/abbr.htm +0 -142
  161. tiny_mce/plugins/xhtmlxtras/acronym.htm +0 -142
  162. tiny_mce/plugins/xhtmlxtras/attributes.htm +0 -149
  163. tiny_mce/plugins/xhtmlxtras/cite.htm +0 -142
  164. tiny_mce/plugins/xhtmlxtras/css/attributes.css +0 -11
  165. tiny_mce/plugins/xhtmlxtras/css/popup.css +0 -9
  166. tiny_mce/plugins/xhtmlxtras/del.htm +0 -162
  167. tiny_mce/plugins/xhtmlxtras/editor_plugin.js +0 -1
  168. tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js +0 -132
  169. tiny_mce/plugins/xhtmlxtras/ins.htm +0 -162
  170. tiny_mce/plugins/xhtmlxtras/js/abbr.js +0 -28
  171. tiny_mce/plugins/xhtmlxtras/js/acronym.js +0 -28
  172. tiny_mce/plugins/xhtmlxtras/js/attributes.js +0 -111
  173. tiny_mce/plugins/xhtmlxtras/js/cite.js +0 -28
  174. tiny_mce/plugins/xhtmlxtras/js/del.js +0 -53
  175. tiny_mce/plugins/xhtmlxtras/js/element_common.js +0 -229
  176. tiny_mce/plugins/xhtmlxtras/js/ins.js +0 -53
  177. tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js +0 -1
  178. tiny_mce/themes/advanced/color_picker.htm +2 -6
  179. tiny_mce/themes/advanced/editor_template.js +1 -1
  180. tiny_mce/themes/advanced/editor_template_src.js +176 -48
  181. tiny_mce/themes/advanced/img/icons.gif +0 -0
  182. tiny_mce/themes/advanced/js/anchor.js +19 -6
  183. tiny_mce/themes/advanced/js/color_picker.js +345 -329
  184. tiny_mce/themes/advanced/js/image.js +4 -2
  185. tiny_mce/themes/advanced/js/link.js +9 -3
  186. tiny_mce/themes/advanced/js/source_editor.js +27 -5
  187. tiny_mce/themes/advanced/langs/en_dlg.js +1 -1
  188. tiny_mce/themes/advanced/skins/default/dialog.css +3 -2
  189. tiny_mce/themes/advanced/skins/default/ui.css +6 -1
  190. tiny_mce/themes/advanced/skins/highcontrast/dialog.css +4 -3
  191. tiny_mce/themes/advanced/skins/highcontrast/ui.css +5 -1
  192. tiny_mce/themes/advanced/skins/o2k7/dialog.css +3 -2
  193. tiny_mce/themes/advanced/skins/o2k7/ui.css +6 -1
  194. tiny_mce/themes/advanced/source_editor.htm +1 -1
  195. tiny_mce/tiny_mce.js +0 -1
admin.css ADDED
@@ -0,0 +1,802 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI CSS Framework 1.8.16
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Theming/API
9
+ */
10
+
11
+ /* Layout helpers
12
+ ----------------------------------*/
13
+ .ui-helper-hidden { display: none; }
14
+ .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
15
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
17
+ .ui-helper-clearfix { display: inline-block; }
18
+ /* required comment for clearfix to work in Opera \*/
19
+ * html .ui-helper-clearfix { height:1%; }
20
+ .ui-helper-clearfix { display:block; }
21
+ /* end clearfix */
22
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
23
+
24
+
25
+ /* Interaction Cues
26
+ ----------------------------------*/
27
+ .ui-state-disabled { cursor: default !important; }
28
+
29
+
30
+ /* Icons
31
+ ----------------------------------*/
32
+
33
+ /* states and images */
34
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
35
+
36
+
37
+ /* Misc visuals
38
+ ----------------------------------*/
39
+
40
+ /* Overlays */
41
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
42
+ /*
43
+ * jQuery UI Accordion 1.8.16
44
+ *
45
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
46
+ * Dual licensed under the MIT or GPL Version 2 licenses.
47
+ * http://jquery.org/license
48
+ *
49
+ * http://docs.jquery.com/UI/Accordion#theming
50
+ */
51
+ /* IE/Win - Fix animation bug - #4615 */
52
+ .ui-accordion { width: 100%; }
53
+ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
54
+ .ui-accordion .ui-accordion-li-fix { display: inline; }
55
+ .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
56
+ .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
57
+ .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
58
+ .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
59
+ .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
60
+ .ui-accordion .ui-accordion-content-active { display: block; }
61
+ /*
62
+ * jQuery UI Autocomplete 1.8.16
63
+ *
64
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
65
+ * Dual licensed under the MIT or GPL Version 2 licenses.
66
+ * http://jquery.org/license
67
+ *
68
+ * http://docs.jquery.com/UI/Autocomplete#theming
69
+ */
70
+ .ui-autocomplete { position: absolute; cursor: default; }
71
+
72
+ /* workarounds */
73
+ * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
74
+
75
+ /*
76
+ * jQuery UI Menu 1.8.16
77
+ *
78
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
79
+ * Dual licensed under the MIT or GPL Version 2 licenses.
80
+ * http://jquery.org/license
81
+ *
82
+ * http://docs.jquery.com/UI/Menu#theming
83
+ */
84
+ .ui-menu {
85
+ list-style:none;
86
+ padding: 2px;
87
+ margin: 0;
88
+ display:block;
89
+ float: left;
90
+ }
91
+ .ui-menu .ui-menu {
92
+ margin-top: -3px;
93
+ }
94
+ .ui-menu .ui-menu-item {
95
+ margin:0;
96
+ padding: 0;
97
+ zoom: 1;
98
+ float: left;
99
+ clear: left;
100
+ width: 100%;
101
+ }
102
+ .ui-menu .ui-menu-item a {
103
+ text-decoration:none;
104
+ display:block;
105
+ padding:.2em .4em;
106
+ line-height:1.5;
107
+ zoom:1;
108
+ }
109
+ .ui-menu .ui-menu-item a.ui-state-hover,
110
+ .ui-menu .ui-menu-item a.ui-state-active {
111
+ font-weight: normal;
112
+ margin: -1px;
113
+ }
114
+ /*
115
+ * jQuery UI Button 1.8.16
116
+ *
117
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
118
+ * Dual licensed under the MIT or GPL Version 2 licenses.
119
+ * http://jquery.org/license
120
+ *
121
+ * http://docs.jquery.com/UI/Button#theming
122
+ */
123
+ .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
124
+ .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
125
+ button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
126
+ .ui-button-icons-only { width: 3.4em; }
127
+ button.ui-button-icons-only { width: 3.7em; }
128
+
129
+ /*button text element */
130
+ .ui-button .ui-button-text { display: block; line-height: 1.4; }
131
+ .ui-button-text-only .ui-button-text { padding: .4em 1em; }
132
+ .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
133
+ .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
134
+ .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
135
+ .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
136
+ /* no icon support for input elements, provide padding by default */
137
+ input.ui-button { padding: .4em 1em; }
138
+
139
+ /*button icon element(s) */
140
+ .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
141
+ .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
142
+ .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
143
+ .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
144
+ .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
145
+
146
+ /*button sets*/
147
+ .ui-buttonset { margin-right: 7px; }
148
+ .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
149
+
150
+ /* workarounds */
151
+ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
152
+ /*
153
+ * jQuery UI Datepicker 1.8.16
154
+ *
155
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
156
+ * Dual licensed under the MIT or GPL Version 2 licenses.
157
+ * http://jquery.org/license
158
+ *
159
+ * http://docs.jquery.com/UI/Datepicker#theming
160
+ */
161
+ .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
162
+ .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
163
+ .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
164
+ .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
165
+ .ui-datepicker .ui-datepicker-prev { left:2px; }
166
+ .ui-datepicker .ui-datepicker-next { right:2px; }
167
+ .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
168
+ .ui-datepicker .ui-datepicker-next-hover { right:1px; }
169
+ .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
170
+ .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
171
+ .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
172
+ .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
173
+ .ui-datepicker select.ui-datepicker-month,
174
+ .ui-datepicker select.ui-datepicker-year { width: 49%;}
175
+ .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
176
+ .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
177
+ .ui-datepicker td { border: 0; padding: 1px; }
178
+ .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
179
+ .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
180
+ .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
181
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
182
+
183
+ /* with multiple calendars */
184
+ .ui-datepicker.ui-datepicker-multi { width:auto; }
185
+ .ui-datepicker-multi .ui-datepicker-group { float:left; }
186
+ .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
187
+ .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
188
+ .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
189
+ .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
190
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
191
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
192
+ .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
193
+ .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
194
+
195
+ /* RTL support */
196
+ .ui-datepicker-rtl { direction: rtl; }
197
+ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
198
+ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
199
+ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
200
+ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
201
+ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
202
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
203
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
204
+ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
205
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
206
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
207
+
208
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
209
+ .ui-datepicker-cover {
210
+ display: none; /*sorry for IE5*/
211
+ display/**/: block; /*sorry for IE5*/
212
+ position: absolute; /*must have*/
213
+ z-index: -1; /*must have*/
214
+ filter: mask(); /*must have*/
215
+ top: -4px; /*must have*/
216
+ left: -4px; /*must have*/
217
+ width: 200px; /*must have*/
218
+ height: 200px; /*must have*/
219
+ }/*
220
+ * jQuery UI Dialog 1.8.16
221
+ *
222
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
223
+ * Dual licensed under the MIT or GPL Version 2 licenses.
224
+ * http://jquery.org/license
225
+ *
226
+ * http://docs.jquery.com/UI/Dialog#theming
227
+ */
228
+ .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
229
+ .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
230
+ .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
231
+ .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
232
+ .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
233
+ .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
234
+ .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
235
+ .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
236
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
237
+ .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
238
+ .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
239
+ .ui-draggable .ui-dialog-titlebar { cursor: move; }
240
+ /*
241
+ * jQuery UI Progressbar 1.8.16
242
+ *
243
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
244
+ * Dual licensed under the MIT or GPL Version 2 licenses.
245
+ * http://jquery.org/license
246
+ *
247
+ * http://docs.jquery.com/UI/Progressbar#theming
248
+ */
249
+ .ui-progressbar { height:2em; text-align: left; }
250
+ .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/*
251
+ * jQuery UI Resizable 1.8.16
252
+ *
253
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
254
+ * Dual licensed under the MIT or GPL Version 2 licenses.
255
+ * http://jquery.org/license
256
+ *
257
+ * http://docs.jquery.com/UI/Resizable#theming
258
+ */
259
+ .ui-resizable { position: relative;}
260
+ .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
261
+ .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
262
+ .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
263
+ .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
264
+ .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
265
+ .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
266
+ .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
267
+ .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
268
+ .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
269
+ .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
270
+ * jQuery UI Selectable 1.8.16
271
+ *
272
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
273
+ * Dual licensed under the MIT or GPL Version 2 licenses.
274
+ * http://jquery.org/license
275
+ *
276
+ * http://docs.jquery.com/UI/Selectable#theming
277
+ */
278
+ .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
279
+ /*
280
+ * jQuery UI Slider 1.8.16
281
+ *
282
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
283
+ * Dual licensed under the MIT or GPL Version 2 licenses.
284
+ * http://jquery.org/license
285
+ *
286
+ * http://docs.jquery.com/UI/Slider#theming
287
+ */
288
+ .ui-slider { position: relative; text-align: left; }
289
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
290
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
291
+
292
+ .ui-slider-horizontal { height: .8em; }
293
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
294
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
295
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
296
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
297
+
298
+ .ui-slider-vertical { width: .8em; height: 100px; }
299
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
300
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
301
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
302
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }/*
303
+ * jQuery UI Tabs 1.8.16
304
+ *
305
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
306
+ * Dual licensed under the MIT or GPL Version 2 licenses.
307
+ * http://jquery.org/license
308
+ *
309
+ * http://docs.jquery.com/UI/Tabs#theming
310
+ */
311
+ .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
312
+ .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
313
+ .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
314
+ .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
315
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
316
+ .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
317
+ .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
318
+ .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
319
+ .ui-tabs .ui-tabs-hide { display: none !important; }
320
+ /*
321
+ * jQuery UI CSS Framework 1.8.16
322
+ *
323
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
324
+ * Dual licensed under the MIT or GPL Version 2 licenses.
325
+ * http://jquery.org/license
326
+ *
327
+ * http://docs.jquery.com/UI/Theming/API
328
+ *
329
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/
330
+ */
331
+
332
+
333
+ /* Component containers
334
+ ----------------------------------*/
335
+ .ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
336
+ .ui-widget .ui-widget { font-size: 1em; }
337
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
338
+ .ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
339
+ .ui-widget-content a { color: #222222/*{fcContent}*/; }
340
+ .ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
341
+ .ui-widget-header a { color: #222222/*{fcHeader}*/; }
342
+
343
+ /* Interaction states
344
+ ----------------------------------*/
345
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
346
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
347
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
348
+ .ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
349
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
350
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
351
+ .ui-widget :active { outline: none; }
352
+
353
+ /* Interaction Cues
354
+ ----------------------------------*/
355
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
356
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
357
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
358
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
359
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
360
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
361
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
362
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
363
+
364
+ /* Icons
365
+ ----------------------------------*/
366
+
367
+ /* states and images */
368
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
369
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
370
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
371
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
372
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
373
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
374
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
375
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
376
+
377
+ /* positioning */
378
+ .ui-icon-carat-1-n { background-position: 0 0; }
379
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
380
+ .ui-icon-carat-1-e { background-position: -32px 0; }
381
+ .ui-icon-carat-1-se { background-position: -48px 0; }
382
+ .ui-icon-carat-1-s { background-position: -64px 0; }
383
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
384
+ .ui-icon-carat-1-w { background-position: -96px 0; }
385
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
386
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
387
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
388
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
389
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
390
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
391
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
392
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
393
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
394
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
395
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
396
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
397
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
398
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
399
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
400
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
401
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
402
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
403
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
404
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
405
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
406
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
407
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
408
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
409
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
410
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
411
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
412
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
413
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
414
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
415
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
416
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
417
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
418
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
419
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
420
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
421
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
422
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
423
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
424
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
425
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
426
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
427
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
428
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
429
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
430
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
431
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
432
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
433
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
434
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
435
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
436
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
437
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
438
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
439
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
440
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
441
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
442
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
443
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
444
+ .ui-icon-extlink { background-position: -32px -80px; }
445
+ .ui-icon-newwin { background-position: -48px -80px; }
446
+ .ui-icon-refresh { background-position: -64px -80px; }
447
+ .ui-icon-shuffle { background-position: -80px -80px; }
448
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
449
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
450
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
451
+ .ui-icon-folder-open { background-position: -16px -96px; }
452
+ .ui-icon-document { background-position: -32px -96px; }
453
+ .ui-icon-document-b { background-position: -48px -96px; }
454
+ .ui-icon-note { background-position: -64px -96px; }
455
+ .ui-icon-mail-closed { background-position: -80px -96px; }
456
+ .ui-icon-mail-open { background-position: -96px -96px; }
457
+ .ui-icon-suitcase { background-position: -112px -96px; }
458
+ .ui-icon-comment { background-position: -128px -96px; }
459
+ .ui-icon-person { background-position: -144px -96px; }
460
+ .ui-icon-print { background-position: -160px -96px; }
461
+ .ui-icon-trash { background-position: -176px -96px; }
462
+ .ui-icon-locked { background-position: -192px -96px; }
463
+ .ui-icon-unlocked { background-position: -208px -96px; }
464
+ .ui-icon-bookmark { background-position: -224px -96px; }
465
+ .ui-icon-tag { background-position: -240px -96px; }
466
+ .ui-icon-home { background-position: 0 -112px; }
467
+ .ui-icon-flag { background-position: -16px -112px; }
468
+ .ui-icon-calendar { background-position: -32px -112px; }
469
+ .ui-icon-cart { background-position: -48px -112px; }
470
+ .ui-icon-pencil { background-position: -64px -112px; }
471
+ .ui-icon-clock { background-position: -80px -112px; }
472
+ .ui-icon-disk { background-position: -96px -112px; }
473
+ .ui-icon-calculator { background-position: -112px -112px; }
474
+ .ui-icon-zoomin { background-position: -128px -112px; }
475
+ .ui-icon-zoomout { background-position: -144px -112px; }
476
+ .ui-icon-search { background-position: -160px -112px; }
477
+ .ui-icon-wrench { background-position: -176px -112px; }
478
+ .ui-icon-gear { background-position: -192px -112px; }
479
+ .ui-icon-heart { background-position: -208px -112px; }
480
+ .ui-icon-star { background-position: -224px -112px; }
481
+ .ui-icon-link { background-position: -240px -112px; }
482
+ .ui-icon-cancel { background-position: 0 -128px; }
483
+ .ui-icon-plus { background-position: -16px -128px; }
484
+ .ui-icon-plusthick { background-position: -32px -128px; }
485
+ .ui-icon-minus { background-position: -48px -128px; }
486
+ .ui-icon-minusthick { background-position: -64px -128px; }
487
+ .ui-icon-close { background-position: -80px -128px; }
488
+ .ui-icon-closethick { background-position: -96px -128px; }
489
+ .ui-icon-key { background-position: -112px -128px; }
490
+ .ui-icon-lightbulb { background-position: -128px -128px; }
491
+ .ui-icon-scissors { background-position: -144px -128px; }
492
+ .ui-icon-clipboard { background-position: -160px -128px; }
493
+ .ui-icon-copy { background-position: -176px -128px; }
494
+ .ui-icon-contact { background-position: -192px -128px; }
495
+ .ui-icon-image { background-position: -208px -128px; }
496
+ .ui-icon-video { background-position: -224px -128px; }
497
+ .ui-icon-script { background-position: -240px -128px; }
498
+ .ui-icon-alert { background-position: 0 -144px; }
499
+ .ui-icon-info { background-position: -16px -144px; }
500
+ .ui-icon-notice { background-position: -32px -144px; }
501
+ .ui-icon-help { background-position: -48px -144px; }
502
+ .ui-icon-check { background-position: -64px -144px; }
503
+ .ui-icon-bullet { background-position: -80px -144px; }
504
+ .ui-icon-radio-off { background-position: -96px -144px; }
505
+ .ui-icon-radio-on { background-position: -112px -144px; }
506
+ .ui-icon-pin-w { background-position: -128px -144px; }
507
+ .ui-icon-pin-s { background-position: -144px -144px; }
508
+ .ui-icon-play { background-position: 0 -160px; }
509
+ .ui-icon-pause { background-position: -16px -160px; }
510
+ .ui-icon-seek-next { background-position: -32px -160px; }
511
+ .ui-icon-seek-prev { background-position: -48px -160px; }
512
+ .ui-icon-seek-end { background-position: -64px -160px; }
513
+ .ui-icon-seek-start { background-position: -80px -160px; }
514
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
515
+ .ui-icon-seek-first { background-position: -80px -160px; }
516
+ .ui-icon-stop { background-position: -96px -160px; }
517
+ .ui-icon-eject { background-position: -112px -160px; }
518
+ .ui-icon-volume-off { background-position: -128px -160px; }
519
+ .ui-icon-volume-on { background-position: -144px -160px; }
520
+ .ui-icon-power { background-position: 0 -176px; }
521
+ .ui-icon-signal-diag { background-position: -16px -176px; }
522
+ .ui-icon-signal { background-position: -32px -176px; }
523
+ .ui-icon-battery-0 { background-position: -48px -176px; }
524
+ .ui-icon-battery-1 { background-position: -64px -176px; }
525
+ .ui-icon-battery-2 { background-position: -80px -176px; }
526
+ .ui-icon-battery-3 { background-position: -96px -176px; }
527
+ .ui-icon-circle-plus { background-position: 0 -192px; }
528
+ .ui-icon-circle-minus { background-position: -16px -192px; }
529
+ .ui-icon-circle-close { background-position: -32px -192px; }
530
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
531
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
532
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
533
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
534
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
535
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
536
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
537
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
538
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
539
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
540
+ .ui-icon-circle-check { background-position: -208px -192px; }
541
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
542
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
543
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
544
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
545
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
546
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
547
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
548
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
549
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
550
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
551
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
552
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
553
+
554
+
555
+ /* Misc visuals
556
+ ----------------------------------*/
557
+
558
+ /* Corner radius */
559
+ .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
560
+ .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
561
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
562
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
563
+
564
+ /* Overlays */
565
+ .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
566
+ .ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
567
+
568
+
569
+ /* Admin header */
570
+ #newsletter-header {
571
+ text-align: left;
572
+ background-color: #f4f4f4;
573
+ padding: 5px;
574
+ padding-left: 15px;
575
+ border-radius: 3px;
576
+ text-transform: uppercase;
577
+ }
578
+
579
+ #newsletter-header a {
580
+ margin-right: 15px;
581
+ }
582
+
583
+ #newsletter-path {
584
+
585
+ }
586
+
587
+ #newsletter-nav {
588
+ margin-bottom: 15px;
589
+ }
590
+
591
+ .wrap h2 {
592
+ color: #21759B;
593
+ }
594
+
595
+ .wrap h3 {
596
+
597
+ }
598
+
599
+ .wrap h4 {
600
+ font-size: 1.1em;
601
+ font-weight: bold;
602
+ font-family: Georgia;
603
+ font-style: italic;
604
+ }
605
+
606
+ .wrap li {
607
+ margin-left: 20px;
608
+ list-style-type: disc;
609
+ }
610
+
611
+ .form-table {
612
+ xborder: 1px solid #ccc;
613
+ background-color: #fff;
614
+ border: 3px solid #ddd;
615
+ }
616
+
617
+ .form-table th {
618
+ text-align: right;
619
+ font-weight: bold;
620
+ border-right: 1px solid #ddd;
621
+ }
622
+ .form-table th small {
623
+ font-weight: normal;
624
+ }
625
+
626
+ .widefat th {
627
+ text-align: left;
628
+ }
629
+
630
+
631
+ p.submit {
632
+ margin-top: 5px;
633
+ padding: 5px;
634
+ }
635
+
636
+ .bordered-table {
637
+ border-collapse: collapse;
638
+ }
639
+
640
+ .bordered-table td, .bordered-table th {
641
+ border: 1px solid #ccc;
642
+ padding: 3px;
643
+ }
644
+
645
+ .newsletter-button {
646
+ font-size: 10px;
647
+ }
648
+ table.clicks td {
649
+ border: 1px solid #666;
650
+ padding: 2px;
651
+ font-size: 10px;
652
+ }
653
+
654
+ table.clicks {
655
+ border-collapse: collapse;
656
+ }
657
+
658
+ .grid {
659
+ border-collapse: collapse;
660
+ }
661
+ .grid td, .grid th {
662
+ padding: 10px;
663
+ border: 1px solid #ddd;
664
+ margin: 0;
665
+ }
666
+ .grid th {
667
+ background-color: #aaa;
668
+ }
669
+
670
+ .form-table textarea {
671
+ width: 100%;
672
+ }
673
+
674
+ .hints {
675
+ border: 1px solid #ccc;
676
+ background-color: #f7f7f7;
677
+ padding: 5px;
678
+ margin-top: 10px;
679
+ border-radius: 4px 4px;
680
+ -moz-border-radius: 4px;
681
+ -webkit-border-radius: 4px;
682
+ font-size: 11px;
683
+ color: #666;
684
+ }
685
+
686
+ .intro {
687
+ font-size: 11px;
688
+ margin: 6px 6px 8px;
689
+ }
690
+
691
+ .inside p, .inside li {
692
+ font-size: 12px;
693
+ margin: 10px;
694
+ }
695
+
696
+ .inside ul {
697
+ list-style-type: circle;
698
+ list-style-position: inside;
699
+ }
700
+
701
+ .nl-checkbox-group {
702
+ float: left;
703
+ margin-right: 5px;
704
+ border: 1px solid #ccc;
705
+ background-color: #f4f4f4;
706
+ width: 200px;
707
+ margin-bottom: 5px;
708
+ padding: 5px;
709
+ white-space: nowrap;
710
+ overflow: hidden;
711
+ }
712
+
713
+ .newsletter-preferences-item {
714
+ float: left;
715
+ margin-right: 5px;
716
+ border: 1px solid #ccc;
717
+ background-color: #f4f4f4;
718
+ width: 200px;
719
+ margin-bottom: 5px;
720
+ padding: 5px;
721
+ white-space: nowrap;
722
+ overflow: hidden;
723
+ }
724
+
725
+ .newsletter-preferences-item label {
726
+ display: inline;
727
+ }
728
+
729
+ .form-table td .nl-checkbox-group label {
730
+ display: inline;
731
+ }
732
+
733
+ #tabs .form-table {
734
+ border: 0;
735
+ font-size: 12px;
736
+ }
737
+
738
+ #tabs .form-table th {
739
+ font-size: 12px;
740
+ }
741
+
742
+ .ui-tabs .ui-tabs-nav li a {
743
+ font-size: 12px;
744
+ }
745
+
746
+
747
+
748
+ .widefat td, .widefat th {
749
+ vertical-align: middle;
750
+ }
751
+
752
+ /*
753
+ .form-table td label {
754
+ font-size: 10px;
755
+ display: block;
756
+ }
757
+ */
758
+
759
+ .newsletter-message {
760
+ background-color: lightYellow;
761
+ border-color: #E6DB55;
762
+ border-radius: 3px;
763
+ border-style: solid;
764
+ border-width: 1px;
765
+ padding: .6em;
766
+ margin-bottom: .6em;
767
+ }
768
+
769
+ .newsletter-error {
770
+ background-color: #FFEBE8;
771
+ border-color: #C00;
772
+ border-radius: 3px;
773
+ border-style: solid;
774
+ border-width: 1px;
775
+ padding: .6em;
776
+ margin-bottom: .6em;
777
+ }
778
+
779
+ #newsletter-warnings {
780
+ background-color: #FFEBE8;
781
+ border-color: #C00;
782
+ border-radius: 3px;
783
+ border-style: solid;
784
+ border-width: 1px;
785
+ padding: .6em;
786
+ margin-bottom: .6em;
787
+ }
788
+
789
+ /* Text under the panel title to explain the panel purpose. */
790
+ .preamble {
791
+ margin-bottom: 15px;
792
+ }
793
+
794
+ .preamble p {
795
+ font-size: 12px;
796
+ }
797
+
798
+ .tab-preamble p {
799
+ font-size: .9em;
800
+ color: #777;
801
+ }
802
+
admin.js ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ var tabs;
3
+ jQuery(document).ready(function(){
4
+ jQuery(function() {
5
+ tabs = jQuery("#tabs").tabs({
6
+ cookie: {
7
+ expires: 30
8
+ }
9
+ });
10
+ });
11
+ });
12
+
13
+ jQuery.cookie = function(name, value, options) {
14
+ if (typeof value != 'undefined') { // name and value given, set cookie
15
+ options = options || {};
16
+ if (value === null) {
17
+ value = '';
18
+ options.expires = -1;
19
+ }
20
+ var expires = '';
21
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
22
+ var date;
23
+ if (typeof options.expires == 'number') {
24
+ date = new Date();
25
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
26
+ } else {
27
+ date = options.expires;
28
+ }
29
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
30
+ }
31
+ // CAUTION: Needed to parenthesize options.path and options.domain
32
+ // in the following expressions, otherwise they evaluate to undefined
33
+ // in the packed version for some reason...
34
+ var path = options.path ? '; path=' + (options.path) : '';
35
+ var domain = options.domain ? '; domain=' + (options.domain) : '';
36
+ var secure = options.secure ? '; secure' : '';
37
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
38
+ } else { // only name given, get cookie
39
+ var cookieValue = null;
40
+ if (document.cookie && document.cookie != '') {
41
+ var cookies = document.cookie.split(';');
42
+ for (var i = 0; i < cookies.length; i++) {
43
+ var cookie = jQuery.trim(cookies[i]);
44
+ // Does this cookie string begin with the name we want?
45
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
46
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ return cookieValue;
52
+ }
53
+ };
api/add.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ if (!isset($newsletter)) $newsletter = new Newsletter();
6
+
7
+ $key = stripslashes($_REQUEST['nk']);
8
+ if (empty(trim($newsletter->options_main['api_key'])) || $key != $newsletter->options_main['api_key'])
9
+ die('Wrong API key');
10
+
11
+ if (!is_email($_REQUEST['ne'])) die('Wrong email');
12
+
13
+ $subscriber = array();
14
+ $subscriber['name'] = stripslashes($_REQUEST['nn']);
15
+ $subscriber['surname'] = stripslashes($_REQUEST['ns']);
16
+ $subscriber['email'] = $newsletter->normalize_email(stripslashes($_REQUEST['ne']));
17
+
18
+ if (is_array($_REQUEST['nl'])) {
19
+ foreach ($_REQUEST['nl'] as $add_list) {
20
+ $subscriber['list_' . $add_list] = 1;
21
+ }
22
+ }
23
+ else if (!empty($_REQUEST['nl'])) {
24
+ $add_lists = explode('|', $_REQUEST['nl']);
25
+ foreach ($add_lists as $add_list) {
26
+ $subscriber['list_' . $add_list] = 1;
27
+ }
28
+ }
29
+
30
+ $options_feed = get_option('newsletter_feed', array());
31
+ if ($options_feed['add_new'] == 1) $subscriber['feed'] = 1;
32
+
33
+ $options_followup = get_option('newsletter_followup', array());
34
+ if ($options_followup['add_new'] == 1) {
35
+ $subscriber['followup'] = 1;
36
+ $subscriber['followup_time'] = time() + $options_followup['interval'] * 3600;
37
+ }
38
+
39
+ $subscriber['status'] = 'C';
40
+
41
+ // TODO: add control for already subscribed emails
42
+ NewsletterUsers::instance()->save_user($subscriber);
43
+ die('ok');
api/delete.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ if (!isset($newsletter)) $newsletter = new Newsletter();
6
+
7
+ $key = stripslashes($_REQUEST['nk']);
8
+ if (empty(trim($newsletter->options['api_key'])) || $key != $newsletter->options['api_key'])
9
+ die('Wrong API key');
10
+
11
+ $email = $newsletter->normalize_email(stripslashes($_REQUEST['ne']));
12
+ $r = $wpdb->query($wpdb->prepare("delete from " . NEWSLETTER_USERS_TABLE . " where email=%s", $email));
13
+ die($r = 0 ? 'ko' : 'ok');
api/whatis.txt ADDED
@@ -0,0 +1 @@
 
1
+ This folder will contain the actual api functions as soon as they will be tranformed in a module.
bounce/bounce.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class NewsletterBounce extends NewsletterModule {
4
+
5
+ const VERSION = '1.0.0';
6
+
7
+ static $instance;
8
+
9
+ /**
10
+ * @return NewsletterBounce
11
+ */
12
+ static function instance() {
13
+ if (self::$instance == null) {
14
+ self::$instance = new NewsletterBounce();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ function __construct() {
20
+ parent::__construct('bounce', self::VERSION);
21
+ }
22
+
23
+ function upgrade() {
24
+ global $wpdb, $charset_collate;
25
+ parent::upgrade();
26
+ }
27
+
28
+ /**
29
+ * Run based on scheduled daily hour and generate, if needed, an email that will be then sent by
30
+ * Newsletter delivery engine.
31
+ *
32
+ * @global Newsletter $newsetter
33
+ */
34
+ function run($force = false) {
35
+ global $wpdb, $newsletter, $post;
36
+
37
+ if (!$force && !$this->check_transient('run', 3600)) return;
38
+
39
+ $this->save_last_run(time());
40
+ }
41
+
42
+ }
43
+
44
+ add_action('newsletter_admin_menu', 'newsletter_bounce_admin_menu');
45
+
46
+ /**
47
+ * Add menu pages for this module.
48
+ * @global Newsletter $newsletter
49
+ */
50
+ function newsletter_bounce_admin_menu() {
51
+ global $newsletter;
52
+ $newsletter->add_menu_page('bounce', 'index', 'Bounce');
53
+ }
54
+
55
+ add_action('newsletter_bounce', 'newsletter_bounce_run');
56
+
57
+ function newsletter_bounce_run() {
58
+ NewsletterBounce::instance()->run();
59
+ }
60
+
bounce/index.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $module = NewsletterBounce::instance();
4
+ $controls = new NewsletterControls();
5
+
6
+ if ($controls->is_action('save')) {
7
+ $module->save_options($controls->data);
8
+ $controls->messages = 'Saved.';
9
+ }
10
+ ?>
11
+
12
+ <div class="wrap">
13
+ <h2>Bounce (not working)</h2>
14
+ <p>
15
+ In this panel you can configure the bounce detection system. Remember the mailbox you select as trap for bounce messages
16
+ must accept all address in the form [prefix]+[something]@domain.tld.
17
+ </p>
18
+
19
+ </div>
commons.php DELETED
@@ -1,439 +0,0 @@
1
- <?php
2
-
3
- error_reporting(E_ALL ^ E_NOTICE);
4
-
5
- $newsletter->set_limits();
6
-
7
- if (!isset($newsletter_options_main['no_translation'])) {
8
- $plugin_dir = basename(dirname(__FILE__));
9
- load_plugin_textdomain('newsletter', 'wp-content/plugins/' . $plugin_dir . '/languages/');
10
- }
11
-
12
- $action = $_REQUEST['act'];
13
- $step = null;
14
- if (isset($action) && !check_admin_referer()) die('Invalid call');
15
- $errors = null;
16
- $messages = null;
17
-
18
- /**
19
- * Utility class to generate HTML form fields.
20
- */
21
- class NewsletterControls {
22
-
23
- var $data;
24
- var $action = false;
25
-
26
- function is_action($action = null) {
27
- if ($action == null) return !empty($_REQUEST['act']);
28
- if (empty($_REQUEST['act'])) return false;
29
- if ($_REQUEST['act'] != $action) return false;
30
- if (check_admin_referer ()) return true;
31
- die('Invalid call');
32
- }
33
-
34
- function errors($errors) {
35
- if (is_null($errors)) return;
36
- echo '<script type="text/javascript">';
37
- echo 'alert("' . addslashes($errors) . '");';
38
- echo '</script>';
39
- }
40
-
41
- function messages($messages) {
42
- if (is_null($messages)) return;
43
- echo '<script type="text/javascript">';
44
- echo 'alert("' . addslashes($messages) . '");';
45
- echo '</script>';
46
- }
47
-
48
- function NewsletterControls($options=null) {
49
- if ($options == null) $this->data = stripslashes_deep($_POST['options']);
50
- else $this->data = $options;
51
- }
52
-
53
- function yesno($name) {
54
- $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
55
-
56
- echo '<select style="width: 60px" name="options[' . $name . ']">';
57
- echo '<option value="0"';
58
- if ($value == 0) echo ' selected';
59
- echo '>No</option>';
60
- echo '<option value="1"';
61
- if ($value == 1) echo ' selected';
62
- echo '>Yes</option>';
63
- echo '</select>&nbsp;&nbsp;&nbsp;';
64
- }
65
-
66
- function enabled($name) {
67
- $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
68
-
69
- echo '<select style="width: 100px" name="options[' . $name . ']">';
70
- echo '<option value="0"';
71
- if ($value == 0) echo ' selected';
72
- echo '>Disabled</option>';
73
- echo '<option value="1"';
74
- if ($value == 1) echo ' selected';
75
- echo '>Enabled</option>';
76
- echo '</select>';
77
- }
78
-
79
- function select($name, $options, $first = null) {
80
- $value = $this->data[$name];
81
-
82
- echo '<select id="options-' . $name . '" name="options[' . $name . ']">';
83
- if (!empty($first)) {
84
- echo '<option value="">' . htmlspecialchars($first) . '</option>';
85
- }
86
- foreach ($options as $key => $label) {
87
- echo '<option value="' . $key . '"';
88
- if ($value == $key) echo ' selected';
89
- echo '>' . htmlspecialchars($label) . '</option>';
90
- }
91
- echo '</select>';
92
- }
93
-
94
- function select_grouped($name, $groups) {
95
- $value = $this->data[$name];
96
-
97
- echo '<select name="options[' . $name . ']">';
98
-
99
- foreach ($groups as $group) {
100
- echo '<optgroup label="' . htmlspecialchars($group['']) . '">';
101
- if (!empty($group)) {
102
- foreach ($group as $key => $label) {
103
- if ($key == '') continue;
104
- echo '<option value="' . $key . '"';
105
- if ($value == $key) echo ' selected';
106
- echo '>' . htmlspecialchars($label) . '</option>';
107
- }
108
- }
109
- echo '</optgroup>';
110
- }
111
- echo '</select>';
112
- }
113
-
114
- function page_themes($name) {
115
- $themes[''] = 'Standard page themes';
116
- $themes['page-1'] = 'Page theme 1';
117
-
118
- $this->select_grouped($name, array(
119
- array_merge(array('' => 'Custom page themes'), newsletter_page_get_themes()),
120
- $themes
121
- ));
122
- }
123
-
124
- function value($name) {
125
- echo htmlspecialchars($this->data[$name]);
126
- }
127
-
128
- function value_date($name) {
129
- $time = $this->data[$name];
130
- echo gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
131
- }
132
-
133
- function text($name, $size=20) {
134
- echo '<input name="options[' . $name . ']" type="text" size="' . $size . '" value="';
135
- echo htmlspecialchars($this->data[$name]);
136
- echo '"/>';
137
- }
138
-
139
- function hidden($name) {
140
- echo '<input name="options[' . $name . ']" type="hidden" value="';
141
- echo htmlspecialchars($this->data[$name]);
142
- echo '"/>';
143
- }
144
-
145
- function button($action, $label, $function=null) {
146
- if (!$this->action) echo '<input name="act" type="hidden" value=""/>';
147
- $this->action = true;
148
- if ($function != null) {
149
- echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.act.value=\'' . $action . '\';' . htmlspecialchars($function) . '"/>';
150
- }
151
- else {
152
- echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.act.value=\'' . $action . '\';this.form.submit()"/>';
153
- }
154
- }
155
-
156
- function button_confirm($action, $label, $message, $data='') {
157
- if (!$this->action) echo '<input name="act" type="hidden" value=""/>';
158
- $this->action = true;
159
- echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.btn.value=\'' . $data . '\';this.form.act.value=\'' . $action . '\';if (confirm(\'' .
160
- htmlspecialchars($message) . '\')) this.form.submit()"/>';
161
- }
162
-
163
- function editor($name, $rows=5, $cols=75) {
164
- echo '<textarea class="visual" name="options[' . $name . ']" style="width: 100%" wrap="off" rows="' . $rows . '" cols="' . $cols . '">';
165
- echo htmlspecialchars($this->data[$name]);
166
- echo '</textarea>';
167
- }
168
-
169
- function textarea($name, $width='100%', $height='50') {
170
- echo '<textarea class="dymanic" name="options[' . $name . ']" wrap="off" style="width:' . $width . ';height:' . $height . '">';
171
- echo htmlspecialchars($this->data[$name]);
172
- echo '</textarea>';
173
- }
174
-
175
- function textarea_fixed($name, $width='100%', $height='50') {
176
- echo '<textarea name="options[' . $name . ']" wrap="off" style="width:' . $width . ';height:' . $height . '">';
177
- echo htmlspecialchars($this->data[$name]);
178
- echo '</textarea>';
179
- }
180
-
181
- function email($prefix) {
182
- echo 'Subject:<br />';
183
- $this->text($prefix . '_subject', 70);
184
- echo '<br />Message:<br />';
185
- $this->editor($prefix . '_message');
186
- }
187
-
188
- function checkbox($name, $label='') {
189
- echo '<input type="checkbox" id="' . $name . '" name="options[' . $name . ']" value="1"';
190
- if (!empty($this->data[$name])) echo ' checked="checked"';
191
- echo '/>';
192
- if ($label != '') echo ' <label for="' . $name . '">' . $label . '</label>';
193
- }
194
-
195
- function hours($name) {
196
- $hours = array();
197
- for ($i = 0; $i < 24; $i++) {
198
- $hours['' . $i] = '' . $i;
199
- }
200
- $this->select($name, $hours);
201
- }
202
-
203
- function days($name) {
204
- $days = array(0 => 'Every day', 1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', 7 => 'Sunday');
205
- $this->select($name, $days);
206
- }
207
-
208
- function init() {
209
- echo '<script type="text/javascript">
210
- jQuery(document).ready(function(){
211
- jQuery("textarea.dynamic").focus(function() {
212
- jQuery("textarea.dynamic").css("height", "50px");
213
- jQuery(this).css("height", "400px");
214
- });
215
- });
216
- </script>
217
- ';
218
- echo '<input name="act" type="hidden" value=""/>';
219
- echo '<input name="btn" type="hidden" value=""/>';
220
- $this->action = true;
221
- wp_nonce_field();
222
- }
223
-
224
- function save($table, $data=null) {
225
- global $wpdb;
226
- if ($data == null) $data = $this->data;
227
- $keys = array_keys($data);
228
- foreach ($keys as $key) {
229
- if ($key[0] == '_') unset($data[$key]);
230
- }
231
- $id = $data['id'];
232
- unset($data['id']);
233
- if (empty($id)) {
234
- $wpdb->insert($table, $data);
235
- $id = $wpdb->insert_id;
236
- }
237
- else {
238
- $wpdb->update($table, $data, array('id' => $id));
239
- }
240
- $this->data = $wpdb->get_row("select * from " . $table . " where id=" . $id, ARRAY_A);
241
- }
242
-
243
- function load($table, $id) {
244
- global $wpdb;
245
- if ($id == 0) $this->data = array('id' => 0);
246
- else $this->data = $wpdb->get_row("select * from " . $table . " where id=" . $id, ARRAY_A);
247
- }
248
-
249
- function update($table, $field, $value, $id=null) {
250
- global $wpdb;
251
- if ($id == null) $id = $this->data['id'];
252
- $wpdb->query("update " . $table . " set " . $field . "='" . mysql_escape_string($value) . "' where id=" . $id);
253
- $this->data[$field] = $value;
254
- }
255
-
256
- }
257
-
258
- $newsletter_options_main = get_option('newsletter_main', array());
259
-
260
- function newsletter_search($text, $status='', $order='email', $list = null, $link = null) {
261
- global $wpdb;
262
-
263
- if (empty($order)) $order = 'email';
264
- if ($order == 'id') $order = 'id desc';
265
-
266
- $query = "select * from " . $wpdb->prefix . "newsletter where 1=1";
267
- if (!empty($status)) {
268
- $query .= " and status='" . $wpdb->escape($status) . "'";
269
- }
270
-
271
- if (trim($text) != '') {
272
- $query .= " and (email like '%" .
273
- $wpdb->escape($text) . "%' or name like '%" . $wpdb->escape($text) . "%')";
274
- }
275
-
276
- if (!empty($list)) {
277
- $query .= " and list_" . ((int)$list) . "=1";
278
- }
279
-
280
- if (!empty($link)) {
281
- list($newsletter, $url) = explode('|', $link);
282
- $query .= " and id in (select distinct newsletter_id from " . $wpdb->prefix . "newsletter_stats where newsletter='" .
283
- $wpdb->escape($newsletter) . "' and url='" . $wpdb->escape($url) . "')";
284
- }
285
-
286
- $query .= ' order by ' . $order;
287
-
288
- //if (empty($link)) $query .= ' limit 100';
289
-
290
- $recipients = $wpdb->get_results($query);
291
-
292
- if (!$recipients) return null;
293
- return $recipients;
294
- }
295
-
296
- function newsletter_get_test_subscribers() {
297
- global $newsletter, $wpdb;
298
- $subscribers = array();
299
- for ($i = 0; $i < 5; $i++) {
300
- if (!empty($newsletter->options_main['test_email_' . $i])) {
301
- $subscriber = new stdClass();
302
- $subscriber->name = $newsletter->options_main['test_name_' . $i];
303
- $subscriber->email = $newsletter->options_main['test_email_' . $i];
304
- $subscriber->sex = $newsletter->options_main['test_sex_' . $i];
305
- $subscriber->token = 'notokenitsatest';
306
- $subscriber->id = 0;
307
- $subscriber->feed_time = 0;
308
- $subscriber->followup_time = 0;
309
-
310
- $subscribers[] = $subscriber;
311
- }
312
- }
313
- $others = $wpdb->get_results("select * from " . $wpdb->prefix . "newsletter where test=1");
314
- if (!empty($others)) {
315
- foreach ($others as &$other) {
316
- $subscribers[] = $other;
317
- }
318
- }
319
- return $subscribers;
320
- }
321
-
322
- function newsletter_delete_all($status=null) {
323
- global $wpdb;
324
-
325
- if ($status == null) {
326
- $wpdb->query("delete from " . $wpdb->prefix . "newsletter");
327
- }
328
- else {
329
- $wpdb->query("delete from " . $wpdb->prefix . "newsletter where status='" . $wpdb->escape($status) . "'");
330
- }
331
- }
332
-
333
- function newsletter_set_status_all($status) {
334
- global $wpdb;
335
-
336
- $wpdb->query("update " . $wpdb->prefix . "newsletter set status='" . $status . "'");
337
- }
338
-
339
- function newsletter_set_status($id, $status) {
340
- global $wpdb;
341
-
342
- $wpdb->query($wpdb->prepare("update " . $wpdb->prefix . "newsletter set status=%s where id=%d", $status, $id));
343
- }
344
-
345
- function newsletter_date($time=null, $now=false, $left=false) {
346
- if (is_null($time)) $time = time();
347
- if ($time === false) $buffer = 'none';
348
- else $buffer = gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
349
- if ($now) {
350
- $buffer .= ' (now: ' . gmdate(get_option('date_format') . ' ' .
351
- get_option('time_format'), time() + get_option('gmt_offset') * 3600);
352
- if ($left) {
353
- $buffer .= ', ' . gmdate('H:i:s', $time - time()) . ' left';
354
- }
355
- $buffer .= ')';
356
- }
357
- return $buffer;
358
- }
359
-
360
- /**
361
- * Retrieves a list of custom themes located under wp-plugins/newsletter-custom/themes.
362
- * Return a list of theme names (which are folder names where the theme files are stored.
363
- */
364
- function newsletter_get_themes() {
365
- $handle = @opendir(ABSPATH . 'wp-content/plugins/newsletter-custom/themes');
366
- $list = array();
367
- if (!$handle) return $list;
368
- while ($file = readdir($handle)) {
369
- if ($file == '.' || $file == '..') continue;
370
- if (!is_dir(ABSPATH . 'wp-content/plugins/newsletter-custom/themes/' . $file)) continue;
371
- if (!is_file(ABSPATH . 'wp-content/plugins/newsletter-custom/themes/' . $file . '/theme.php')) continue;
372
- $list['*' . $file] = $file;
373
- }
374
- closedir($handle);
375
- return $list;
376
- }
377
-
378
- function newsletter_page_get_themes() {
379
- $handle = @opendir(ABSPATH . 'wp-content/plugins/newsletter-custom/themes-page');
380
- $list = array();
381
- if (!$handle) return $list;
382
- while ($file = readdir($handle)) {
383
- if ($file == '.' || $file == '..') continue;
384
- if (!is_dir(ABSPATH . 'wp-content/plugins/newsletter-custom/themes-page/' . $file)) continue;
385
- if (!is_file(ABSPATH . 'wp-content/plugins/newsletter-custom/themes-page/' . $file . '/theme.php')) continue;
386
- $list['*' . $file] = $file;
387
- }
388
- closedir($handle);
389
- return $list;
390
- }
391
-
392
- /**
393
- * $subscriber needs to be an array. If the key 'id' is set, the subscriber data will
394
- * be update, otherwise a new subscriber will be inserted.
395
- * When inserted as new, subscriber's data is returned with id, token and so on.
396
- *
397
- * @global <type> $wpdb
398
- * @param <type> $subscriber Save a new subscriber setting status to confirmed, creating
399
- */
400
- function newsletter_save($subscriber) {
401
- global $wpdb, $newsletter;
402
-
403
- $email = $newsletter->normalize_email($email);
404
- $name = $newsletter->normalize_name($name);
405
- if (isset($subscriber['id'])) {
406
- $wpdb->update($wpdb->prefix . 'newsletter', $subscriber, array('id' => $subscriber['id']));
407
- }
408
- else {
409
- $subscriber['status'] = 'C';
410
- $subscriber['token'] = md5(rand());
411
-
412
- $wpdb->insert($wpdb->prefix . 'newsletter', $subscriber);
413
- $subscriber['id'] = $wpdb->insert_id;
414
- }
415
- return $subscriber;
416
- }
417
-
418
- function newsletter_get_subscriber_strict($id, $token) {
419
- if (is_null($token)) {
420
- newsletter_fatal(__FUNCTION__, 'Ivalid token');
421
- return null;
422
- }
423
- $s = newsletter_get_subscriber($id, $token);
424
- if (is_null($s)) {
425
- newsletter_fatal(__FUNCTION__, 'Subscriber not found or invalid token');
426
- }
427
- return $s;
428
- }
429
-
430
- function newsletter_get_subscriber($id, $token=null, $check_token=false) {
431
- global $wpdb;
432
-
433
- $recipients = $wpdb->get_results($wpdb->prepare("select * from " . $wpdb->prefix .
434
- "newsletter where id=%d", $id));
435
- if (!$recipients) return null;
436
- if ((!is_null($token) || $check_token) && $recipients[0]->token != $token) return null;
437
- return $recipients[0];
438
- }
439
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config-sample.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Move this file inside the /wp_content/newsletter folder to activate it and rename it
4
+ * "config.php".
5
+ *
6
+ */
7
+
8
+ // Even if still called "list" those are the user's "preferences"
9
+ // define('NEWSLETTER_LIST_MAX', 20);
10
+ // define('NEWSLETTER_PROFILE_MAX', 20);
11
+ // define('NEWSLETTER_FORMS_MAX', 10);
12
+ ?>
diagnostic.php ADDED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+
4
+ $controls = new NewsletterControls();
5
+
6
+ if ($controls->is_action('save')) {
7
+ update_option('newsletter_log_level', $controls->data['log_level']);
8
+ update_option('newsletter_diagnostic', $controls->data);
9
+ $controls->messages = 'Loggin levels saved.';
10
+ }
11
+
12
+ if ($controls->is_action('trigger')) {
13
+ $newsletter->hook_newsletter();
14
+ $controls->messages = 'Delivery engine triggered.';
15
+ }
16
+
17
+ if ($controls->is_action('trigger_followup')) {
18
+ NewsletterFollowup::instance()->send();
19
+ $controls->messages = 'Follow up delivery engine triggered.';
20
+ }
21
+
22
+ if ($controls->is_action('engine_on')) {
23
+ wp_clear_scheduled_hook('newsletter');
24
+ wp_schedule_event(time() + 30, 'newsletter', 'newsletter');
25
+ $controls->messages = 'Delivery engine reactivated.';
26
+ }
27
+
28
+ if ($controls->is_action('upgrade')) {
29
+ // TODO: Compact them in a call to Newsletter which should be able to manage the installed modules
30
+ Newsletter::instance()->upgrade();
31
+ NewsletterUsers::instance()->upgrade();
32
+ NewsletterSubscription::instance()->upgrade();
33
+ NewsletterEmails::instance()->upgrade();
34
+ NewsletterStatistics::instance()->upgrade();
35
+ $controls->messages = 'Upgrade forced!';
36
+ }
37
+
38
+ if ($controls->is_action('delete_transient')) {
39
+ delete_transient($_POST['btn']);
40
+ $controls->messages = 'Deleted.';
41
+ }
42
+
43
+ if ($controls->is_action('test_wp')) {
44
+
45
+ if ($controls->data['test_email'] == $newsletter->options['sender_email']) {
46
+ $controls->messages .= 'You are using as test email the same configured as sender email. Test can fail because that.<br />';
47
+ }
48
+
49
+ $text = 'This is a simple test email sent directly with the WordPress mailing functionality' . "\r\n" .
50
+ 'in the same way WordPress sends notifications of new comment or registered users.' . "\r\n\r\n" .
51
+ 'This email is in pure text format and the sender should be wordpress@youdomain.tld (but it can be forced to be different with specific plugins.';
52
+
53
+ $r = wp_mail($controls->data['test_email'], 'Newsletter: direct WordPress email test', $text);
54
+
55
+ if ($r) {
56
+ $controls->messages .= 'Direct WordPress email sent<br />';
57
+ } else {
58
+ $controls->errors .= 'Direct WordPress email NOT sent: ask your provider if your web space is enabled to send emails.<br />';
59
+ }
60
+ }
61
+
62
+ if ($controls->is_action('send_test')) {
63
+
64
+ if ($controls->data['test_email'] == $controls->data['sender_email']) {
65
+ $controls->messages .= 'You are using as test email the same configured as sender email. Test can fail because that.<br />';
66
+ }
67
+
68
+ $text = 'This is a pure textual email sent using the sender data set on basic Newsletter settings.' . "\r\n" .
69
+ 'You should see it to come from the email address you set on basic Newsletter plugin setting.';
70
+ $r = $newsletter->mail($controls->data['test_email'], 'Newsletter: pure text email', array('text' => $text));
71
+
72
+
73
+ if ($r) $controls->messages .= 'Newsletter TEXT test email sent.<br />';
74
+ else
75
+ $controls->errors .= 'Newsletter TEXT test email NOT sent: try to change the sender data, remove the return path and the reply to settings.<br />';
76
+
77
+ $text = '<p>This is a <strong>html</strong> email sent using the <i>sender data</i> set on Newsletter main setting.</p>';
78
+ $text .= '<p>You should see some "mark up", like bold and italic characters.</p>';
79
+ $text .= '<p>You should see it to come from the email address you set on basic Newsletter plugin setting.</p>';
80
+ $r = $newsletter->mail($controls->data['test_email'], 'Newsletter: pure html email', $text);
81
+ if ($r) $controls->messages .= 'Newsletter HTML test email sent.<br />';
82
+ else
83
+ $controls->errors .= 'Newsletter HTML test email NOT sent: try to change the sender data, remove the return path and the reply to settings.<br />';
84
+
85
+
86
+ $text = array();
87
+ $text['html'] = '<p>This is an <b>HTML</b> test email part sent using the sender data set on Newsletter main setting.</p>';
88
+ $text['text'] = 'This is a textual test email part sent using the sender data set on Newsletter main setting.';
89
+ $r = $newsletter->mail($controls->data['test_email'], 'Newsletter: both textual and html email', $text);
90
+ if ($r) $controls->messages .= 'Newsletter: both textual and html test email sent.<br />';
91
+ else
92
+ $controls->errors .= 'Newsletter both TEXT and HTML test email NOT sent: try to change the sender data, remove the return path and the reply to settings.<br />';
93
+ }
94
+
95
+ if (empty($controls->data)) $controls->data = get_option('newsletter_diagnostic');
96
+
97
+ ?>
98
+ <div class="wrap">
99
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletter-diagnostic'; ?>
100
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
101
+
102
+ <h2>Newsletter Diagnostic</h2>
103
+
104
+ <?php $controls->show(); ?>
105
+
106
+ <p>
107
+ If something is not working, here there are test procedures and diagnostic data. But before start take a little time to
108
+ write down a list of modifications you coulf have made recently. Sender email or name? Return path? Reply to?
109
+ </p>
110
+
111
+ <form method="post" action="">
112
+ <?php $controls->init(); ?>
113
+
114
+ <h3>Test</h3>
115
+ <table class="form-table">
116
+ <tr>
117
+ <th>Email test</th>
118
+ <td>
119
+ <?php $controls->text('test_email'); ?>
120
+ <?php $controls->button('test_wp', 'Send an email with WordPress'); ?>
121
+ <?php $controls->button('send_test', 'Send test emails to this address'); ?>
122
+ <div class="hints">
123
+ Some test emails will be sent to the specified address:<br />
124
+ 1. One with the native mail functionality of WordPress as is, so the email should come fro wordpress@yourdomain.tld<br />
125
+ 2. One with sender data/reply to/return path as configured on Newsletter main settings in TEXT format (some time those values can break the mail system)<br />
126
+ 3. One with sender data/reply to/return path as configured on Newsletter main settings in HTML format (some time those values can break the mail system)<br />
127
+ 4. One in multipart format (with html and text parts) managed directly by Newsletter
128
+ </div>
129
+ </td>
130
+ </tr>
131
+ </table>
132
+
133
+ <h3>System Check and Upgrade</h3>
134
+ <p>
135
+ Tables below contain some system parameter that can affect Newsletter plugin working mode. When asking for support consider to
136
+ report those values.
137
+ </p>
138
+
139
+ <div id="tabs">
140
+
141
+ <ul>
142
+ <li><a href="#tabs-1">Modules and logging</a></li>
143
+ <li><a href="#tabs-2">Sempahores and Crons</a></li>
144
+ <li><a href="#tabs-4">System</a></li>
145
+ <li><a href="#tabs-upgrade">Upgrade</a></li>
146
+ </ul>
147
+
148
+ <div id="tabs-1">
149
+ <h4>Modules</h4>
150
+
151
+ <p>Logs are store on wp-content/logs folder.</p>
152
+
153
+ <?php $controls->log_level('log_level'); ?>
154
+
155
+ <table class="widefat" style="width: auto">
156
+ <thead>
157
+ <tr>
158
+ <th>Module</th>
159
+ <th>Version</th>
160
+ </tr>
161
+ </thead>
162
+ <!-- TODO: Should be a cicle of installed modules -->
163
+ <tbody>
164
+ <tr>
165
+ <td>Main</td>
166
+ <td><?php echo Newsletter::VERSION; ?></td>
167
+ </tr>
168
+ <tr>
169
+ <td>Users</td>
170
+ <td><?php echo NewsletterUsers::VERSION; ?></td>
171
+ </tr>
172
+ <tr>
173
+ <td>Subscription</td>
174
+ <td><?php echo NewsletterSubscription::VERSION; ?></td>
175
+ </tr>
176
+ <tr>
177
+ <td>Newsletters</td>
178
+ <td><?php echo NewsletterEmails::VERSION; ?></td>
179
+ </tr>
180
+ <tr>
181
+ <td>Statistics</td>
182
+ <td><?php echo NewsletterStatistics::VERSION; ?></td>
183
+ </tr>
184
+ </tbody>
185
+ </table>
186
+ <?php $controls->button('save', 'Save'); ?>
187
+ </div>
188
+ <div id="tabs-2">
189
+ <h4>Semaphores</h4>
190
+ <table class="widefat" style="width: auto">
191
+ <thead>
192
+ <tr>
193
+ <th>Name</th>
194
+ <th>Active since</th>
195
+ </tr>
196
+ </thead>
197
+
198
+ <tbody>
199
+ <tr>
200
+ <td>
201
+ Newsletter delivery
202
+ </td>
203
+ <td>
204
+ <?php
205
+ $value = get_transient('newsletter_main_engine');
206
+ if ($value) echo (time() - $value) . ' seconds';
207
+ else echo 'Not set';
208
+ ?>
209
+ <?php $controls->button('delete_transient', 'Delete', null, 'newsletter_main_engine'); ?>
210
+ </td>
211
+ </tr>
212
+ </tbody>
213
+ </table>
214
+
215
+ <h4>Crons</h4>
216
+ <table class="widefat" style="width: auto">
217
+ <thead>
218
+ <tr>
219
+ <th>Function</th>
220
+ <th>Runs in (seconds)</th>
221
+ </tr>
222
+ </thead>
223
+
224
+ <tbody>
225
+ <tr>
226
+ <td>
227
+ WordPress Cron System
228
+ </td>
229
+ <td>
230
+ <?php
231
+ if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON)
232
+ echo 'DISABLED. (really bad, see <a href="http://www.satollo.net/?p=2015" target="_tab">this page)</a>';
233
+ else echo "ENABLED. (it's ok)";
234
+ ?>
235
+ </td>
236
+ </tr>
237
+ <tr>
238
+ <td>
239
+ Delivery Engine
240
+ </td>
241
+ <td>
242
+ <?php
243
+ $x = wp_next_scheduled('newsletter');
244
+ if ($x === false) {
245
+ echo 'Error! The delivery engine is off (it should never be off),';
246
+ $controls->button('engine_on', 'Reactivate now');
247
+ }
248
+ echo 'next run on ';
249
+ if ($x > 0) echo $x - time();
250
+ echo ' seconds';
251
+ if ($x < -1000)
252
+ echo ' (not good, see <a href="http://www.satollo.net/?p=2015" target="_tab">this page)</a>)';
253
+ ?>
254
+ <?php $controls->button('trigger', 'Trigger now'); ?>
255
+ </td>
256
+ </tr>
257
+ <tr>
258
+ <td>
259
+ Feed by Mail
260
+ </td>
261
+ <td>
262
+ <?php
263
+ $x = wp_next_scheduled('newsletter_feed');
264
+ if ($x === false) {
265
+ echo 'Not active';
266
+ //$controls->button('engine_on', 'Reactivate now');
267
+ } else {
268
+ if ($x > 0) {
269
+ echo 'Next run on ' . ($x - time()) . ' seconds';
270
+ } else {
271
+ echo 'Running now';
272
+ }
273
+ }
274
+ ?>
275
+ <?php //$controls->button('trigger_followup', 'Trigger now'); ?>
276
+ </td>
277
+ </tr>
278
+ <tr>
279
+ <td>
280
+ Follow Up
281
+ </td>
282
+ <td>
283
+ <?php
284
+ $x = wp_next_scheduled('newsletter_followup');
285
+ if ($x === false) {
286
+ echo 'Not active';
287
+ //$controls->button('engine_on', 'Reactivate now');
288
+ } else {
289
+ if ($x > 0) {
290
+ echo 'Next run on ' . ($x - time()) . ' seconds';
291
+ } else {
292
+ echo 'Running now';
293
+ }
294
+ }
295
+ ?>
296
+ <?php $controls->button('trigger_followup', 'Trigger now'); ?>
297
+ </td>
298
+ </tr>
299
+ </tbody>
300
+ </table>
301
+ </div>
302
+ <div id="tabs-4">
303
+ <h4>System parameters</h4>
304
+
305
+ <table class="widefat" style="width: auto">
306
+ <thead>
307
+ <tr>
308
+ <th>Parameter</th>
309
+ <th>Value</th>
310
+ </tr>
311
+ </thead>
312
+ <tbody>
313
+ <tr>
314
+ <td>Database Wait Timeout</td>
315
+ <td>
316
+ <?php $wait_timeout = $wpdb->get_var("select @@wait_timeout"); ?>
317
+ <?php echo $wait_timeout; ?> (seconds)
318
+ </td>
319
+ </tr>
320
+ <tr>
321
+ <td>PHP Execution Time</td>
322
+ <td>
323
+ <?php echo ini_get('max_execution_time'); ?> (seconds)
324
+ </td>
325
+ </tr>
326
+ <tr>
327
+ <td>PHP Memory Limit</td>
328
+ <td>
329
+ <?php echo @ini_get('memory_limit'); ?>
330
+ </td>
331
+ </tr>
332
+ <tr>
333
+ <td>WordPress Memory limit</td>
334
+ <td>
335
+ <?php echo WP_MEMORY_LIMIT; ?>
336
+ </td>
337
+ </tr>
338
+ <tr>
339
+ <td>Absolute path</td>
340
+ <td>
341
+ <?php echo ABSPATH; ?>
342
+ </td>
343
+ </tr>
344
+ <tr>
345
+ <td>Tables Prefix</td>
346
+ <td>
347
+ <?php echo $table_prefix; ?>
348
+ </td>
349
+ </tr>
350
+ <tr>
351
+ <td>Database Charset and Collate</td>
352
+ <td>
353
+ <?php echo DB_CHARSET; ?> <?php echo DB_COLLATE; ?>
354
+ </td>
355
+ </tr>
356
+ <tr>
357
+ <td>Hook "phpmailer_init"</td>
358
+ <td>
359
+ Obsolete.<br>
360
+ <?php
361
+ $filters = $wp_filter['phpmailer_init'];
362
+ if (!is_array($filters)) echo 'No actions attached';
363
+ else {
364
+ foreach ($filters as &$filter) {
365
+ foreach ($filter as &$entry) {
366
+ if (is_array($entry['function']))
367
+ echo get_class($entry['function'][0]) . '->' . $entry['function'][1];
368
+ else echo $entry['function'];
369
+ echo '<br />';
370
+ }
371
+ }
372
+ }
373
+ ?>
374
+ </td>
375
+ </tr>
376
+ </tbody>
377
+ </table>
378
+
379
+ </div>
380
+ <div id="tabs-upgrade">
381
+ <h3>Upgrade</h3>
382
+ <p>
383
+ Plugin and modules are able to upgrade them self when needed. If you urgently need to try to force an upgrade, press the
384
+ button below.
385
+ </p>
386
+ <p>
387
+ <?php $controls->button('upgrade', 'Force an upgrade'); ?>
388
+ </p>
389
+ </div>
390
+ </div>
391
+
392
+ </form>
393
+
394
+ </div>
do.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
-
3
- include '../../../wp-load.php';
4
-
5
- $action = $_REQUEST['a'];
6
- if (empty($action)) return;
7
-
8
- $user = $newsletter->check_user();
9
-
10
- if ($user == null) {
11
- echo 'Subscriber not found, sorry.';
12
- die();
13
- }
14
-
15
- $options = get_option('newsletter', array());
16
- $options_main = get_option('newsletter_main', array());
17
-
18
- if ($action == 'c') {
19
- setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
20
- $wpdb->query("update " . $wpdb->prefix . "newsletter set status='C' where id=" . $user->id);
21
-
22
- $newsletter->mail($user->email, $newsletter->replace($options['confirmed_subject'], $user), $newsletter->replace($options['confirmed_message'], $user));
23
- $newsletter->notify_admin($user, 'Newsletter subscription');
24
-
25
- $url = $options_main['url'];
26
- if (empty($url)) $url = get_option('home');
27
-
28
- header('Location: ' . $newsletter->add_qs($url, 'na=c&ni=' . $user->id . '&nt=' . $user->token, false));
29
- die();
30
- }
31
-
32
- if ($action == 'uc') {
33
- $wpdb->query($wpdb->prepare("update " . $wpdb->prefix . "newsletter set status='U' where id=%d and token=%s", $user->id, $user->token));
34
- setcookie("newsletter", "", time() - 3600);
35
- $newsletter->mail($user->email, $newsletter->replace($options['unsubscribed_subject'], $user), $newsletter->replace($options['unsubscribed_message'], $user));
36
- $newsletter->notify_admin($user, 'Newsletter cancellation');
37
-
38
- $url = $options_main['url'];
39
- if (empty($url)) $url = get_option('home');
40
-
41
- header('Location: ' . $newsletter->add_qs($url, 'na=uc&ni=' . $user->id . '&nt=' . $user->token, false));
42
- die();
43
- }
44
- ?>
45
- Unknown action.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
do/change.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ $user = Newsletter::instance()->get_user_from_request(true);
6
+ $field = $_REQUEST['nf'];
7
+ $value = $_REQUEST['nv'];
8
+ $url = $_REQUEST['nu'];
9
+
10
+ switch ($field) {
11
+ case 'sex':
12
+ if (!in_array($value, array('f', 'm', 'n'))) die('Invalid sex value');
13
+ NewsletterUsers::instance()->set_user_field($user->id, 'sex', $value);
14
+ break;
15
+ // Should be managed by Feed by Mail
16
+ case 'feed':
17
+ if ($value != 1) die('Invalid feed value');
18
+ NewsletterUsers::instance()->set_user_field($user->id, 'feed', $value);
19
+ break;
20
+ default:
21
+ die('Invalid field');
22
+ }
23
+ if (isset($url)) {
24
+ header("Location: $url");
25
+ } else {
26
+ NewsletterSubscription::instance()->show_message('profile', $user, NewsletterSubscription::instance()->options['profile_saved']);
27
+ }
do/confirm.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ // This page is linked to {subscription_confirm_url} tag.
8
+
9
+ include '../../../../wp-load.php';
10
+
11
+ $user = NewsletterSubscription::instance()->confirm();
12
+ NewsletterSubscription::instance()->show_message('confirmed', $user);
do/profile.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ // This page is linked to {profile_url} tag.
8
+
9
+ include '../../../../wp-load.php';
10
+
11
+ $user = NewsletterSubscription::instance()->get_user_from_request();
12
+ if ($user == null) die('No subscriber found.');
13
+
14
+ NewsletterSubscription::instance()->show_message('profile', $user);
do/save.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+ include '../../../../wp-load.php';
3
+
4
+ $user = NewsletterSubscription::instance()->save_profile();
5
+ NewsletterSubscription::instance()->show_message('profile', $user, NewsletterSubscription::instance()->options['profile_saved']);
do/subscribe-popup.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ $popup = true;
3
+ include 'subscribe.php';
do/subscribe.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ require_once '../../../../wp-load.php';
8
+
9
+ $user = NewsletterSubscription::instance()->subscribe();
10
+ if ($user->status == 'C') NewsletterSubscription::instance()->show_message('confirmed', $user->id);
11
+ if ($user->status == 'S') NewsletterSubscription::instance()->show_message('confirmation', $user->id);
do/subscription-popup.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once '../../../../wp-load.php';
4
+
5
+ if (!isset($newsletter)) $newsletter = new Newsletter();
6
+
7
+ $options_main = get_option('newsletter_main', array());
8
+ $options = get_option('newsletter', array());
9
+
10
+ $text = trim($options['subscription_popup_text']);
11
+ if (empty($text)) $text = $options['subscription_text'];
12
+
13
+ if (stripos($text, '<form') !== false) {
14
+ $message = str_ireplace('<form', '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_POPUP_URL . '" onsubmit="return newsletter_check(this)"', $options['subscription_text']);
15
+ $message = $this->replace_lists($message);
16
+ } else {
17
+ $form = $newsletter->subscription_form(null, true, NEWSLETTER_SUBSCRIBE_POPUP_URL);
18
+
19
+ if (strpos($options['subscription_text'], '{subscription_form}') !== false)
20
+ $message = str_replace('{subscription_form}', $form, $text);
21
+ else $message = $text . $form;
22
+ }
23
+ include NEWSLETTER_DIR . '/popup.php';
do/subscription.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once '../../../../wp-load.php';
4
+
5
+ if (!isset($newsletter)) $newsletter = new Newsletter();
6
+
7
+ $options_main = get_option('newsletter_main', array());
8
+
9
+ if (!empty($options_main['url'])) {
10
+ header('Location: ' . $options_main['url']);
11
+ die();
12
+ }
13
+
14
+ $options = get_option('newsletter', array());
15
+
16
+ if (stripos($options['subscription_text'], '<form') !== false) {
17
+ $message = str_ireplace('<form', '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_URL . '" onsubmit="return newsletter_check(this)"', $options['subscription_text']);
18
+ $message = $this->replace_lists($message);
19
+ } else {
20
+ $form = $newsletter->subscription_form();
21
+
22
+ if (strpos($options['subscription_text'], '{subscription_form}') !== false)
23
+ $message = str_replace('{subscription_form}', $form, $options['subscription_text']);
24
+ else $message = $options['subscription_text'] . $form;
25
+ }
26
+ include NEWSLETTER_DIR . '/page.php';
do/unlock.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ include '../../../../wp-load.php';
8
+
9
+ $user = NewsletterSubscription::instance()->check_user();
10
+
11
+ if ($user == null || $user->status != 'C') {
12
+ echo 'Subscriber not found, sorry.';
13
+ die();
14
+ }
15
+
16
+ $options_main = get_option('newsletter_main', array());
17
+
18
+ setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
19
+
20
+ header('Location: ' . $options_main['lock_url']);
21
+
22
+ die();
do/unsubscribe.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ require_once '../../../../wp-load.php';
8
+
9
+ $user = NewsletterSubscription::instance()->unsubscribe();
10
+ NewsletterSubscription::instance()->show_message('unsubscribed', $user);
do/unsubscription.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Patch to avoid "na" parameter to disturb the call
3
+ unset($_REQUEST['na']);
4
+ unset($_POST['na']);
5
+ unset($_GET['na']);
6
+
7
+ require_once '../../../../wp-load.php';
8
+
9
+ $user = NewsletterSubscription::instance()->get_user_from_request();
10
+ if ($user == null) die('No subscriber found.');
11
+ NewsletterSubscription::instance()->show_message('unsubscription', $user);
12
+
do/view.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a generic viewer for sent emails. It is not binded to one shot emails, it can display even the emails from
4
+ * updates or feed by mail module.
5
+ */
6
+ include '../../../../wp-load.php';
7
+
8
+ // TODO: Change to Newsletter::instance()->get:email(), not urgent
9
+ $email = Newsletter::instance()->get_email($_GET['id']);
10
+ if (empty($email)) die('Email not found');
11
+
12
+ $user = NewsletterSubscription::instance()->get_user_from_request();
13
+
14
+ if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/view.php')) {
15
+ include WP_CONTENT_DIR . '/extensions/newsletter/view.php';
16
+ die();
17
+ }
18
+
19
+ echo $newsletter->replace($email->message, $user);
20
+ ?>
emails-edit.php DELETED
@@ -1,242 +0,0 @@
1
- <?php
2
- @include_once 'commons.php';
3
- $nc = new NewsletterControls();
4
-
5
- if (isset($_GET['id'])) {
6
- $nc->load($wpdb->prefix . 'newsletter_emails', $_GET['id']);
7
- if (empty($nc->data['id'])) {
8
- $nc->data['status'] = 'new';
9
- $nc->data['subject'] = 'Here the email subject';
10
- $nc->data['message'] = '<p>An empty email to start.</p>';
11
- $nc->data['theme'] = 'blank';
12
- }
13
- }
14
- else {
15
- if ($nc->is_action('save') || $nc->is_action('send')) {
16
- $nc->save($wpdb->prefix . 'newsletter_emails');
17
- }
18
-
19
- if ($nc->is_action('send')) {
20
-
21
- // Fake value representing the WordPress users as target
22
- if ($nc->data['list'] == -1) {
23
- $query = "select count(*) from " . $wpdb->prefix . "users " . $nc->data['query'];
24
- }
25
- else {
26
- if (!empty($nc->data['query'])) $query = "select count(*) from " . $wpdb->prefix . "newsletter " . $nc->data['query'];
27
- else {
28
- $query = "select count(*) from " . $wpdb->prefix . "newsletter where status='C'";
29
- if ($nc->data['list'] != 0) $query .= " and list_" . $nc->data['list'] . "=1";
30
- if (!empty($nc->data['sex'])) $query .= " and sex='" . $nc->data['sex'] . "'";
31
- }
32
- }
33
- $newsletter->log($query, 3);
34
- $newsletter->log('total: ' . $wpdb->get_var($query), 3);
35
-
36
- $nc->data['total'] = $wpdb->get_var($query);
37
- $nc->data['sent'] = 0;
38
- $nc->data['status'] = 'sending';
39
- $nc->data['last_id'] = 0;
40
- $nc->save($wpdb->prefix . 'newsletter_emails');
41
- $nc->load($wpdb->prefix . 'newsletter_emails', $nc->data['id']);
42
- }
43
-
44
- if ($nc->is_action('pause')) {
45
- $nc->update($wpdb->prefix . 'newsletter_emails', 'status', 'paused');
46
- $nc->load($wpdb->prefix . 'newsletter_emails', $nc->data['id']);
47
- }
48
-
49
- if ($nc->is_action('continue')) {
50
- $wpdb->query("update " . $wpdb->prefix . "newsletter_emails set status='sending' where id=" . $nc->data['id']);
51
- $nc->load($wpdb->prefix . 'newsletter_emails', $nc->data['id']);
52
- }
53
-
54
- if ($nc->is_action('abort')) {
55
- $wpdb->query("update " . $wpdb->prefix . "newsletter_emails set last_id=0, status='new' where id=" . $nc->data['id']);
56
- $nc->load($wpdb->prefix . 'newsletter_emails', $nc->data['id']);
57
- }
58
-
59
- if ($nc->is_action('delete')) {
60
- $wpdb->query("delete from " . $wpdb->prefix . "newsletter_emails where id=" . $nc->data['id']);
61
- ?><script>location.href="admin.php?page=newsletter/emails.php";</script><?php
62
- return;
63
- }
64
-
65
- if ($nc->is_action('compose')) {
66
- if ($nc->data['theme'][0] == '*') $file = ABSPATH . 'wp-content/plugins/newsletter-custom/themes/' . substr($nc->data['theme'], 1) .
67
- '/theme.php';
68
- else $file = dirname(__FILE__) . '/themes/' . $nc->data['theme'] . '/theme.php';
69
-
70
- ob_start();
71
- @include($file);
72
- $nc->data['message'] = ob_get_contents();
73
- ob_end_clean();
74
- }
75
-
76
- if ($nc->is_action('test')) {
77
- $nc->save($wpdb->prefix . 'newsletter_emails');
78
- $users = newsletter_get_test_subscribers();
79
- $email = new stdClass();
80
- $email->message = $nc->data['message'];
81
- $email->subject = $nc->data['subject'];
82
- $email->track = $nc->data['track'];
83
- $email->type = 'email';
84
- $newsletter->send($email, $users);
85
- }
86
- }
87
-
88
-
89
- $options_main = get_option('newsletter_main', array());
90
-
91
- $options_profile = get_option('newsletter_profile', array());
92
- $lists = array('0' => 'To all subscribers', '-1'=>'To WordPress users');
93
- for ($i = 1; $i <= 9; $i++) {
94
- $lists['' . $i] = '(' . $i . ') ' . $options_profile['list_' . $i];
95
- }
96
-
97
- // Themes
98
- $themes[''] = 'Packaged themes';
99
- $themes['blank'] = 'Empty email';
100
- $themes['theme-1'] = 'Newsletter theme 1';
101
- //$themes['theme-2'] = 'Newsletter theme 2';
102
- $themes['theme-3'] = 'Newsletter theme 3';
103
-
104
- $nc->errors($errors);
105
- $nc->messages($messages);
106
-
107
- function newsletter_get_theme_file($theme) {
108
- if ($theme[0] == '*') $file = ABSPATH . 'wp-content/plugins/newsletter-custom/themes/' . substr($theme, 1) . '/theme.php';
109
- else $file = dirname(__FILE__) . '/themes/' . $theme . '/theme.php';
110
- }
111
-
112
- function newsletter_get_theme_css_url($theme) {
113
- if ($theme[0] == '*') $file = 'newsletter-custom/themes/' . substr($theme, 1) . '/style.css';
114
- else $file = 'newsletter/themes/' . $theme . '/style.css';
115
- if (!file_exists(ABSPATH . 'wp-content/plugins/' . $file)) return get_option('siteurl') . '/wp-content/plugins/newsletter/themes/empty.css';
116
- return get_option('siteurl') . '/wp-content/plugins/' . $file;
117
- }
118
-
119
- ?>
120
-
121
- <script type="text/javascript" src="<?php echo get_option('siteurl'); ?>/wp-content/plugins/newsletter/tiny_mce/tiny_mce.js"></script>
122
- <script type="text/javascript">
123
- tinyMCE.init({
124
- mode : "specific_textareas",
125
- editor_selector : "visual",
126
- theme : "advanced",
127
- plugins: "table,fullscreen,paste",
128
- theme_advanced_disable : "styleselect",
129
- theme_advanced_buttons1_add: "forecolor,blockquote,code,pastetext,pasteword,selectall",
130
- theme_advanced_buttons3 : "tablecontrols,fullscreen",
131
- relative_urls : false,
132
- remove_script_host : false,
133
- theme_advanced_toolbar_location : "top",
134
- document_base_url : "<?php echo get_option('home'); ?>/",
135
- content_css: "<?php echo newsletter_get_theme_css_url($nc->data['theme']) . '?' . time(); ?>"
136
- });
137
- </script>
138
-
139
-
140
- <div class="wrap">
141
-
142
- <h2>Email Composer</h2>
143
-
144
- <form method="post" action="admin.php?page=newsletter/emails-edit.php">
145
- <?php $nc->init(); ?>
146
- <?php $nc->hidden('id'); ?>
147
- <?php $nc->hidden('status'); ?>
148
-
149
- <table class="form-table">
150
-
151
- <tr valign="top">
152
- <th>Theme</th>
153
- <td>
154
- <?php $nc->select_grouped('theme', array(
155
- array_merge(array(''=>'Custom themes'), newsletter_get_themes()),
156
- $themes,
157
- $themes_panel
158
- ));
159
- ?>
160
- <?php $nc->button('compose', 'Change'); ?> (email content below will be regenerated)
161
- <div class="hints">
162
- Theme changing does not save this email, remember to press save if you are satisfied of the result. A theme can have a style file
163
- (style.css in theme folder): that style will be added to your emails, so when you change the theme you MUST press "change" to have
164
- in the editor the right content for the current theme style. No easy to explain. No all email readers respect the theme graphics!
165
- </div>
166
- </td>
167
- </tr>
168
-
169
- <tr valign="top">
170
- <th>Subject</th>
171
- <td>
172
- <?php $nc->text('subject', 70); ?>
173
- <div class="hints">
174
- Tags: <strong>{name}</strong> receiver name.
175
- </div>
176
- </td>
177
- </tr>
178
-
179
- <tr valign="top">
180
- <th>Message</th>
181
- <td>
182
- <?php $nc->data['editor'] == 0?$nc->editor('message', 20):$nc->textarea_fixed('message', '100%', 400); ?>
183
- <br />
184
- <?php $nc->select('editor', array(0=>'Edit with visual editor', 1=>'Edit as plain text')); ?>
185
- <div class="hints">
186
- Tags: <strong>{name}</strong> receiver name;
187
- <strong>{unsubscription_url}</strong> unsubscription URL;
188
- <strong>{token}</strong> the subscriber token; <strong>{profile_url}</strong> link to user subscription options page;
189
- <strong>{np_aaa}</strong> user profile data named "aaa".
190
- </div>
191
- </td>
192
- </tr>
193
-
194
- <tr valign="top">
195
- <th>To...</th>
196
- <td>
197
- list: <?php $nc->select('list', $lists); ?>
198
- sex: <?php $nc->select('sex', array(''=>'All', 'n'=>'No sex specified', 'f'=>'Females', 'm'=>'Males')); ?>
199
- <div class="hints">
200
- When sending to WordPress users, they cannot cancel the subscription and the cannot
201
- be tracked.
202
- </div>
203
- </td>
204
- </tr>
205
- <!--
206
- <tr valign="top">
207
- <th>Query<br/><small>Really advanced!</small></th>
208
- <td>
209
- select * from wp_newsletter<br />
210
- <?php $nc->textarea('query'); ?>
211
- <br />
212
- and id>... order by id limit ...
213
- <div class="hints">
214
- If you want to specify a different query to extract subscriber from Newsletter Pro database, here you
215
- can write it. Be aware that the query starts and ends as specified, so your SQL snippet needs to create a
216
- complete and working query.<br />
217
- Leave this area empty to leave Newsletter Pro doing the work.<br />
218
- When you specify a query, options like the target list will be ignored.<br />
219
- For examples of queries study the documentation panel.
220
- </div>
221
- </td>
222
- </tr>
223
- -->
224
-
225
- </table>
226
-
227
- <p class="submit">
228
- <?php if ($nc->data['status'] != 'sending') $nc->button('save', 'Save'); ?>
229
- <?php if ($nc->data['status'] != 'sending') $nc->button_confirm('test', 'Save and test', 'Save and send test emails to test addresses?'); ?>
230
-
231
- <?php if ($nc->data['status'] == 'new') {
232
- $nc->button_confirm('send', 'Send', 'Start a real delivery?');
233
- } ?>
234
- <?php if ($nc->data['status'] == 'sending') $nc->button_confirm('pause', 'Pause', 'Pause the delivery?'); ?>
235
- <?php if ($nc->data['status'] == 'paused') $nc->button_confirm('continue', 'Continue', 'Continue the delivery?'); ?>
236
- <?php if ($nc->data['status'] != 'new') $nc->button_confirm('abort', 'Abort', 'Abort the delivery?'); ?>
237
- <?php if ($nc->data['id'] != 0) $nc->button_confirm('delete', 'Delete', 'Delete?'); ?>
238
- (email status: <?php echo $nc->data['status']; ?>)
239
- </p>
240
-
241
- </form>
242
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
emails.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- @include_once 'commons.php';
3
- $nc = new NewsletterControls();
4
-
5
- $emails = $wpdb->get_results("select * from " . $wpdb->prefix . "newsletter_emails where type='email' order by id desc");
6
-
7
- if ($nc->is_action('send')) {
8
- $newsletter->hook_newsletter();
9
- }
10
- ?>
11
-
12
- <div class="wrap">
13
-
14
- <h2>Messages</h2>
15
-
16
- <?php include dirname(__FILE__) . '/header.php'; ?>
17
-
18
- <form method="post" action="admin.php?page=newsletter/emails.php">
19
- <?php $nc->init(); ?>
20
-
21
- <p><a href="admin.php?page=newsletter/emails-edit.php&amp;id=0" class="button">New message</a></p>
22
- <p>
23
- Delivery engine next run: <?php echo wp_next_scheduled('newsletter')-time(); ?> seconds
24
- <?php $nc->button('send', 'Trigger now'); ?>
25
- </p>
26
-
27
- <table class="widefat">
28
- <thead>
29
- <tr>
30
- <th>Id</th>
31
- <th>Subject</th>
32
- <th>Date</th>
33
- <th>Status</th>
34
- <th>&nbsp;</th>
35
- </tr>
36
- </thead>
37
-
38
- <tbody>
39
- <?php foreach ($emails as &$email) { ?>
40
- <tr>
41
- <td><?php echo $email->id; ?></td>
42
- <td><a href="admin.php?page=newsletter/emails-edit.php&amp;id=<?php echo $email->id; ?>"><?php echo htmlspecialchars($email->subject); ?></a></td>
43
- <td><?php echo $email->date; ?></td>
44
- <td>
45
- <?php echo $email->status; ?>
46
- (<?php echo $email->sent; ?>/<?php echo $email->total; ?>)
47
- </td>
48
- </tr>
49
- <?php } ?>
50
- </tbody>
51
- </table>
52
- </form>
53
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
emails/css.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ $email_id = (int)$_GET['id'];
6
+
7
+ $body = Newsletter::instance()->get_email_field($email_id, 'message');
8
+
9
+ $x = strpos($body, '<style');
10
+ if ($x === false) return;
11
+
12
+ $x = strpos($body, '>', $x);
13
+ $y = strpos($body, '</style>');
14
+
15
+ header('Content-Type: text/css');
16
+
17
+ echo substr($body, $x+1, $y-$x-1);
emails/edit.php ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $controls = new NewsletterControls();
4
+ $module = NewsletterEmails::instance();
5
+
6
+
7
+ // Always required
8
+ $email_id = $_GET['id'];
9
+ $email = Newsletter::instance()->get_email($email_id, ARRAY_A);
10
+
11
+ // If there is no action we assume we are enter the first time so we populate the
12
+ // $nc->data with the editable email fields
13
+ if (!$controls->is_action()) {
14
+ $controls->data = $email;
15
+ if (!empty($email['preferences'])) $controls->data['preferences'] = explode(',', $email['preferences']);
16
+ if (!empty($email['sex'])) $controls->data['sex'] = explode(',', $email['sex']);
17
+ }
18
+
19
+ if ($controls->is_action('test') || $controls->is_action('save') || $controls->is_action('send') || $controls->is_action('editor')) {
20
+
21
+ // If we were editing with visual editor (==0), we must read the extra <body> content
22
+ if ($email['editor'] == 0) {
23
+ $x = strpos($email['message'], '<body');
24
+ if ($x !== false) {
25
+ $x = strpos($email['message'], '>', $x);
26
+ $email['message'] = substr($email['message'], 0, $x + 1) . $controls->data['message'] . '</body></html>';
27
+ } else {
28
+ $email['message'] = '<html><body>' . $controls->data['message'] . '</body></html>';
29
+ }
30
+ } else {
31
+ $email['message'] = $controls->data['message'];
32
+ }
33
+ $email['message_text'] = $controls->data['message_text'];
34
+ $email['subject'] = $controls->data['subject'];
35
+ $email['track'] = $controls->data['track'];
36
+
37
+ if (is_array($controls->data['preferences'])) $email['preferences'] = implode(',', $controls->data['preferences']);
38
+ else $email['preferences'] = '';
39
+
40
+ if (is_array($controls->data['sex'])) $email['sex'] = implode(',', $controls->data['sex']);
41
+ else $email['sex'] = '';
42
+
43
+ // Before send, we build the query to extract subscriber, so the delivery engine does not
44
+ // have to worry about the email parameters
45
+ $query = "select * from " . $wpdb->prefix . "newsletter where status='C'";
46
+
47
+ $preferences = $controls->data['preferences'];
48
+ if (is_array($preferences)) {
49
+ $query .= " and (";
50
+ foreach ($preferences as $x) {
51
+ $query .= "list_" . $x . "=1 or ";
52
+ }
53
+ $query = substr($query, 0, -4);
54
+ $query .= ")";
55
+ }
56
+
57
+ $sex = $controls->data['sex'];
58
+ if (is_array($sex)) {
59
+ $query .= " and sex in (";
60
+ foreach ($sex as $x) {
61
+ $query .= "'" . $x . "', ";
62
+ }
63
+ $query = substr($query, 0, -2);
64
+ $query .= ")";
65
+ }
66
+
67
+ $email['query'] = $query;
68
+ if ($controls->is_action('test')) {
69
+ $email['total'] = 0;
70
+ } else {
71
+ $email['total'] = $wpdb->get_var(str_replace('*', 'count(*)', $query));
72
+ }
73
+ $email['sent'] = 0;
74
+ $email['last_id'] = 0;
75
+ $email['send_on'] = $controls->data['send_on'];
76
+
77
+ Newsletter::instance()->save_email($email);
78
+ }
79
+
80
+ if ($controls->is_action('send')) {
81
+
82
+ $wpdb->update($wpdb->prefix . 'newsletter_emails', array('status' => 'sending'), array('id' => $email_id));
83
+ $email['status'] = 'sending';
84
+ $controls->messages = "Email added to the queue.";
85
+ }
86
+
87
+ if ($controls->is_action('pause')) {
88
+ $wpdb->update($wpdb->prefix . 'newsletter_emails', array('status' => 'paused'), array('id' => $email_id));
89
+ $email['status'] = 'paused';
90
+ }
91
+
92
+ if ($controls->is_action('continue')) {
93
+ $wpdb->update($wpdb->prefix . 'newsletter_emails', array('status' => 'sending'), array('id' => $email_id));
94
+ $email['status'] = 'sending';
95
+ }
96
+
97
+ if ($controls->is_action('abort')) {
98
+ $wpdb->query("update " . $wpdb->prefix . "newsletter_emails set last_id=0, total=0, sent=0, status='new' where id=" . $email_id);
99
+ $email['status'] = 'new';
100
+ $email['total'] = 0;
101
+ $email['sent'] = 0;
102
+ $email['last_id'] = 0;
103
+ $controls->messages = "Sending aborted.";
104
+ }
105
+
106
+ if ($controls->is_action('test')) {
107
+ $users = NewsletterUsers::instance()->get_test_users();
108
+ if (count($users) == 0) {
109
+ $controls->errors = 'There is no test subscribers to who send this email. Mark some subscribers as test subscriber from the Subscriber panel.';
110
+ } else {
111
+ Newsletter::instance()->send(Newsletter::instance()->get_email($email_id), $users);
112
+ $controls->messages = 'Test emails sent to ' . count($users) . ' test users.';
113
+ }
114
+ }
115
+
116
+
117
+ if ($email['editor'] == 0) {
118
+ $x = strpos($controls->data['message'], '<body');
119
+ // Some time the message in $nc->data is already cleaned up, it depends on action called
120
+ if ($x !== false) {
121
+ $x = strpos($controls->data['message'], '>', $x);
122
+ $y = strpos($controls->data['message'], '</body>');
123
+
124
+ $controls->data['message'] = substr($controls->data['message'], $x + 1, $y - $x - 1);
125
+ }
126
+ }
127
+ ?>
128
+
129
+ <script type="text/javascript" src="<?php echo NEWSLETTER_URL; ?>/tiny_mce/tiny_mce.js"></script>
130
+ <script type="text/javascript">
131
+ tinyMCE.init({
132
+ mode : "specific_textareas",
133
+ editor_selector : "visual",
134
+ theme : "advanced",
135
+ plugins: "table,fullscreen,legacyoutput",
136
+ theme_advanced_disable : "styleselect",
137
+ theme_advanced_buttons1_add: "forecolor,blockquote,code",
138
+ theme_advanced_buttons3 : "tablecontrols,fullscreen",
139
+ relative_urls : false,
140
+ theme_advanced_statusbar_location: "bottom",
141
+ remove_script_host : false,
142
+ theme_advanced_resizing : true,
143
+ theme_advanced_toolbar_location : "top",
144
+ document_base_url : "<?php echo get_option('home'); ?>/",
145
+ content_css: "<?php echo NEWSLETTER_URL . '/emails/css.php?id=' . $email_id . '&' . time(); ?>"
146
+ });
147
+
148
+ jQuery(document).ready(function() {
149
+ jQuery('#upload_image_button').click(function() {
150
+ tb_show('', 'media-upload.php?type=image&amp;TB_iframe=true');
151
+ return false;
152
+ });
153
+
154
+ window.send_to_editor = function(html) {
155
+ imgurl = jQuery('img',html).attr('src');
156
+ //jQuery('#upload_image').val(imgurl);
157
+ tinyMCE.execCommand('mceInsertContent',false,'<img src="' + imgurl + '" />');
158
+ tb_remove();
159
+ }
160
+ });
161
+ </script>
162
+
163
+ <div class="wrap">
164
+
165
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletters-module'; ?>
166
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
167
+
168
+ <h2>Newsletters Module</h2>
169
+
170
+ <?php $controls->show(); ?>
171
+
172
+ <form method="post" action="" id="newsletter-form">
173
+ <?php $controls->init(); ?>
174
+
175
+ <p class="submit">
176
+ <?php if ($email['status'] != 'sending') $controls->button('save', 'Save'); ?>
177
+ <?php if ($email['status'] != 'sending') $controls->button_confirm('test', 'Save and test', 'Save and send test emails to test addresses?'); ?>
178
+
179
+ <?php if ($email['status'] == 'new') $controls->button_confirm('send', 'Send', 'Start a real delivery?'); ?>
180
+ <?php if ($email['status'] == 'sending') $controls->button_confirm('pause', 'Pause', 'Pause the delivery?'); ?>
181
+ <?php if ($email['status'] == 'paused') $controls->button_confirm('continue', 'Continue', 'Continue the delivery?'); ?>
182
+ <?php if ($email['status'] != 'new') $controls->button_confirm('abort', 'Abort', 'Abort the delivery?'); ?>
183
+ <?php $controls->button_confirm('editor', 'Save and switch to ' . ($email['editor'] == 0 ? 'HTML source' : 'visual') . ' editor', 'Sure?'); ?>
184
+ </p>
185
+
186
+ <div id="tabs">
187
+ <ul>
188
+ <li><a href="#tabs-1">Message</a></li>
189
+ <li><a href="#tabs-2">Message (textual)</a></li>
190
+ <li><a href="#tabs-3">Who will receive it</a></li>
191
+ <li><a href="#tabs-4">Status</a></li>
192
+ </ul>
193
+
194
+
195
+ <div id="tabs-1">
196
+ <table class="form-table">
197
+ <tr valign="top">
198
+ <th>Subject</th>
199
+ <td>
200
+ <?php $controls->text('subject', 70); ?>
201
+ </td>
202
+ </tr>
203
+
204
+ <tr valign="top">
205
+ <th>Message</th>
206
+ <td>
207
+ <input id="upload_image_button" type="button" value="Choose or upload an image" />
208
+ <?php $email['editor'] == 0 ? $controls->editor('message', 30) : $controls->textarea_fixed('message', '100%'); ?>
209
+ <div class="hints">
210
+ Tags: <strong>{name}</strong> receiver name;
211
+ <strong>{unsubscription_url}</strong> unsubscription URL;
212
+ <strong>{token}</strong> the subscriber token; <strong>{profile_url}</strong> link to user subscription options page;
213
+ <strong>{np_aaa}</strong> user profile data named "aaa".
214
+ </div>
215
+ </td>
216
+ </tr>
217
+ </table>
218
+ </div>
219
+
220
+
221
+ <div id="tabs-2">
222
+ <p>
223
+ This is the textual version of your newsletter. If you empty it, only an HTML version will be sent but
224
+ is an anti-spam best practice to include a text only version.
225
+ </p>
226
+ <table class="form-table">
227
+ <tr valign="top">
228
+ <th>Message</th>
229
+ <td>
230
+ <?php $controls->textarea_fixed('message_text', '100%', '250'); ?>
231
+ </td>
232
+ </tr>
233
+ </table>
234
+ </div>
235
+
236
+
237
+ <div id="tabs-3">
238
+ <table class="form-table">
239
+ <tr valign="top">
240
+ <th>Approximative number of receivers</th>
241
+ <td>
242
+ <?php
243
+ // Compute the receivers ids that should receive that email
244
+ $query = "select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='C'";
245
+
246
+ if (is_array($controls->data['preferences'])) {
247
+ $query .= " and (";
248
+ foreach ($controls->data['preferences'] as $x) {
249
+ $query .= "list_" . $x . "=1 or ";
250
+ }
251
+ $query = substr($query, 0, -4);
252
+ $query .= ")";
253
+ }
254
+
255
+ if (is_array($controls->data['sex'])) {
256
+ $query .= " and sex in (";
257
+ foreach ($controls->data['sex'] as $x) {
258
+ $query .= "'" . $x . "', ";
259
+ }
260
+ $query = substr($query, 0, -2);
261
+ $query .= ")";
262
+ }
263
+ echo $wpdb->get_var($query);
264
+ ?>
265
+ <div class="hints">
266
+ If you change selections below, save the email to update this values.
267
+ </div>
268
+ </td>
269
+ </tr>
270
+ <tr valign="top">
271
+ <th>Sex</th>
272
+ <td>
273
+ <div class="nl-checkbox-group"><?php $controls->checkbox_group('sex', 'f', 'Women'); ?></div>
274
+ <div class="nl-checkbox-group"><?php $controls->checkbox_group('sex', 'm', 'Men'); ?></div>
275
+ <div class="nl-checkbox-group"><?php $controls->checkbox_group('sex', 'n', 'Not specified'); ?></div>
276
+ <div style="clear: both"></div>
277
+ <div class="hints">
278
+ Leaving all sex options unselected means to NOT filter by sex.
279
+ </div>
280
+ </td>
281
+ </tr>
282
+ <tr valign="top">
283
+ <th>Preferences</th>
284
+ <td>
285
+ <?php $controls->preferences_group('preferences', true); ?>
286
+ <div style="clear: both"></div>
287
+ <div class="hints">
288
+ Leaving all preferences unselected means to NOT filter by preference.
289
+ </div>
290
+ </td>
291
+ </tr>
292
+ <tr valign="top">
293
+ <th>Track message links?</th>
294
+ <td>
295
+ <?php $controls->yesno('track'); ?>
296
+ <div class="hints">
297
+ When this option is enabled, each link in the email text will be rewritten and clicks
298
+ on them intercepted.
299
+ </div>
300
+ </td>
301
+ </tr>
302
+ </table>
303
+ </div>
304
+
305
+
306
+ <div id="tabs-4">
307
+ <table class="form-table">
308
+ <tr valign="top">
309
+ <th>Send on</th>
310
+ <td>
311
+ <?php $controls->datetime('send_on'); ?> (<?php echo date_i18n(get_option('date_format') . ' ' . get_option('time_format')); ?> )
312
+ </td>
313
+ </tr>
314
+ <tr valign="top">
315
+ <th>Email status</th>
316
+ <td><?php echo $email['status']; ?></td>
317
+ </tr>
318
+ <tr valign="top">
319
+ <th>Email sent</th>
320
+ <td><?php echo $email['sent']; ?> of <?php echo $email['total']; ?></td>
321
+ </tr>
322
+ </table>
323
+ </div>
324
+
325
+
326
+ </div>
327
+
328
+ </form>
329
+ </div>
emails/emails.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once NEWSLETTER_INCLUDES_DIR . '/themes.php';
4
+ require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
5
+
6
+ class NewsletterEmails extends NewsletterModule {
7
+
8
+ const VERSION = '1.0.4';
9
+
10
+ /**
11
+ * @var NewsletterThemes
12
+ */
13
+ var $themes;
14
+
15
+ static $instance;
16
+
17
+ /**
18
+ *
19
+ * @return NewsletterEmails
20
+ */
21
+ static function instance() {
22
+ if (self::$instance == null) {
23
+ self::$instance = new NewsletterEmails();
24
+ }
25
+ return self::$instance;
26
+ }
27
+
28
+ function __construct() {
29
+ parent::__construct('emails', self::VERSION);
30
+ $this->themes = new NewsletterThemes('emails');
31
+ }
32
+
33
+ function upgrade() {
34
+ global $wpdb, $charset_collate;
35
+
36
+ $wpdb->query("alter table " . NEWSLETTER_EMAILS_TABLE . " add column token varchar(10) not null default ''");
37
+ $wpdb->query("alter table " . NEWSLETTER_EMAILS_TABLE . " drop column visibility");
38
+
39
+ // Force a token to email without one already set.
40
+ $token = self::get_token();
41
+ $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set token='" . $token . "' where token=''");
42
+
43
+ return true;
44
+ }
45
+
46
+ function save_options($options) {
47
+ $this->options = $options;
48
+ parent::save_options($options);
49
+ // This separately save the theme options
50
+ $this->themes->save_options($options['theme'], $options);
51
+ }
52
+
53
+ /**
54
+ * Returns the current selected theme.
55
+ */
56
+ function get_current_theme() {
57
+ $theme = $this->options['theme'];
58
+ if (empty($theme)) return 'blank';
59
+ else return $theme;
60
+ }
61
+
62
+ function get_current_theme_options() {
63
+ return $this->themes->get_options($this->get_current_theme());
64
+ }
65
+
66
+ /**
67
+ * Returns the file path to a theme using the theme overriding rules.
68
+ * @param type $theme
69
+ * @param type $file
70
+ */
71
+ function get_theme_file_path($theme, $file) {
72
+ return $this->themes->get_file_path($theme);
73
+ }
74
+
75
+ function get_current_theme_file_path($file) {
76
+ return $this->themes->get_file_path($this->get_current_theme(), $file);
77
+ }
78
+
79
+ function get_current_theme_url() {
80
+ return $this->themes->get_theme_url($this->get_current_theme());
81
+ }
82
+
83
+ /**
84
+ * Returns true if the emails database still contain old 2.5 format emails.
85
+ *
86
+ * @return boolean
87
+ */
88
+ function has_old_emails() {
89
+ return $this->store->get_count(NEWSLETTER_EMAILS_TABLE, "where type='email'") > 0;
90
+ }
91
+
92
+ function convert_old_emails() {
93
+ global $newsletter;
94
+ $list = $newsletter->get_emails('email', ARRAY_A);
95
+ foreach ($list as &$email) {
96
+ $email['type'] = 'message';
97
+ $query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'";
98
+
99
+ if ($email['list'] != 0) $query .= " and list_" . $email['list'] . "=1";
100
+ $email['preferences'] = $email['list'];
101
+
102
+ if (!empty($email['sex'])) {
103
+ $query .= " and sex='" . $email['sex'] . "'";
104
+ }
105
+ $email['query'] = $query;
106
+
107
+ $newsletter->save_email($email);
108
+ }
109
+ }
110
+
111
+ }
emails/index.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
4
+ $controls = new NewsletterControls();
5
+ $module = NewsletterEmails::instance();
6
+
7
+ if ($controls->is_action('convert')) {
8
+ $module->convert_old_emails();
9
+ $controls->messages = 'Converted!';
10
+ }
11
+
12
+ if ($controls->is_action('unconvert')) {
13
+ $wpdb->query("update wp_newsletter_emails set type='email' where type='message'");
14
+ $controls->messages = 'Unconverted!';
15
+ }
16
+
17
+ if ($controls->is_action('send')) {
18
+ $newsletter->hook_newsletter();
19
+ $controls->messages .= 'Delivery engine triggered.';
20
+ }
21
+
22
+ if ($controls->is_action('copy')) {
23
+ $original = Newsletter::instance()->get_email($_POST['btn']);
24
+ $email = array();
25
+ $email['subject'] = $original->subject;
26
+ $email['message'] = $original->message;
27
+ $email['message_text'] = $original->message_text;
28
+ $email['type'] = 'message';
29
+ Newsletter::instance()->save_email($email);
30
+ $controls->messages .= 'Message duplicated.';
31
+ }
32
+
33
+ if ($controls->is_action('delete')) {
34
+ Newsletter::instance()->delete_email($_POST['btn']);
35
+ $controls->messages .= 'Message deleted';
36
+ }
37
+
38
+ if ($controls->is_action('delete_selected')) {
39
+ $r = Newsletter::instance()->delete_email($_POST['ids']);
40
+ $controls->messages .= $r . ' message(s) deleted';
41
+ }
42
+
43
+ $emails = Newsletter::instance()->get_emails('message');
44
+ ?>
45
+
46
+ <div class="wrap">
47
+
48
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletters-module'; ?>
49
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
50
+
51
+ <h2>Newsletters Module</h2>
52
+
53
+ <div class="preamble">
54
+ <p>Here you can manage your messages: compose, deliver, monitor.</p>
55
+ </div>
56
+
57
+ <?php $controls->show(); ?>
58
+
59
+ <form method="post" action="admin.php?page=newsletter/emails/index.php">
60
+ <?php $controls->init(); ?>
61
+
62
+ <?php if ($module->has_old_emails()) { ?>
63
+ <div class="newsletter-message">
64
+ <p>
65
+ Your Newsletter installation has emails still in old format. To get them listed, you should convert them in
66
+ a new format. Would you to convert them now?
67
+ </p>
68
+ <p>
69
+ <?php $controls->button('convert', 'Convert now'); ?>
70
+ <?php //$controls->button('unconvert', 'Unconvert (DEBUG)'); ?>
71
+ </p>
72
+ </div>
73
+ <?php } ?>
74
+
75
+ <p>
76
+ <a href="admin.php?page=newsletter/emails/new.php" class="button">New message</a>
77
+ <?php $controls->button_confirm('delete_selected', 'Delete selected messages', 'Proceed?'); ?>
78
+ <?php $controls->button('send', 'Trigger now'); ?>
79
+ </p>
80
+ <table class="widefat" style="width: auto">
81
+ <thead>
82
+ <tr>
83
+ <th>&nbsp;</th>
84
+ <th>Id</th>
85
+ <th>Subject</th>
86
+ <th>Date</th>
87
+ <th>Status</th>
88
+ <th>&nbsp;</th>
89
+ <th>&nbsp;</th>
90
+ <th>&nbsp;</th>
91
+ <th>&nbsp;</th>
92
+ </tr>
93
+ </thead>
94
+
95
+ <tbody>
96
+ <?php foreach ($emails as &$email) { ?>
97
+ <tr>
98
+ <td><input type="checkbox" name="ids[]" value="<?php echo $email->id; ?>"/></td>
99
+ <td><?php echo $email->id; ?></td>
100
+ <td><?php echo htmlspecialchars($email->subject); ?></td>
101
+ <td><?php echo $module->date($email->send_on); ?></td>
102
+ <td>
103
+ <?php echo $email->status; ?>
104
+ (<?php echo $email->sent; ?>/<?php echo $email->total; ?>)
105
+ </td>
106
+ <td><a class="button" href="admin.php?page=newsletter/emails/edit.php&amp;id=<?php echo $email->id; ?>">Edit</a></td>
107
+ <td>
108
+ <a class="button" href="<?php echo NewsletterStatistics::instance()->get_statistics_url($email->id); ?>">Statistics</a>
109
+ </td>
110
+ <td><?php $controls->button_confirm('copy', 'Copy', 'Proceed?', $email->id); ?></td>
111
+ <td><?php $controls->button_confirm('delete', 'Delete', 'Proceed?', $email->id); ?></td>
112
+ </tr>
113
+ <?php } ?>
114
+ </tbody>
115
+ </table>
116
+ </form>
117
+ </div>
emails/new.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $controls = new NewsletterControls();
4
+ $module = NewsletterEmails::instance();
5
+ $store = NewsletterStore::instance();
6
+
7
+
8
+ if ($controls->is_action('change')) {
9
+ // Recover the selected theme options, if any, and use them.
10
+ $controls->merge($module->themes->get_options($controls->data['theme']));
11
+ $module->save_options($controls->data);
12
+ }
13
+
14
+ if ($controls->is_action('save')) {
15
+ $module->save_options($controls->data);
16
+ }
17
+
18
+ if ($controls->is_action('create') || $controls->is_action('test')) {
19
+ $module->save_options($controls->data);
20
+
21
+ if ($controls->is_action('test')) {
22
+ $users = $controls->get_test_subscribers();
23
+ $email = new stdClass();
24
+ $email->id = 0;
25
+ $email->message = $controls->data['message'];
26
+ $email->message_text = $controls->data['message_text'];
27
+ $email->subject = 'Test subject';
28
+ $email->track = $controls->data['track'];
29
+ $email->type = 'message';
30
+ $newsletter->send($email, $users);
31
+ }
32
+
33
+ if ($controls->is_action('create')) {
34
+ $email = array();
35
+ $email['status'] = 'new';
36
+ $email['subject'] = 'Here the email subject';
37
+ $email['track'] = 1;
38
+
39
+ $theme_options = $module->get_current_theme_options();
40
+ $theme_url = $module->get_current_theme_url();
41
+
42
+ ob_start();
43
+ include $module->get_current_theme_file_path('theme.php');
44
+ $email['message'] = ob_get_clean();
45
+ ob_end_clean();
46
+
47
+ ob_start();
48
+ include $module->get_current_theme_file_path('theme-text.php');
49
+ $email['message_text'] = ob_get_clean();
50
+ ob_end_clean();
51
+
52
+ $email['type'] = 'message';
53
+ $email['send_on'] = time();
54
+ $email = Newsletter::instance()->save_email($email);
55
+ ?>
56
+ <script>
57
+ location.href="admin.php?page=newsletter/emails/edit.php&id=<?php echo $email->id; ?>";
58
+ </script>
59
+ <?php
60
+ return;
61
+ }
62
+ }
63
+
64
+ if ($controls->data == null) {
65
+ $controls->data = NewsletterEmails::instance()->get_options();
66
+ }
67
+
68
+
69
+
70
+ function newsletter_emails_update_options($options) {
71
+ add_option('newsletter_emails', '', null, 'no');
72
+ update_option('newsletter_emails', $options);
73
+ }
74
+
75
+ function newsletter_emails_update_theme_options($theme, $options) {
76
+ $x = strrpos($theme, '/');
77
+ if ($x !== false) {
78
+ $theme = substr($theme, $x+1);
79
+ }
80
+ add_option('newsletter_emails_' . $theme, '', null, 'no');
81
+ update_option('newsletter_emails_' . $theme, $options);
82
+ }
83
+
84
+ function newsletter_emails_get_options() {
85
+ $options = get_option('newsletter_emails', array());
86
+ return $options;
87
+ }
88
+
89
+ function newsletter_emails_get_theme_options($theme) {
90
+ $x = strrpos($theme, '/');
91
+ if ($x !== false) {
92
+ $theme = substr($theme, $x+1);
93
+ }
94
+ $options = get_option('newsletter_emails_' . $theme, array());
95
+ return $options;
96
+ }
97
+ ?>
98
+
99
+ <div class="wrap">
100
+
101
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletters-module'; ?>
102
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
103
+
104
+ <h2>Newsletters Module</h2>
105
+
106
+
107
+ <?php $controls->show(); ?>
108
+
109
+ <!--
110
+ <p>
111
+ <strong>Select a theme</strong> to compose a precompiled message, tune the theme setting, look at the previews and then preceed to the
112
+ composer.
113
+ </p>
114
+ -->
115
+
116
+ <form method="post" action="admin.php?page=newsletter/emails/new.php" id="newsletter-form">
117
+ <?php $controls->init(); ?>
118
+ <div style="padding: .6em; border: 1px solid #ddd; background-color: #f4f4f4; border-radius: 3px;">
119
+ <strong>Choose a theme</strong>
120
+ <?php $controls->select('theme', NewsletterEmails::instance()->themes->get_all()); ?>
121
+ <?php $controls->button('change', 'Change theme'); ?>
122
+ <a href="http://www.satollo.net/plugins/newsletter/newsletter-themes" target="_blank">(more about themes)</a>
123
+ </div>
124
+
125
+ <p>
126
+ <?php $controls->button('save', 'Save options and refresh'); ?>
127
+ <?php $controls->button('create', 'Create the email'); ?>
128
+ </p>
129
+
130
+ <div id="tabs">
131
+ <ul>
132
+ <li><a href="#tabs-2">Preview</a></li>
133
+ <li><a href="#tabs-3">Preview (textual)</a></li>
134
+ <li><a href="#tabs-1">Theme options</a></li>
135
+ <li><a href="#tabs-4">Help</a></li>
136
+ </ul>
137
+
138
+ <div id="tabs-1">
139
+ <?php
140
+ include NewsletterEmails::instance()->get_current_theme_file_path('theme-options.php');
141
+ ?>
142
+ </div>
143
+
144
+
145
+ <div id="tabs-2">
146
+ <iframe src="<?php echo NEWSLETTER_URL; ?>/emails/preview.php?<?php echo time(); ?>" width="100%" height="500"></iframe>
147
+ </div>
148
+
149
+
150
+ <div id="tabs-3">
151
+ <iframe src="<?php echo NEWSLETTER_URL; ?>/emails/preview-text.php?<?php echo time(); ?>" width="100%" height="500"></iframe>
152
+ </div>
153
+
154
+ <div id="tabs-4">
155
+ <p>
156
+ Custom themes can be created starting from the supplied themes (on <code>wp_content/plugins/newsletter/emails/themes</code>
157
+ each subfolder is a theme)
158
+ and copied inside the <code>wp_content/newsletter/emails/themes</code> folder.
159
+ </p>
160
+ </div>
161
+ </div>
162
+
163
+ </form>
164
+ </div>
emails/preview-text.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ header('Content-Type: text/plain');
3
+
4
+ include '../../../../wp-load.php';
5
+
6
+ if (get_current_user_id() != 1)
7
+ die('Only the administrator can view the preview');
8
+
9
+ // Used by theme code
10
+ $theme_options = NewsletterEmails::instance()->get_current_theme_options();
11
+
12
+ include(NewsletterEmails::instance()->get_current_theme_file_path('theme-text.php'));
emails/preview.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ if (get_current_user_id() != 1)
6
+ die('Only the administrator can view the preview');
7
+
8
+ // Used by theme code
9
+ $theme_options = NewsletterEmails::instance()->get_current_theme_options();
10
+ $theme_url = NewsletterEmails::instance()->get_current_theme_url();
11
+
12
+ include(NewsletterEmails::instance()->get_current_theme_file_path('theme.php'));
emails/themes/blank/theme-options.php ADDED
@@ -0,0 +1 @@
 
1
+ <p>This theme has no options</p>
emails/themes/blank/theme-text.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Blank newsletter!
2
+
3
+ ---
4
+ To unsubscribe follow the link
5
+ {unsubscription_url}
6
+ to edit your profile follow the link
7
+ {profile_url}
emails/themes/blank/theme.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <p>Blank newsletter!</p>
2
+
3
+ <p>
4
+ To unsubscribe <a href="{unsubscription_url}">click here</a>, to edit your profile
5
+ <a href="{profile_url}">click here</a>.
6
+ </p>
emails/themes/default/theme-options.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <table class="form-table">
2
+ <tr>
3
+ <th>Base color</th>
4
+ <td><?php $controls->color('theme_color'); ?></td>
5
+ </tr>
6
+ <tr>
7
+ <th>Add latest posts</th>
8
+ <td><?php $controls->checkbox('theme_posts'); ?></td>
9
+ </tr>
10
+ </table>
emails/themes/default/theme-text.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ View this email online here: {email_url}.
2
+ ---
3
+
4
+ Blank newsletter!
5
+
6
+ ---
7
+ To change your subscription follow {profile_url}.
emails/themes/default/theme.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // TODO: Documentation!!!
3
+
4
+ global $newsletter;
5
+
6
+ $color = $theme_options['theme_color'];
7
+ if (empty($color)) $color = '#0088cc';
8
+
9
+ if (isset($theme_options['theme_posts'])) $posts = get_posts(array('shoposts'=>10));
10
+
11
+ ?><!DOCTYPE html>
12
+ <html>
13
+ <head>
14
+ <style type="text/css" media="all">
15
+ a {
16
+ text-decoration: none;
17
+ color: <?php echo $color; ?>;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body style="background-color: #ddd; font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 14px; color: #666; margin: 0 auto; padding: 0;">
22
+ <br>
23
+ <table align="center">
24
+ <tr>
25
+ <td style="font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 14px; color: #666;">
26
+ <div style="text-align: left; max-width: 500px; border-top: 10px solid <?php echo $color; ?>; border-bottom: 3px solid <?php echo $color; ?>;">
27
+ <div style="padding: 10px 20px; color: #000; font-size: 20px; background-color: #EFEFEF; border-bottom: 1px solid #ddd">
28
+ <?php echo get_option('blogname'); ?>
29
+ </div>
30
+ <div style="padding: 20px; background-color: #fff; line-height: 18px">
31
+
32
+ <p style="text-align: center"><a href="{email_url}">View this email online</a></p>
33
+
34
+ <?php if (empty($posts)) { ?>
35
+ <p>Here you can start to write your message. Be polite with your readers! Do not forget the subsject of this message.</p>
36
+ <?php } else { ?>
37
+ <table cellpadding="5">
38
+ <?php foreach ($posts as $post) { setup_postdata($post); ?>
39
+ <tr>
40
+ <td><a href="<?php echo get_permalink(); ?>"><img width="75" src="<?php echo newsletter_get_post_image($post->ID); ?>" alt="image"></a></td>
41
+ <td valign="top"><a href="<?php echo get_permalink(); ?>" style="font-size: 20px; line-height: 26px"><?php the_title(); ?></a></td>
42
+ </tr>
43
+ <?php } ?>
44
+ </table>
45
+ <?php } ?>
46
+
47
+ <p>To change your subscription, <a href="{profile_url}">click here</a>.
48
+ </div>
49
+
50
+ </div>
51
+ </td>
52
+ </tr>
53
+ </table>
54
+ </body>
55
+ </html>
emails/themes/linear/images/facebook.png ADDED
Binary file
emails/themes/linear/images/purple.png ADDED
Binary file
emails/themes/linear/images/twitter.png ADDED
Binary file
emails/themes/linear/images/youtube.png ADDED
Binary file
emails/themes/linear/theme-options.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <table class="form-table">
2
+ <tr>
3
+ <th>Facebook link</th>
4
+ <td><?php $controls->text('theme_facebook'); ?></td>
5
+ </tr>
6
+ <tr>
7
+ <th>Twitter link</th>
8
+ <td><?php $controls->text('theme_twitter'); ?></td>
9
+ </tr>
10
+ <tr>
11
+ <th>YouTube link</th>
12
+ <td><?php $controls->text('theme_youtube'); ?></td>
13
+ </tr>
14
+ </table>
emails/themes/linear/theme.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $posts = get_posts();
3
+ $theme_options['theme_background'] = 'purple.png';
4
+ ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
5
+ <html>
6
+ <head>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8
+
9
+ <style type="text/css">
10
+ </style>
11
+ </head>
12
+ <body leftmargin="0" marginwidth="0" topmargin="0" marginheight="0" offset="0" style="background-image:url(<?php echo $theme_url; ?>/images/<?php echo $theme_options['theme_background']; ?>);background-repeat: repeat-x;background-color: #efefef;">
13
+
14
+ <table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
15
+ <tr>
16
+ <td align="center" valign="top">
17
+
18
+ <table border="0" cellpadding="10" cellspacing="0" width="600" style="background-color: #FAFAFA;">
19
+ <tr>
20
+ <td valign="top">
21
+ <table border="0" cellpadding="10" cellspacing="0" width="100%">
22
+ <tr>
23
+ <td valign="top" align="left" style="color: #505050;font-family: Arial;font-size: 10px;">
24
+ You are receiving this email because you subscribed to <?php echo get_option('blogname'); ?>. <a href="{profile_url}">Click here to change your subscription</a>.
25
+ </td>
26
+ <td valign="top" width="190" align="left" style="color: #505050;font-family: Arial;font-size: 10px;">
27
+ Is this email not displaying correctly?<br><a href="{email_url}" style="color: #336699;font-weight: normal;text-decoration: underline;">View it online</a>.
28
+ </td>
29
+ </tr>
30
+ </table>
31
+ </td>
32
+ </tr>
33
+ </table>
34
+
35
+ <table border="0" cellpadding="0" cellspacing="0" width="600" bgcolor="#FFFFFF">
36
+ <tr>
37
+ <td align="center" valign="middle" height="150" style="color: #202020;font-family: Arial;font-size: 34px;font-weight: bold;line-height: 100%;padding: 5px 0 -2px 0;border-width: 1px 0px;border-style: solid;border-color: #dddddd;">
38
+ <?php echo get_option('blogname'); ?>
39
+ </td>
40
+ </tr>
41
+ </table>
42
+ <table border="0" cellpadding="0" cellspacing="0" width="600" bgcolor="#FFFFFF">
43
+ <tr>
44
+
45
+ <td valign="top">
46
+ <table border="0" cellpadding="20" cellspacing="0" width="200">
47
+ <tr>
48
+ <td valign="top" align="left" style="color: #505050;font-family: Arial;font-size: 12px;line-height: 150%;">
49
+ Sidebar text
50
+ </td>
51
+ </tr>
52
+ <tr>
53
+ <td valign="top" align="left">
54
+ <?php foreach (array('facebook','twitter','youtube') as $social) { ?>
55
+ <?php if (!empty($theme_options["theme_$social"])) { ?>
56
+ <a href="<?php echo $theme_options["theme_$social"]; ?>"><img src="<?php echo $theme_url; ?>/images/<?php echo $social; ?>.png" alt="<?php echo $social; ?>"></a>
57
+ <?php } ?>
58
+ <?php } ?>
59
+ </td>
60
+ </tr>
61
+ </table>
62
+ </td>
63
+
64
+ <td valign="top">
65
+ <table border="0" cellpadding="20" cellspacing="0" width="100%" bgcolor="#ffffff">
66
+ <tr>
67
+ <td valign="top">
68
+
69
+ <?php foreach ($posts as $post) { setup_postdata($post); ?>
70
+ <h2 style="color: #202020;font-family: Arial;font-size: 20px;font-weight: bold;margin-top: 0;margin-bottom: 10px;border-bottom: 1px solid #efefef;">
71
+ <?php the_title(); ?>
72
+ </h2>
73
+ <center><img src="<?php echo newsletter_get_post_image($post->ID, 'medium');?>"></center>
74
+ <div style="color: #505050;font-family: Arial;font-size: 14px;line-height: 150%;">
75
+ <?php the_excerpt(); ?>
76
+ </div>
77
+ <?php } ?>
78
+
79
+ </td>
80
+ </tr>
81
+ </table>
82
+ </td>
83
+
84
+ </tr>
85
+ </table>
86
+ </td>
87
+ </tr>
88
+
89
+ </table>
90
+ <br><br>
91
+
92
+ </body>
93
+ </html>
emails/themes/theme-1/theme-options.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This is a pre packaged theme options page. Every option name
4
+ * must start with "theme_" so Newsletter can distinguish them from other
5
+ * options that are specific to the object using the theme.
6
+ *
7
+ * An array of theme default options should always be present and that default options
8
+ * should be merged with the current complete set of options as shown below.
9
+ *
10
+ * Every theme can define its own set of options, the will be used in the theme.php
11
+ * file while composing the email body. Newsletter knows nothing about theme options
12
+ * (other than saving them) and does not use or relies on any of them.
13
+ *
14
+ * For multilanguage purpose you can actually check the constants "WP_LANG", until
15
+ * a decent system will be implemented.
16
+ */
17
+ $theme_defaults = array(
18
+ 'theme_max_posts'=>10,
19
+
20
+ 'theme_categories'=>array()
21
+ );
22
+
23
+ // Mandatory!
24
+ $controls->merge_defaults($theme_defaults);
25
+ ?>
26
+ <p>This theme build an email loading all new posts after the date of the last run.</p>
27
+ <table class="form-table">
28
+ <tr valign="top">
29
+ <th>Max new posts to include</th>
30
+ <td>
31
+ <?php $controls->text('theme_max_posts', 5); ?> (it defaults to 10 if empty or invalid)
32
+ </td>
33
+ </tr>
34
+ <tr valign="top">
35
+ <th>Categories to include</th>
36
+ <td>
37
+ <?php
38
+ $categories = get_categories();
39
+ foreach ($categories as $c) {
40
+ echo '<div class="nl-checkbox-group">';
41
+ $controls->checkbox_group('theme_categories', $c->cat_ID, esc_html($c->cat_name));
42
+ echo '</div>';
43
+ }
44
+ ?>
45
+ <div style="clear: both"></div>
46
+ <div class="hints">
47
+ Leaving all categories unselected means to NOT filter by category.
48
+ </div>
49
+ </td>
50
+ </tr>
51
+ </table>
52
+
emails/themes/theme-1/theme-text.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $newsletter; // Newsletter object
3
+ global $post; // Current post managed by WordPress
4
+
5
+ // This file is included inside a function so it inherit all the local variables.
6
+
7
+ // Since a theme has it's own options, it must check if there is new content to send
8
+ // out.
9
+ // Inside $theme_options['last_time'] there is the time stamps of the last run
10
+ // to be used to decide if we need to stop or not.
11
+
12
+ $filters = array();
13
+
14
+ $filters['showposts'] = (int)$theme_options['max_posts'];
15
+ if ($filters['showposts'] == 0) $filters['showposts'] = 10;
16
+
17
+ // This theme has an option with categories to be included.
18
+ if (is_array($theme_options['categories'])) {
19
+ $filters['cat'] = implode(',', $theme_options['categories']);
20
+ }
21
+
22
+ $posts = get_posts($filters);
23
+
24
+ // Retrieve the posts asking them to WordPress
25
+ $posts = get_posts($filters);
26
+
27
+ ?><?php echo $theme_options['theme_opening_text']; ?>
28
+
29
+ * <?php echo $theme_options['theme_title']; ?>
30
+
31
+
32
+ <?php
33
+ foreach ($posts as $post) {
34
+ // Setup the post (WordPress requirement)
35
+ setup_postdata($post);
36
+ ?>
37
+ <?php the_title(); ?>
38
+
39
+ <?php the_permalink(); ?>
40
+
41
+
42
+ <?php } ?>
43
+
44
+
45
+ <?php echo $theme_options['theme_footer_text']; ?>
46
+
emails/themes/theme-1/theme.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $newsletter; // Newsletter object
3
+ global $post; // Current post managed by WordPress
4
+
5
+ /*
6
+ * Some variabled are prepared by Newsletter Plus and are available inside the theme,
7
+ * for example the theme options used to build the email body as configured by blog
8
+ * owner.
9
+ *
10
+ * $theme_options - is an associative array with theme options: every option starts
11
+ * with "theme_" as required. See the theme-options.php file for details.
12
+ * Inside that array there are the autmated email options as well, if needed.
13
+ * A special value can be present in theme_options and is the "last_run" which indicates
14
+ * when th automated email has been composed last time. Is should be used to find if
15
+ * there are now posts or not.
16
+ *
17
+ * $is_test - if true it means we are composing an email for test purpose.
18
+ */
19
+
20
+
21
+ // This array will be passed to WordPress to extract the posts
22
+ $filters = array();
23
+
24
+ // Maximum number of post to retrieve
25
+ $filters['showposts'] = (int)$theme_options['theme_max_posts'];
26
+ if ($filters['showposts'] == 0) $filters['showposts'] = 10;
27
+
28
+
29
+ // Include only posts from specified categories. Do not filter per category is no
30
+ // one category has been selected.
31
+ if (is_array($theme_options['theme_categories'])) {
32
+ $filters['cat'] = implode(',', $theme_options['theme_categories']);
33
+ }
34
+
35
+ // Retrieve the posts asking them to WordPress
36
+ $posts = get_posts($filters);
37
+
38
+ ?>
39
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
40
+ <html>
41
+ <head>
42
+ <title></title>
43
+ </head>
44
+
45
+ <body>
46
+ <table bgcolor="#c0c0c0" width="100%" cellpadding="20" cellspacing="0" border="0">
47
+ <tr>
48
+ <td align="center">
49
+ <table width="500" bgcolor="#ffffff" align="center" cellspacing="10" cellpadding="0" style="border: 1px solid #666;">
50
+ <tr>
51
+ <td style="font-size: 30px">
52
+ <i><?php echo get_option('blogname'); ?></i>
53
+ </td>
54
+ </tr>
55
+ <tr>
56
+ <td style="border-top: 1px solid #eee; border-bottom: 1px solid #eee; font-size: 12px; color: #999">
57
+ <br />NEWSLETTER<br /><br />
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td style="font-size: 14px; color: #666">
62
+ <p>Dear {name}, here an update from <?php echo get_option('blogname'); ?>.</p>
63
+ </td>
64
+ </tr>
65
+ <?php
66
+ // Do not use &post, it leads to problems...
67
+ foreach ($posts as $post) {
68
+
69
+ // Setup the post (WordPress requirement)
70
+ setup_postdata($post);
71
+
72
+ // The theme can "suggest" a subject replacing the one configured, for example. In this case
73
+ // the theme, is there is no subject, suggest the first post title.
74
+ if (empty($theme_options['subject'])) $theme_options['subject'] = $post->post_title;
75
+
76
+ // Extract a thumbnail, return null if no thumb can be found
77
+ $image = nt_post_image(get_the_ID());
78
+ ?>
79
+ <tr>
80
+ <td style="font-size: 14px; color: #666">
81
+ <?php if ($image != null) { ?>
82
+ <img src="<?php echo $image; ?>" alt="picture" align="left"/>
83
+ <?php } ?>
84
+ <p><a href="<?php echo get_permalink(); ?>" style="font-size: 16px; color: #000; text-decoration: none"><?php the_title(); ?></a></p>
85
+
86
+ <?php the_excerpt(); ?>
87
+ </td>
88
+ </tr>
89
+ <?php
90
+ }
91
+ ?>
92
+ <tr>
93
+ <td style="border-top: 1px solid #eee; border-bottom: 1px solid #eee; font-size: 12px; color: #999">
94
+ You received this email because you subscribed for it as {email}. If you'd like, you can <a href="{unsubscription_url}">unsubscribe</a>.
95
+ </td>
96
+ </tr>
97
+ </table>
98
+ </td>
99
+ </tr>
100
+ </table>
101
+ </body>
102
+ </html>
{themes → emails/themes}/theme-3/header.jpg RENAMED
File without changes
emails/themes/theme-3/theme-options.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This is a pre packaged theme options page. Every option name
4
+ * must start with "theme_" so Newsletter can distinguish them from other
5
+ * options that are specific to the object using the theme.
6
+ *
7
+ * An array of theme default options should always be present and that default options
8
+ * should be merged with the current complete set of options as shown below.
9
+ *
10
+ * Every theme can define its own set of options, the will be used in the theme.php
11
+ * file while composing the email body. Newsletter knows nothing about theme options
12
+ * (other than saving them) and does not use or relies on any of them.
13
+ *
14
+ * For multilanguage purpose you can actually check the constants "WP_LANG", until
15
+ * a decent system will be implemented.
16
+ */
17
+ $theme_defaults = array(
18
+ 'theme_max_posts'=>10,
19
+
20
+ 'theme_categories'=>array()
21
+ );
22
+
23
+ // Mandatory!
24
+ $controls->merge_defaults($theme_defaults);
25
+ ?>
26
+ <p>This theme build an email loading all new posts after the date of the last run.</p>
27
+ <table class="form-table">
28
+ <tr valign="top">
29
+ <th>Max new posts to include</th>
30
+ <td>
31
+ <?php $controls->text('theme_max_posts', 5); ?> (it defaults to 10 if empty or invalid)
32
+ </td>
33
+ </tr>
34
+ <tr valign="top">
35
+ <th>Categories to include</th>
36
+ <td>
37
+ <?php
38
+ $categories = get_categories();
39
+ foreach ($categories as $c) {
40
+ echo '<div class="nl-checkbox-group">';
41
+ $controls->checkbox_group('theme_categories', $c->cat_ID, esc_html($c->cat_name));
42
+ echo '</div>';
43
+ }
44
+ ?>
45
+ <div style="clear: both"></div>
46
+ <div class="hints">
47
+ Leaving all categories unselected means to NOT filter by category.
48
+ </div>
49
+ </td>
50
+ </tr>
51
+ </table>
52
+
{themes → emails/themes}/theme-3/theme.php RENAMED
@@ -1,13 +1,48 @@
1
  <?php
2
- // If you want to translate or customize this theme, just copy the file inside the folder
3
- // wp-content/plugins/newsletter-pro-custom/themes
4
- // (create it if it does not exist) and the a new theme called "theme-1" will appear
5
- // on autocompose menu. You can rename the file if you want.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- $posts = new WP_Query();
8
- $posts->query(array('showposts' => 10, 'post_status' => 'publish'));
9
  ?>
 
 
 
 
 
10
 
 
11
  <br />
12
 
13
  <table cellspacing="0" align="center" border="0" style="max-width:600px; width:600px; background-color: #eee;" cellpadding="0" width="600px">
@@ -28,11 +63,20 @@ $posts->query(array('showposts' => 10, 'post_status' => 'publish'));
28
  <tr>
29
  <td>
30
  <table cellpadding="0" cellspacing="0" border="0" bordercolor="" width="100%" bgcolor="#ffffff">
31
- <?php
32
- while ($posts->have_posts()) {
33
- $posts->the_post();
34
- $image = nt_post_image(get_the_ID());
35
- ?>
 
 
 
 
 
 
 
 
 
36
  <tr>
37
  <td style="font-family: Arial; font-size: 12px">
38
  <?php if ($image != null) { ?>
@@ -65,3 +109,5 @@ $posts->query(array('showposts' => 10, 'post_status' => 'publish'));
65
  </td>
66
  </tr>
67
  </table>
 
 
1
  <?php
2
+ global $newsletter; // Newsletter object
3
+ global $post; // Current post managed by WordPress
4
+
5
+ /*
6
+ * Some variabled are prepared by Newsletter Plus and are available inside the theme,
7
+ * for example the theme options used to build the email body as configured by blog
8
+ * owner.
9
+ *
10
+ * $theme_options - is an associative array with theme options: every option starts
11
+ * with "theme_" as required. See the theme-options.php file for details.
12
+ * Inside that array there are the autmated email options as well, if needed.
13
+ * A special value can be present in theme_options and is the "last_run" which indicates
14
+ * when th automated email has been composed last time. Is should be used to find if
15
+ * there are now posts or not.
16
+ *
17
+ * $is_test - if true it means we are composing an email for test purpose.
18
+ */
19
+
20
+
21
+ // This array will be passed to WordPress to extract the posts
22
+ $filters = array();
23
+
24
+ // Maximum number of post to retrieve
25
+ $filters['showposts'] = (int)$theme_options['theme_max_posts'];
26
+ if ($filters['showposts'] == 0) $filters['showposts'] = 10;
27
+
28
+
29
+ // Include only posts from specified categories. Do not filter per category is no
30
+ // one category has been selected.
31
+ if (is_array($theme_options['theme_categories'])) {
32
+ $filters['cat'] = implode(',', $theme_options['theme_categories']);
33
+ }
34
+
35
+ // Retrieve the posts asking them to WordPress
36
+ $posts = get_posts($filters);
37
 
 
 
38
  ?>
39
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
40
+ <html>
41
+ <head>
42
+ <title></title>
43
+ </head>
44
 
45
+ <body>
46
  <br />
47
 
48
  <table cellspacing="0" align="center" border="0" style="max-width:600px; width:600px; background-color: #eee;" cellpadding="0" width="600px">
63
  <tr>
64
  <td>
65
  <table cellpadding="0" cellspacing="0" border="0" bordercolor="" width="100%" bgcolor="#ffffff">
66
+ <?php
67
+ // Do not use &post, it leads to problems...
68
+ foreach ($posts as $post) {
69
+
70
+ // Setup the post (WordPress requirement)
71
+ setup_postdata($post);
72
+
73
+ // The theme can "suggest" a subject replacing the one configured, for example. In this case
74
+ // the theme, is there is no subject, suggest the first post title.
75
+ if (empty($theme_options['subject'])) $theme_options['subject'] = $post->post_title;
76
+
77
+ // Extract a thumbnail, return null if no thumb can be found
78
+ $image = nt_post_image(get_the_ID());
79
+ ?>
80
  <tr>
81
  <td style="font-family: Arial; font-size: 12px">
82
  <?php if ($image != null) { ?>
109
  </td>
110
  </tr>
111
  </table>
112
+ </body>
113
+ </html>
emails/themes/vimeo-like/bg_header_email.gif ADDED
Binary file
emails/themes/vimeo-like/theme-options.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This is a pre packaged theme options page. Every option name
4
+ * must start with "theme_" so Newsletter can distinguish them from other
5
+ * options that are specific to the object using the theme.
6
+ *
7
+ * An array of theme default options should always be present and that default options
8
+ * should be merged with the current complete set of options as shown below.
9
+ *
10
+ * Every theme can define its own set of options, the will be used in the theme.php
11
+ * file while composing the email body. Newsletter knows nothing about theme options
12
+ * (other than saving them) and does not use or relies on any of them.
13
+ *
14
+ * For multilanguage purpose you can actually check the constants "WP_LANG", until
15
+ * a decent system will be implemented.
16
+ */
17
+ $theme_defaults = array(
18
+ 'theme_max_posts'=>5,
19
+ 'theme_read_more'=>'Read More',
20
+ 'theme_pre_message'=>'This email has been sent to {email} because subscribed and confirmed on ' . get_option('blogname') . '. <a href="{profile_url}">Click here to modify you subscription or unsubscribe</a>.',
21
+ 'theme_categories'=>array()
22
+ );
23
+
24
+ // Mandatory!
25
+ $controls->merge_defaults($theme_defaults);
26
+ ?>
27
+ <p>This theme build an email loading all new posts after the date of the last run.</p>
28
+ <table class="form-table">
29
+ <tr valign="top">
30
+ <th>Max new posts to include</th>
31
+ <td>
32
+ <?php $controls->text('theme_max_posts', 5); ?> (it defaults to 10 if empty or invalid)
33
+ </td>
34
+ </tr>
35
+ <tr valign="top">
36
+ <th>Categories to include</th>
37
+ <td>
38
+ <?php
39
+ $categories = get_categories();
40
+ foreach ($categories as $c) {
41
+ echo '<div class="nl-checkbox-group">';
42
+ $controls->checkbox_group('theme_categories', $c->cat_ID, esc_html($c->cat_name));
43
+ echo '</div>';
44
+ }
45
+ ?>
46
+ <div style="clear: both"></div>
47
+ <div class="hints">
48
+ Leaving all categories unselected means to NOT filter by category.
49
+ </div>
50
+ </td>
51
+ </tr>
52
+ <tr valign="top">
53
+ <th>Pre message</th>
54
+ <td>
55
+ <?php $controls->text('theme_pre_message', 70); ?>
56
+ </td>
57
+ </tr>
58
+ <tr valign="top">
59
+ <th>Read more label</th>
60
+ <td>
61
+ <?php $controls->text('theme_read_more'); ?>
62
+ </td>
63
+ </tr>
64
+ </table>
emails/themes/vimeo-like/theme-text.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ This email can be seen only on rich text email client. To see it online visit:
2
+
3
+ {email_url}
4
+
5
+ To change your subscription visit:
6
+
7
+ {profile_url}
8
+
9
+ Thank you!
emails/themes/vimeo-like/theme.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $newsletter; // Newsletter object
3
+ global $post; // Current post managed by WordPress
4
+
5
+ /*
6
+ * Some variabled are prepared by Newsletter Plus and are available inside the theme,
7
+ * for example the theme options used to build the email body as configured by blog
8
+ * owner.
9
+ *
10
+ * $theme_options - is an associative array with theme options: every option starts
11
+ * with "theme_" as required. See the theme-options.php file for details.
12
+ * Inside that array there are the autmated email options as well, if needed.
13
+ * A special value can be present in theme_options and is the "last_run" which indicates
14
+ * when th automated email has been composed last time. Is should be used to find if
15
+ * there are now posts or not.
16
+ *
17
+ * $is_test - if true it means we are composing an email for test purpose.
18
+ */
19
+
20
+
21
+ // This array will be passed to WordPress to extract the posts
22
+ $filters = array();
23
+
24
+ // Maximum number of post to retrieve
25
+ $filters['showposts'] = (int)$theme_options['theme_max_posts'];
26
+ if ($filters['showposts'] == 0) $filters['showposts'] = 10;
27
+
28
+
29
+ // Include only posts from specified categories. Do not filter per category is no
30
+ // one category has been selected.
31
+ if (is_array($theme_options['theme_categories'])) {
32
+ $filters['cat'] = implode(',', $theme_options['theme_categories']);
33
+ }
34
+
35
+ // Retrieve the posts asking them to WordPress
36
+ $posts = get_posts($filters);
37
+
38
+ // Styles
39
+ $color = $theme_options['theme_color'];
40
+ if (empty($color)) $color = '#777';
41
+
42
+ $font = $theme_options['theme_font'];
43
+ $font_size = $theme_options['theme_font_size'];
44
+
45
+ ?>
46
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
47
+ <html>
48
+ <head>
49
+ <title></title>
50
+ <style>
51
+ * {
52
+ font-family: <?php echo $font; ?>;
53
+ font-size: <?php echo $font_size; ?>;
54
+ }
55
+ </style>
56
+ </head>
57
+ <body>
58
+
59
+ <table style="background:#ffffff" width="600" align="center" border="0" cellpadding="0" cellspacing="0">
60
+
61
+ <tbody><tr><td style="color:#9ab;font:normal 11px helvetica,sans-serif;text-align:center;padding:10px 0 20px 0"><?php echo $theme_options['theme_pre_message']; ?></td></tr>
62
+
63
+ <tr><td><img src="<?php echo $theme_url; ?>/bg_header_email.gif" alt=""></td></tr>
64
+
65
+ <tr>
66
+
67
+ <td style="border:1px dotted #e1e2e3;border-top:none;border-bottom:3px solid #e1e2e3;background:#ffffff">
68
+
69
+
70
+
71
+ <table width="100%" align="center" border="0" cellpadding="20" cellspacing="0">
72
+
73
+ <tbody><tr><td style="background:#ffffff">
74
+
75
+
76
+
77
+ <p style="color:#456;font-family:arial,sans-serif;font-size:24px;line-height:1.2;margin:15px 0;padding:0"><a href="<?php echo get_option('home'); ?>" style="color:#28c;text-decoration:none" target="_blank"><?php echo get_option('blogname'); ?></a></p>
78
+
79
+
80
+ <?php
81
+ foreach ($posts as $post) {
82
+ setup_postdata($post);
83
+ $image = nt_post_image(get_the_ID());
84
+ ?>
85
+
86
+
87
+ <table style="width:100%;color:#456;font:normal 12px/1.5em helvetica,sans-serif;margin:15px 0 0 0;padding:0 0 15px 0;border-bottom:1px dotted #e1e2e3">
88
+
89
+ <tbody><tr>
90
+
91
+ <td style="width:100%;padding:0 10px 0 0;vertical-align:top">
92
+
93
+ <p style="font-family:arial,sans-serif;color:#456;font-size:20px;line-height:22px;margin:0;padding:0"><strong><a href="<?php echo get_permalink(); ?>" style="color:#456;text-decoration:none" target="_blank"><?php the_title(); ?></a></strong></p>
94
+
95
+ <p style="font-family:arial,sans-serif;line-height:1.5em;margin:15px 0;padding:0"><?php the_excerpt(); ?>. </p>
96
+
97
+ </td>
98
+
99
+ <td style="vertical-align:middle; width: 100px">
100
+
101
+ <a href="<?php echo get_permalink(); ?>" target="_blank"><img src="<?php echo $image; ?>" alt="" width="100" border="0" height="100"></a>
102
+
103
+ <p style="background:#2786c2;text-align:center;margin:10px 0 0 0;font-size:11px;line-height:14px;font-family:arial,sans-serif;padding:4px 2px;border-radius:4px"><a href="<?php echo get_permalink(); ?>" style="color:#fff;text-decoration:none" target="_blank"><strong><?php echo $theme_options['theme_read_more']; ?></strong></a></p>
104
+
105
+ </td>
106
+
107
+ </tr>
108
+
109
+ </tbody></table>
110
+
111
+ <br>
112
+ <?php
113
+ }
114
+ ?>
115
+
116
+
117
+
118
+
119
+ <br><br>
120
+ <p style="color:#456;font-family:arial,sans-serif;font-size:12px;line-height:1.6em;font-style:italic;margin:0 0 15px 0;padding:0">
121
+ Have a nice reading!</p>
122
+
123
+ <p style="color:#456;font-family:arial,sans-serif;font-size:12px;line-height:1.6em;font-style:italic;margin:0 0 15px 0;padding:0">Good bye</p>
124
+
125
+
126
+
127
+
128
+
129
+ </td></tr></tbody></table></td></tr></tbody></table>
130
+
131
+
132
+
133
+
134
+ </body>
135
+ </html>
136
+
example/base.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is only a module example. Pay attention to correct all the "NewsletterBase" references, even most of them
4
+ * are only useful for code completion inside IDEs like Netbeans.
5
+ */
6
+ require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
7
+
8
+ class NewsletterBase extends NewsletterModule {
9
+
10
+ /**
11
+ * Use to track the current version. A version change, see the construction, triggers an upgrade.
12
+ */
13
+ const VERSION = '1.0.0';
14
+
15
+ /**
16
+ * Internal variable used to keep the module instance when the singleton pattern is used (recommended).
17
+ * @var NewsletterBase
18
+ */
19
+ static private $instance;
20
+
21
+ /**
22
+ * Create an instance of this module. Cannot done on NewsletterModule since there is no way to reference the
23
+ * extending class (need PHP 5.3 to do that).
24
+ * @return NewsletterBase
25
+ */
26
+ static function instance() {
27
+ if (self::$instance == null) {
28
+ self::$instance = new NewsletterBase();
29
+ }
30
+ return self::$instance;
31
+ }
32
+
33
+ function __construct() {
34
+ // Pay attetion to module name that must be tha same of the containing folder basename. The module name
35
+ // can be replaced with basename(dirname(__FILE__)) but it's a lot less efficient.
36
+ parent::__construct('base', self::VERSION);
37
+ }
38
+
39
+ /**
40
+ * Called when there is a version change or when explicitely triggered. Add here the installation/upgrade code.
41
+ *
42
+ * @global type $wpdb
43
+ * @global type $charset_collate
44
+ */
45
+ function upgrade() {
46
+ global $wpdb, $charset_collate;
47
+
48
+ // That call loads initialize the module options if they are not present on database. Multilangua options can
49
+ // be stored under the "language" folder of this module. See documentation on site.
50
+ parent::upgrade();
51
+
52
+ // Use $this->upgrade_query() se the query will be logged.
53
+ //$this->upgrade_query("create table if not exists {$wpdb->prefix}newsletter_table (id int auto_increment, primary key (id)) $charset_collate");
54
+ }
55
+
56
+ }
57
+
58
+ // Registering here the actions/filters we avoid to initialize the module when not needed.
59
+ add_action('newsletter_admin_menu', 'newsletter_base_admin_menu');
60
+
61
+ /**
62
+ * Add menu pages for this module.
63
+ * @global Newsletter $newsletter
64
+ */
65
+ function newsletter_base_admin_menu() {
66
+ global $newsletter;
67
+
68
+ // The global $newsletter variable can be used in place of Newsletter::instance() that is less performant. Newsletter
69
+ // class is always initialized and an instance associated to the $newsletter global variable.
70
+ $newsletter->add_menu_page('statistics', 'index', 'Statistics');
71
+ $newsletter->add_admin_page('statistics', 'view', 'Statistics');
72
+ }
73
+
example/index.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $module = NewsletterStatistics::instance();
4
+ $controls = new NewsletterControls();
5
+ $emails = Newsletter::instance()->get_emails();
6
+
7
+ if ($controls->is_action('save')) {
8
+ $module->save_options($controls->data);
9
+ $controls->messages = 'Saved.';
10
+ }
11
+ ?>
12
+
13
+ <div class="wrap">
14
+ <h2>Statistics</h2>
15
+ <p>
16
+ This is the basic version of Newsletter Statistics module. Single email statistics can be accessed directly from
17
+ email list on Emails, Updates, Follow Up panels. Below the complete list.
18
+ </p>
19
+
20
+ <form method="post">
21
+ <?php $controls->init(); ?>
22
+
23
+ <table class="form-table">
24
+ <tr>
25
+ <th>Log level</th>
26
+ <td>
27
+ <?php $controls->log_level(); ?>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+ <p><?php $controls->button('save', 'Save'); ?>
32
+ </form>
33
+
34
+ <table class="widefat" style="width: auto">
35
+ <thead>
36
+ <tr>
37
+ <th>Id</th>
38
+ <th>Subject</th>
39
+ <th>Date</th>
40
+ <th>Type</th>
41
+ <th>Status</th>
42
+ <th>&nbsp;</th>
43
+ </tr>
44
+ </thead>
45
+
46
+ <tbody>
47
+ <?php foreach ($emails as &$email) { ?>
48
+ <tr>
49
+ <td><?php echo $email->id; ?></td>
50
+ <td><?php echo htmlspecialchars($email->subject); ?></td>
51
+ <td><?php echo $email->date; ?></td>
52
+ <td><?php echo $email->type; ?></td>
53
+ <td>
54
+ <?php echo $email->status; ?>
55
+ (<?php echo $email->sent; ?>/<?php echo $email->total; ?>)
56
+ </td>
57
+ <td>
58
+ <a class="button" href="<?php echo NewsletterStatistics::instance()->get_statistics_url($email->id); ?>">statistics</a>
59
+ </td>
60
+ </tr>
61
+ <?php } ?>
62
+ </tbody>
63
+ </table>
64
+ </div>
65
+
66
+ </div>
feed/whatis.txt ADDED
@@ -0,0 +1 @@
 
1
+ Reserved for feed integration.
header.php CHANGED
@@ -1,15 +1,20 @@
1
- <table cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #ddd; background-color: #f7f7ff; padding: 10px;">
2
- <tr>
3
- <td valign="middle" align="left" width="110">
4
- <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Y6JXSA7BSU2L" target="_blank"><img src="http://www.satollo.net/images/donate.gif"/></a>
5
- </td>
6
- <td valign="top" align="left">
7
- <strong>Your donation is like a diamond: it's forever</strong>.
8
- More about <a href="http://www.satollo.net/donations" target="_blank">donations I receive</a>.
9
- See <a href="http://www.satollo.net/plugins" target="_blank"><strong>other plugins</strong></a> that can be useful for your blog.
10
- <form method="post" action="http://www.satollo.net/subscribe" target="_blank">
11
- Subscribe my newsletter: <input name="ne" value="Your email" onclick="if (this.defaultValue==this.value) this.value=''" onblur="if (this.value=='') this.value=this.defaultValue"> <input type="hidden" value="s" name="na"> <input type="hidden" value="plugin" name="nr"><input type="submit" value="Subscribe">
12
- </form>
13
- </td>
14
- </tr>
15
- </table>
 
 
 
 
 
1
+ <div id="newsletter-header">
2
+ <a href="<?php echo $help_url?$help_url:'http://www.satollo.net/plugins/newsletter/newsletter-configuration'; ?>" target="_blank">Get Help</a>
3
+ <a href="http://www.satollo.net/plugins/newsletter/newsletter-faq" target="_blank">FAQ</a>
4
+ <a href="http://www.satollo.net/forums" target="_blank">Forum</a>
5
+ <a href="http://www.satollo.net/plugins/newsletter/newsletter-collaboration" target="_blank">Collaboration</a>
6
+
7
+ <form style="display: inline; margin: 0;" action="http://www.satollo.net/wp-content/plugins/newsletter/do/subscribe.php" method="post" target="_blank">
8
+ Subscribe to satollo.net <input type="email" name="ne" required placeholder="Your email">
9
+ <input type="submit" value="Go">
10
+ </form>
11
+
12
+ <a href="https://www.facebook.com/satollo.net" target="_blank"><img style="vertical-align: bottom" src="<?php echo NEWSLETTER_URL; ?>/images/facebook.png"></a>
13
+
14
+ <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Y6JXSA7BSU2L" target="_blank"><img style="vertical-align: bottom" src="<?php echo NEWSLETTER_URL; ?>/images/donate.png"></a>
15
+ <a href="http://www.satollo.net/donations" target="_blank">Even <b>1$</b> helps: read more</a>
16
+
17
+ Engine next run in <?php echo wp_next_scheduled('newsletter') - time(); ?> s
18
+ </div>
19
+
20
+ <?php $newsletter->warnings(); ?>
images/donate.png ADDED
Binary file
images/facebook.png ADDED
Binary file
images/popup/bg.png ADDED
Binary file
images/popup/button.png ADDED
Binary file
images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
images/ui-bg_flat_75_ffffff_40x100.png ADDED
Binary file
images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
images/ui-icons_222222_256x240.png ADDED
Binary file
images/ui-icons_2e83ff_256x240.png ADDED
Binary file
images/ui-icons_454545_256x240.png ADDED
Binary file
images/ui-icons_888888_256x240.png ADDED
Binary file
images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
import.php DELETED
@@ -1,188 +0,0 @@
1
- <?php
2
-
3
- @include_once 'commons.php';
4
-
5
- $options = stripslashes_deep($_POST['options']);
6
-
7
- $options_profile = get_option('newsletter_profile');
8
-
9
- if ($action == 'import') {
10
- @set_time_limit(100000);
11
- $csv = stripslashes($_POST['csv']);
12
- $lines = explode("\n", $csv);
13
-
14
- $error = array();
15
- // Subscriber array with base user data from selected lists and other default values
16
- $subscriber = array();
17
- for ($i=1; $i<=NEWSLETTER_LIST_MAX; $i++)
18
- {
19
- $list = 'list_' . $i;
20
- if (isset($options[$list])) $subscriber[$list] = 1;
21
- else {
22
- if ($options['mode'] == 'overwrite') $subscriber[$list] = 0;
23
- }
24
- }
25
-
26
- foreach ($lines as $line) {
27
- // Parse the CSV line
28
- $line = trim($line);
29
- if ($line == '') continue;
30
- if ($line[0] == '#') continue;
31
- $separator = $options['separator'];
32
- if ($separator == 'tab') $separator = "\t";
33
- $data = explode($separator, $line);
34
-
35
-
36
- // Builds a subscriber data structure
37
- $subscriber['email'] = $newsletter->normalize_email($data[0]);
38
- if (!$newsletter->is_email($subscriber['email']))
39
- {
40
- $error[] = '[INVALID EMAIL] ' . $line;
41
- continue;
42
- }
43
- $subscriber['name'] = $newsletter->normalize_name($data[1]);
44
- $subscriber['surname'] = $newsletter->normalize_name($data[2]);
45
-
46
- for ($i=1; $i<=NEWSLETTER_PROFILE_MAX; $i++) {
47
- if (isset($data[$i+2])) $subscriber['profile_' . $i] = $data[$i+2];
48
- }
49
-
50
- // May by here for a previous saving
51
- unset($subscriber['id']);
52
-
53
- // Try to load the user by email
54
- $user = $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix .
55
- "newsletter where email=%s", $subscriber['email']), ARRAY_A);
56
-
57
- // If the user is new, we simply add it
58
- if (empty($user)) {
59
- newsletter_save($subscriber);
60
- continue;
61
- }
62
-
63
- if ($options['mode'] == 'skip') {
64
- $error[] = '[DUPLICATE] ' . $line;
65
- continue;
66
- }
67
-
68
- if ($options['mode'] == 'overwrite') {
69
- $subscriber['id'] = $user['id'];
70
- newsletter_save($subscriber);
71
- continue;
72
- }
73
-
74
- if ($options['mode'] == 'update') {
75
- newsletter_save(array_merge($user, $subscriber));
76
- }
77
- }
78
- }
79
-
80
- $nc = new NewsletterControls();
81
- $nc->errors($errors);
82
- $nc->messages($messages);
83
-
84
-
85
- $lists = array('0' => 'All');
86
- for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
87
- $lists['' . $i] = '(' . $i . ') ' . $options_profile['list_' . $i];
88
- }
89
- ?>
90
-
91
- <div class="wrap">
92
- <h2>Newsletter Import/Export</h2>
93
- <form method="post" action="">
94
- <?php $nc->init(); ?>
95
- <h3>Export</h3>
96
- <table class="form-table">
97
- <tr>
98
- <td>
99
- <?php $nc->select('list', $lists); ?>
100
- <?php $nc->button('export', 'Export'); ?>
101
- </td>
102
- </tr>
103
- </table>
104
- </form>
105
-
106
- <h3>Import</h3>
107
- <p>
108
- Please consider to break up your input list if you get errors, blank pages or partially imported lists: it can be a time/resource limit
109
- of your provider. It's safe to import the same list a second time, no duplications will occur.
110
- </p>
111
- <p>
112
- Import list format is:<br /><br />
113
- <b>email 1</b><i>[separator]</i><b>first name 1</b><i>[separator]</i><b>last name 1</b><i>[new line]</i><br />
114
- <b>email 2</b><i>[separator]</i><b>first name 2</b><i>[separator]</i><b>last name 2</b><i>[new line]</i><br />
115
- <br />
116
- where the [separator] must be selected from the available ones. The "name" field is optional, while the "email" field is
117
- mandatory. Empty lines and lines starting with "#" will be skipped.
118
- </p>
119
-
120
-
121
- <?php require_once 'header.php'; ?>
122
-
123
- <?php if (!empty($error)) { ?>
124
-
125
- <h3><?php _e('Rows with errors', 'newsletter'); ?></h3>
126
-
127
- <textarea wrap="off" style="width: 100%; height: 150px; font-size: 11px; font-family: monospace"><?php echo htmlspecialchars(implode("\n", $error))?></textarea>
128
-
129
- <?php } ?>
130
-
131
- <form method="post" action="">
132
- <?php $nc->init(); ?>
133
-
134
- <h3><?php _e('CSV text with subscribers', 'newsletter'); ?></h3>
135
- <table class="form-table">
136
- <tr valign="top">
137
- <th>Lists to associate</th>
138
- <td>
139
- <?php for ($i=1; $i<=NEWSLETTER_LIST_MAX; $i++) { ?>
140
- <?php $nc->checkbox('list_' . $i, '(' . $i . ') ' . htmlspecialchars($options_profile['list_' . $i])); ?><br />
141
- <?php } ?>
142
- <div class="hints">
143
- Every new imported or updated subscribers will be associate with selected lists above.
144
- </div>
145
- </td>
146
- </tr>
147
- <!--
148
- <tr valign="top">
149
- <th>Follow up</th>
150
- <td>
151
- <?php $nc->select('followup', array('none'=>'None', 'activate'=>'Activate')); ?>
152
- </td>
153
- </tr>
154
- -->
155
- <tr valign="top">
156
- <th>Import mode</th>
157
- <td>
158
- If the email is already present:
159
- <?php $nc->select('mode', array('update'=>'Update', 'overwrite'=>'Overwrite', 'skip'=>'Skip')); ?>
160
- <div class="hints">
161
- <strong>Update</strong>: the user data is updated: if a user was associated to some lists, those associations will be
162
- kept and the new one added; his name is updated as well.<br />
163
- <strong>Overwrite</strong>: recreate the subscriber with specified data (CSV+lists).<br />
164
- <strong>Skip</strong>: leave untouched user's data when he's already subscribed.
165
- </div>
166
- </td>
167
- </tr>
168
- <tr valign="top">
169
- <th>Separator</th>
170
- <td>
171
- <?php $nc->select('separator', array(';'=>'Semicolon', ','=>'Comma', 'tab'=>'Tabulation')); ?>
172
- </td>
173
- </tr>
174
-
175
-
176
- <tr valign="top">
177
- <th>CSV text</th>
178
- <td>
179
- <textarea name="csv" wrap="off" style="width: 100%; height: 300px; font-size: 11px; font-family: monospace"></textarea>
180
- </td>
181
- </table>
182
-
183
- <p class="submit">
184
- <?php $nc->button('import', 'Import'); ?>
185
- </p>
186
- </form>
187
-
188
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/controls.php ADDED
@@ -0,0 +1,450 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class NewsletterControls {
4
+
5
+ var $data;
6
+ var $action = false;
7
+ var $button_data = '';
8
+
9
+ function __construct($options = null) {
10
+ if ($options == null) $this->data = stripslashes_deep($_POST['options']);
11
+ else $this->data = $options;
12
+
13
+ $this->action = $_REQUEST['act'];
14
+
15
+ if (isset($_REQUEST['btn'])) $this->button_data = $_REQUEST['btn'];
16
+
17
+ // Fields analysis
18
+ $fields = $_REQUEST['fields'];
19
+ if (is_array($fields)) {
20
+ foreach ($fields as $name=>$type) {
21
+ if ($type == 'datetime') {
22
+ // Ex. The user insert 01/07/2012 14:30 and it set the time zone to +2. We cannot use the
23
+ // mktime, since it uses the time zone of the machine. We create the time as if we are on
24
+ // GMT 0 and then we subtract the GMT offset (the example date and time on GMT+2 happens
25
+ // "before").
26
+
27
+ $time = gmmktime($_REQUEST[$name . '_hour'], 0, 0,
28
+ $_REQUEST[$name . '_month'], $_REQUEST[$name . '_day'], $_REQUEST[$name . '_year']);
29
+ echo $_REQUEST[$name . '_year'];
30
+ $time -= get_option('gmt_offset') * 3600;
31
+ //echo date('Y-m-j', $time);
32
+ // echo $time;
33
+ $this->data[$name] = $time;
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ function merge($options) {
40
+ if (!is_array($options)) return;
41
+ if ($this->data == null) $this->data = array();
42
+ $this->data = array_merge($this->data, $options);
43
+ }
44
+
45
+ function merge_defaults($defaults) {
46
+ if ($this->data == null) $this->data = $defaults;
47
+ else $this->data = array_merge($defaults, $this->data);
48
+ }
49
+
50
+ /**
51
+ * Return true is there in an asked action is no action name is specified or
52
+ * true is the requested action matches the passed action.
53
+ * Dies if it is not a safe call.
54
+ */
55
+ function is_action($action = null) {
56
+ if ($action == null) return $this->action != null;
57
+ if ($this->action == null) return false;
58
+ if ($this->action != $action) return false;
59
+ if (check_admin_referer()) return true;
60
+ die('Invalid call');
61
+ }
62
+
63
+ /**
64
+ * Show the errors and messages.
65
+ */
66
+ function show() {
67
+ if (!empty($this->errors)) {
68
+ echo '<div class="newsletter-error">';
69
+ echo $this->errors;
70
+ echo '</div>';
71
+ }
72
+ if (!empty($this->messages)) {
73
+ echo '<div class="newsletter-message">';
74
+ echo $this->messages;
75
+ echo '</div>';
76
+ }
77
+ }
78
+
79
+ function yesno($name) {
80
+ $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
81
+
82
+ echo '<select style="width: 60px" name="options[' . $name . ']">';
83
+ echo '<option value="0"';
84
+ if ($value == 0) echo ' selected';
85
+ echo '>No</option>';
86
+ echo '<option value="1"';
87
+ if ($value == 1) echo ' selected';
88
+ echo '>Yes</option>';
89
+ echo '</select>&nbsp;&nbsp;&nbsp;';
90
+ }
91
+
92
+ function enabled($name) {
93
+ $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
94
+
95
+ echo '<select style="width: 100px" name="options[' . $name . ']">';
96
+ echo '<option value="0"';
97
+ if ($value == 0) echo ' selected';
98
+ echo '>Disabled</option>';
99
+ echo '<option value="1"';
100
+ if ($value == 1) echo ' selected';
101
+ echo '>Enabled</option>';
102
+ echo '</select>';
103
+ }
104
+
105
+ function checkbox_group($name, $value, $label = '') {
106
+ echo '<input type="checkbox" id="' . $name . '" name="options[' . $name . '][]" value="' . $value . '"';
107
+ if (is_array($this->data[$name]) && array_search($value, $this->data[$name]) !== false)
108
+ echo ' checked="checked"';
109
+ echo '/>';
110
+ if ($label != '') echo ' <label for="' . $name . '">' . $label . '</label>';
111
+ }
112
+
113
+ function select_group($name, $options) {
114
+ echo '<select name="options[' . $name . '][]">';
115
+
116
+ foreach ($options as $key => $label) {
117
+ echo '<option value="' . $key . '"';
118
+ if (is_array($this->data[$name]) && array_search($value, $this->data[$name]) !== false) echo ' selected';
119
+ echo '>' . htmlspecialchars($label) . '</option>';
120
+ }
121
+
122
+ echo '</select>';
123
+ }
124
+
125
+ function select($name, $options, $first = null) {
126
+ $value = $this->data[$name];
127
+
128
+ echo '<select id="options-' . $name . '" name="options[' . $name . ']">';
129
+ if (!empty($first)) {
130
+ echo '<option value="">' . htmlspecialchars($first) . '</option>';
131
+ }
132
+ foreach ($options as $key => $label) {
133
+ echo '<option value="' . $key . '"';
134
+ if ($value == $key) echo ' selected';
135
+ echo '>' . htmlspecialchars($label) . '</option>';
136
+ }
137
+ echo '</select>';
138
+ }
139
+
140
+ function select_grouped($name, $groups) {
141
+ $value = $this->data[$name];
142
+
143
+ echo '<select name="options[' . $name . ']">';
144
+
145
+ foreach ($groups as $group) {
146
+ echo '<optgroup label="' . htmlspecialchars($group['']) . '">';
147
+ if (!empty($group)) {
148
+ foreach ($group as $key => $label) {
149
+ if ($key == '') continue;
150
+ echo '<option value="' . $key . '"';
151
+ if ($value == $key) echo ' selected';
152
+ echo '>' . htmlspecialchars($label) . '</option>';
153
+ }
154
+ }
155
+ echo '</optgroup>';
156
+ }
157
+ echo '</select>';
158
+ }
159
+
160
+ /**
161
+ * Generated a select control with all available templates. From version 3 there are
162
+ * only on kind of templates, they are no more separated by type.
163
+ */
164
+ function themes($name, $theme_dir, $theme_dir2 = null) {
165
+ $list = array();
166
+
167
+ $handle = @opendir($theme_dir);
168
+
169
+ while ($file = readdir($handle)) {
170
+ if ($file == '.' || $file == '..') continue;
171
+ // TODO: optimize the string concatenation
172
+ if (!is_dir($theme_dir . '/' . $file)) continue;
173
+ if (!is_file($theme_dir . '/' . $file . '/theme.php')) continue;
174
+ $list[$theme_dir . '/' . $file] = $file;
175
+ }
176
+ closedir($handle);
177
+
178
+ if ($theme_dir2 != null && is_dir($theme_dir2)) {
179
+ $handle = @opendir($theme_dir2);
180
+ $list = array();
181
+ while ($file = readdir($handle)) {
182
+ if ($file == '.' || $file == '..') continue;
183
+ // TODO: optimize the string concatenation
184
+ if (!is_dir($theme_dir2 . '/' . $file)) continue;
185
+ if (!is_file($theme_dir2 . '/' . $file . '/theme.php')) continue;
186
+ $list[$theme_dir2 . '/' . $file] = $file;
187
+ }
188
+ closedir($handle);
189
+ }
190
+
191
+ $this->select($name, $list);
192
+ }
193
+
194
+ function value($name) {
195
+ echo htmlspecialchars($this->data[$name]);
196
+ }
197
+
198
+ function value_date($name) {
199
+ $time = $this->data[$name];
200
+ echo gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
201
+ }
202
+
203
+ function text($name, $size = 20) {
204
+ echo '<input name="options[' . $name . ']" type="text" size="' . $size . '" value="';
205
+ echo htmlspecialchars($this->data[$name]);
206
+ echo '"/>';
207
+ }
208
+
209
+ function text_email($name, $size = 40) {
210
+ echo '<input name="options[' . $name . ']" type="email" placeholder="Valid email address" size="' . $size . '" value="';
211
+ echo htmlspecialchars($this->data[$name]);
212
+ echo '"/>';
213
+ }
214
+
215
+ function hidden($name) {
216
+ echo '<input name="options[' . $name . ']" type="hidden" value="';
217
+ echo htmlspecialchars($this->data[$name]);
218
+ echo '"/>';
219
+ }
220
+
221
+ function button($action, $label, $function = null) {
222
+ if ($function != null) {
223
+ echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.act.value=\'' . $action . '\';' . htmlspecialchars($function) . '"/>';
224
+ } else {
225
+ echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.act.value=\'' . $action . '\';this.form.submit()"/>';
226
+ }
227
+ }
228
+
229
+ function button_confirm($action, $label, $message, $data = '') {
230
+ echo '<input class="button-secondary" type="button" value="' . $label . '" onclick="this.form.btn.value=\'' . $data . '\';this.form.act.value=\'' . $action . '\';if (confirm(\'' .
231
+ htmlspecialchars($message) . '\')) this.form.submit()"/>';
232
+ }
233
+
234
+ function editor($name, $rows = 5, $cols = 75) {
235
+ echo '<textarea class="visual" name="options[' . $name . ']" style="width: 100%" wrap="off" rows="' . $rows . '">';
236
+ echo htmlspecialchars($this->data[$name]);
237
+ echo '</textarea>';
238
+ }
239
+
240
+ function textarea($name, $width = '100%', $height = '50') {
241
+ echo '<textarea class="dymanic" name="options[' . $name . ']" wrap="off" style="width:' . $width . ';height:' . $height . '">';
242
+ echo htmlspecialchars($this->data[$name]);
243
+ echo '</textarea>';
244
+ }
245
+
246
+ function textarea_fixed($name, $width = '100%', $height = '50') {
247
+ echo '<textarea name="options[' . $name . ']" wrap="off" style="width:' . $width . ';height:' . $height . 'px">';
248
+ echo htmlspecialchars($this->data[$name]);
249
+ echo '</textarea>';
250
+ }
251
+
252
+ function email($prefix) {
253
+ echo 'Subject:<br />';
254
+ $this->text($prefix . '_subject', 70);
255
+ echo '<br />Message:<br />';
256
+ $this->editor($prefix . '_message');
257
+ }
258
+
259
+ function checkbox($name, $label = '') {
260
+ echo '<input type="checkbox" id="' . $name . '" name="options[' . $name . ']" value="1"';
261
+ if (!empty($this->data[$name])) echo ' checked="checked"';
262
+ echo '/>';
263
+ if ($label != '') echo '&nbsp;<label for="' . $name . '">' . $label . '</label>';
264
+ }
265
+
266
+ function color($name) {
267
+ echo $this->text($name, 10);
268
+ }
269
+
270
+ /**
271
+ * Creates a set of checkbox to activate the profile preferences. Every checkbox has a DIV around to
272
+ * be formatted.
273
+ */
274
+ function preferences_group($name = 'preferences', $skip_empty = false) {
275
+ $options_profile = get_option('newsletter_profile');
276
+
277
+ echo '<div class="newsletter-preferences-group">';
278
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
279
+ if (empty($options_profile['list_' . $i])) continue;
280
+ echo '<div class="newsletter-preferences-item">';
281
+ $this->checkbox_group($name, $i, '(' . $i . ') ' . htmlspecialchars($options_profile['list_' . $i]));
282
+ echo '</div>';
283
+ }
284
+ echo '<div style="clear: both"></div>';
285
+ echo '<a href="http://www.satollo.net/plugins/newsletter/newsletter-preferences" target="_blank">Click here know more about preferences.</a> They can be configured on Subscription/Form field panel.';
286
+ echo '</div>';
287
+ }
288
+
289
+ function preferences($name = 'preferences', $skip_empty = false) {
290
+ $options_profile = get_option('newsletter_profile');
291
+ echo '<div class="newsletter-preferences-group">';
292
+
293
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
294
+ if (empty($options_profile['list_' . $i])) continue;
295
+ echo '<div class="newsletter-preferences-item">';
296
+ $this->checkbox($name . '_' . $i, '(' . $i . ') ' . htmlspecialchars($options_profile['list_' . $i]));
297
+ echo '</div>';
298
+ }
299
+ echo '<div style="clear: both"></div>';
300
+ echo '<a href="http://www.satollo.net/plugins/newsletter/newsletter-preferences" target="_blank">Click here know more about preferences.</a> They can be configured on Subscription/Form field panel.';
301
+ echo '</div>';
302
+
303
+ }
304
+
305
+ function date($name) {
306
+ $this->hidden($name);
307
+ $year = date('Y', $this->data[$name]);
308
+ $day = date('j', $this->data[$name]);
309
+ $month = date('m', $this->data[$name]);
310
+ $onchange = "this.form.elements['options[" . $name . "]'].value = new Date(document.getElementById('" . $name . "_year').value, document.getElementById('" . $name . "_month').value, document.getElementById('" . $name . "_day').value, 12, 0, 0).getTime()/1000";
311
+ echo '<select id="' . $name . '_month" onchange="' . $onchange . '">';
312
+ for ($i = 0; $i < 12; $i++) {
313
+ echo '<option value="' . $i . '"';
314
+ if ($month - 1 == $i) echo ' selected';
315
+ echo '>' . date('F', mktime(0, 0, 0, $i + 1, 1, 2000)) . '</option>';
316
+ }
317
+ echo '</select>';
318
+
319
+ echo '<select id="' . $name . '_day" onchange="' . $onchange . '">';
320
+ for ($i = 1; $i <= 31; $i++) {
321
+ echo '<option value="' . $i . '"';
322
+ if ($day == $i) echo ' selected';
323
+ echo '>' . $i . '</option>';
324
+ }
325
+ echo '</select>';
326
+
327
+ echo '<select id="' . $name . '_year" onchange="' . $onchange . '">';
328
+ for ($i = 2011; $i <= 2021; $i++) {
329
+ echo '<option value="' . $i . '"';
330
+ if ($year == $i) echo ' selected';
331
+ echo '>' . $i . '</option>';
332
+ }
333
+ echo '</select>';
334
+ }
335
+
336
+ function datetime($name) {
337
+ echo '<input type="hidden" name="fields[' . $name . ']" value="datetime">';
338
+ $time = $this->data[$name] + get_option('gmt_offset') * 3600;
339
+ $year = gmdate('Y', $time);
340
+ $day = gmdate('j', $time);
341
+ $month = gmdate('m', $time);
342
+ $hour = gmdate('H', $time);
343
+
344
+ echo '<select name="' . $name . '_month">';
345
+ for ($i = 1; $i <= 12; $i++) {
346
+ echo '<option value="' . $i . '"';
347
+ if ($month == $i) echo ' selected';
348
+ echo '>' . date('F', mktime(0, 0, 0, $i, 1, 2000)) . '</option>';
349
+ }
350
+ echo '</select>';
351
+
352
+ echo '<select name="' . $name . '_day">';
353
+ for ($i = 1; $i <= 31; $i++) {
354
+ echo '<option value="' . $i . '"';
355
+ if ($day == $i) echo ' selected';
356
+ echo '>' . $i . '</option>';
357
+ }
358
+ echo '</select>';
359
+
360
+ echo '<select name="' . $name . '_year">';
361
+ for ($i = 2011; $i <= 2021; $i++) {
362
+ echo '<option value="' . $i . '"';
363
+ if ($year == $i) echo ' selected';
364
+ echo '>' . $i . '</option>';
365
+ }
366
+ echo '</select>';
367
+
368
+ echo '<select name="' . $name . '_hour">';
369
+ for ($i = 0; $i <= 23; $i++) {
370
+ echo '<option value="' . $i . '"';
371
+ if ($hour == $i) echo ' selected';
372
+ echo '>' . $i . ':00</option>';
373
+ }
374
+ echo '</select>';
375
+ }
376
+
377
+ function hours($name) {
378
+ $hours = array();
379
+ for ($i = 0; $i < 24; $i++) {
380
+ $hours['' . $i] = '' . $i;
381
+ }
382
+ $this->select($name, $hours);
383
+ }
384
+
385
+ function days($name) {
386
+ $days = array(0 => 'Every day', 1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', 7 => 'Sunday');
387
+ $this->select($name, $days);
388
+ }
389
+
390
+ function init() {
391
+ echo '<script type="text/javascript">
392
+ jQuery(document).ready(function(){
393
+ jQuery("textarea.dynamic").focus(function() {
394
+ jQuery("textarea.dynamic").css("height", "50px");
395
+ jQuery(this).css("height", "400px");
396
+ });
397
+ tabs = jQuery("#tabs").tabs({ cookie: { expires: 30 } });
398
+ });
399
+ </script>
400
+ ';
401
+ echo '<input name="act" type="hidden" value=""/>';
402
+ echo '<input name="btn" type="hidden" value=""/>';
403
+ wp_nonce_field();
404
+ }
405
+
406
+ function log_level($name = 'log_level') {
407
+ $this->select($name, array(0 => 'None', 2 => 'Error', 3 => 'Normal', 4 => 'Debug'));
408
+ }
409
+
410
+ function update_option($name, $data = null) {
411
+ if ($data == null) $data = $this->data;
412
+ update_option($name, $data);
413
+ if (isset($data['log_level'])) {
414
+ update_option($name . '_log_level', $data['log_level']);
415
+ }
416
+ }
417
+
418
+ // function button_link($action, $url, $anchor) {
419
+ // if (strpos($url, '?') !== false) $url .= $url . '&';
420
+ // else $url .= $url . '?';
421
+ // $url .= 'act=' . $action;
422
+ //
423
+ // $url .= '&_wpnonce=' . wp_create_nonce();
424
+ //
425
+ // echo '<a class="button" href="' . $url . '">' . $anchor . '</a>';
426
+ // }
427
+
428
+ function js_redirect($url) {
429
+ echo '<script>';
430
+ echo 'location.href="' . $url . '"';
431
+ echo '</script>';
432
+ }
433
+
434
+ /**
435
+ * @deprecated
436
+ */
437
+ function save_user($subscriber) {
438
+ return NewsletterUsers::instance()->save_user($user);
439
+ }
440
+
441
+ /**
442
+ * @deprecated
443
+ */
444
+ function get_test_subscribers() {
445
+ return NewsletterUsers::instance()->get_test_users();
446
+ }
447
+
448
+ }
449
+
450
+ ?>
includes/logger.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class NewsletterLogger {
4
+
5
+ const NONE = 0;
6
+ const FATAL = 1;
7
+ const ERROR = 2;
8
+ const INFO = 3;
9
+ const DEBUG = 4;
10
+
11
+ var $level;
12
+ var $module;
13
+ var $file;
14
+
15
+ function __construct($module) {
16
+ $this->module = $module;
17
+ if (defined('NEWSLETTER_LOG_LEVEL')) $this->level = NEWSLETTER_LOG_LEVEL;
18
+ else $this->level = get_option('newsletter_log_level', self::ERROR);
19
+
20
+ $secret = get_option('newsletter_logger_secret');
21
+ if (strlen($secret) < 8) {
22
+ $secret = NewsletterModule::get_token(8);
23
+ update_option('newsletter_logger_secret', $secret);
24
+ }
25
+
26
+ @wp_mkdir_p(WP_CONTENT_DIR . '/logs/newsletter/');
27
+
28
+ $this->file = WP_CONTENT_DIR . '/logs/newsletter/' . $module . '-' . $secret . '.txt';
29
+ }
30
+
31
+ function log($text, $level = self::ERROR) {
32
+
33
+ if ($this->level < $level) return;
34
+
35
+ $time = date('d-m-Y H:i:s ');
36
+ switch ($level) {
37
+ case self::FATAL: $time .= '- FATAL';
38
+ break;
39
+ case self::ERROR: $time .= '- ERROR';
40
+ break;
41
+ case self::INFO: $time .= '- INFO ';
42
+ break;
43
+ case self::DEBUG: $time .= '- DEBUG';
44
+ break;
45
+ }
46
+ if (is_array($text) || is_object($text)) $text = print_r($text, true);
47
+
48
+ // The "logs" dir is created on Newsletter constructor.
49
+ file_put_contents($this->file, $time . ' - ' . $text . "\n", FILE_APPEND | FILE_TEXT);
50
+ }
51
+
52
+ function error($text) {
53
+ self::log($text, self::ERROR);
54
+ }
55
+
56
+ function info($text) {
57
+ $this->log($text, self::INFO);
58
+ }
59
+
60
+ function fatal($text) {
61
+ $this->log($text, self::FATAL);
62
+ }
63
+
64
+ function debug($text) {
65
+ $this->log($text, self::DEBUG);
66
+ }
67
+
68
+ }
includes/module.php ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class NewsletterModule {
4
+
5
+ /**
6
+ * @var NewsletterLogger
7
+ */
8
+ var $logger;
9
+
10
+ /**
11
+ * @var NewsletterStore
12
+ */
13
+ var $store;
14
+
15
+ /**
16
+ * The main module options
17
+ * @var array
18
+ */
19
+ var $options;
20
+
21
+ /**
22
+ * @var string The module name
23
+ */
24
+ var $module;
25
+
26
+ /**
27
+ * The module version
28
+ * @var string
29
+ */
30
+ var $version;
31
+
32
+ /**
33
+ * Prefix for all options stored on WordPress options table.
34
+ * @var string
35
+ */
36
+ var $prefix;
37
+
38
+ function __construct($module, $version) {
39
+ $this->module = $module;
40
+ $this->version = $version;
41
+ $this->prefix = 'newsletter_' . $module;
42
+
43
+ $this->options = $this->get_options();
44
+
45
+ $this->logger = new NewsletterLogger($module);
46
+ $this->store = NewsletterStore::singleton();
47
+
48
+ //$this->logger->debug($module . ' constructed');
49
+
50
+ // Version check
51
+ if ($this->compare_version($this->version) != 0) {
52
+ $this->logger->info('Version changed from ' . $this->get_version() . ' to ' . $this->version);
53
+ // Do all the stuff for this version change
54
+ $this->upgrade();
55
+ $this->save_version($this->version);
56
+ }
57
+ }
58
+
59
+ function upgrade() {
60
+ $this->logger->info('upgrade> Start');
61
+
62
+ if (empty($this->options)) {
63
+ $this->options = $this->get_default_options();
64
+ $this->save_options($this->options);
65
+ }
66
+ }
67
+
68
+ function upgrade_query($query) {
69
+ global $wpdb, $charset_collate;
70
+
71
+ $this->logger->info('upgrade_query> Executing ' . $query);
72
+ $wpdb->query($query);
73
+ if ($wpdb->last_error) $this->logger->error($wpdb->last_error);
74
+ }
75
+
76
+ /** Returns a prefix to be used for option names and other things which need to be uniquely named. The parameter
77
+ * "sub" should be used when a sub name is needed for another set of options or like.
78
+ *
79
+ * @param string $sub
80
+ * @return string The prefix for names
81
+ */
82
+ function get_prefix($sub = '') {
83
+ return $this->prefix . ($sub != '' ? '_' : '') . $sub;
84
+ }
85
+
86
+ /**
87
+ * Returns the options of a module.
88
+ */
89
+ function get_options($sub = '') {
90
+ $options = get_option($this->get_prefix($sub));
91
+ if ($options == false) return array();
92
+ return $options;
93
+ }
94
+
95
+ function get_default_options($sub = '') {
96
+ if ($sub != '') $sub .= '-';
97
+ @include NEWSLETTER_DIR . '/' . $this->module . '/languages/' . $sub . '/en_US.php';
98
+ @include NEWSLETTER_DIR . '/' . $this->module . '/languages/' . $sub . WPLANG . '.php';
99
+ if (!is_array($options)) return array();
100
+ return $options;
101
+ }
102
+
103
+ function save_options($options, $sub = '') {
104
+ update_option($this->get_prefix($sub), $options);
105
+ if (isset($options['log_level']))
106
+ update_option('newsletter_' . $this->module . '_log_level', $options['log_level']);
107
+ }
108
+
109
+ function backup_options($sub) {
110
+ $options = $this->get_options();
111
+ add_option($this->get_prefix($sub) . '_backup', '', null, 'no');
112
+ update_option($this->get_prefix($sub) . '_backup', $options);
113
+ }
114
+
115
+ function get_last_run($sub = '') {
116
+ return get_option($this->get_prefix($sub) . '_last_run', 0);
117
+ }
118
+
119
+ function save_last_run($time, $sub = '') {
120
+ update_option($this->get_prefix($sub) . '_last_run', $time);
121
+ }
122
+
123
+ function add_to_last_run($delta, $sub = '') {
124
+ $time = $this->get_last_run($sub);
125
+ $this->save_last_run($time + $delta, $sub);
126
+ }
127
+
128
+ function get_version() {
129
+ return get_option($this->prefix . '_version');
130
+ }
131
+
132
+ function save_version($version) {
133
+ update_option($this->prefix . '_version', $version);
134
+ }
135
+
136
+ function compare_version($new_version) {
137
+ return strcmp($this->get_version(), $new_version);
138
+ }
139
+
140
+ function delete_transient($sub = '') {
141
+ delete_transient($this->get_prefix($sub));
142
+ }
143
+
144
+ /**
145
+ * Checks if the semaphore of that name (for this module) is still red giving that it should last only
146
+ * $time seconds.
147
+ *
148
+ * @param string $name
149
+ * @param int $time Max time in second this semaphore should stay red
150
+ * @return boolean False if the semaphore is red and you should not proceed.
151
+ */
152
+ function check_transient($name, $time) {
153
+ usleep(rand(0, 1000000));
154
+ if (($value = get_transient($this->get_prefix() . '_' . $name)) !== false) {
155
+ $this->logger->error('Blocked by transient ' . $this->get_prefix() . '_' . $name . ' set ' . (time() - $value) . ' seconds ago');
156
+ return false;
157
+ }
158
+ set_transient($this->get_prefix() . '_' . $name, time(), $time);
159
+ return true;
160
+ }
161
+
162
+ /** Returns a random token of the specified size (or 10 characters if size is not specified).
163
+ *
164
+ * @param int $size
165
+ * @return string
166
+ */
167
+ static function get_token($size = 10) {
168
+ return substr(md5(rand()), 0, $size);
169
+ }
170
+
171
+ static function add_qs($url, $qs, $amp = true) {
172
+ if (strpos($url, '?') !== false) {
173
+ if ($amp) return $url . '&amp;' . $qs;
174
+ else return $url . '&' . $qs;
175
+ }
176
+ else return $url . '?' . $qs;
177
+ }
178
+
179
+ static function normalize_email($email) {
180
+ $email = strtolower(trim($email));
181
+ if (!is_email($email)) return null;
182
+ return $email;
183
+ }
184
+
185
+ static function normalize_name($name) {
186
+ $name = str_replace(';', ' ', $name);
187
+ $name = strip_tags($name);
188
+ return $name;
189
+ }
190
+
191
+ static function is_email($email, $empty_ok = false) {
192
+ $email = strtolower(trim($email));
193
+ if ($empty_ok && $email == '') return true;
194
+
195
+ if (!is_email($email)) return false;
196
+ if (strpos($email, 'mailinator.com') !== false) return false;
197
+ if (strpos($email, 'guerrillamailblock.com') !== false) return false;
198
+ if (strpos($email, 'emailtemporanea.net') !== false) return false;
199
+ return true;
200
+ }
201
+
202
+ /**
203
+ * Converts a GMT date into timestamp.
204
+ *
205
+ * @param type $s
206
+ * @return type
207
+ */
208
+ static function m2t($s) {
209
+
210
+ // TODO: use the wordpress function I don't remeber the name
211
+ $s = explode(' ', $s);
212
+ $d = explode('-', $s[0]);
213
+ $t = explode(':', $s[1]);
214
+ return gmmktime((int) $t[0], (int) $t[1], (int) $t[2], (int) $d[1], (int) $d[2], (int) $d[0]);
215
+ }
216
+
217
+ static function date($time = null, $now = false, $left = false) {
218
+ if (is_null($time)) $time = time();
219
+ if ($time == false) $buffer = 'none';
220
+ else
221
+ $buffer = gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + get_option('gmt_offset') * 3600);
222
+ if ($now) {
223
+ $buffer .= ' (now: ' . gmdate(get_option('date_format') . ' ' .
224
+ get_option('time_format'), time() + get_option('gmt_offset') * 3600);
225
+ if ($left) {
226
+ $buffer .= ', ' . gmdate('H:i:s', $time - time()) . ' left';
227
+ }
228
+ $buffer .= ')';
229
+ }
230
+ return $buffer;
231
+ }
232
+
233
+ /**
234
+ * Return an array of array with on first element the array of recent post and on second element the array
235
+ * of old posts.
236
+ *
237
+ * @param array $posts
238
+ * @param int $time
239
+ */
240
+ static function split_posts(&$posts, $time = 0) {
241
+ $result = array(array(), array());
242
+ foreach ($posts as &$post) {
243
+ if (self::is_post_old($post, $time)) $result[1][] = $post;
244
+ else $result[0][] = $post;
245
+ }
246
+ return $result;
247
+ }
248
+
249
+ static function is_post_old(&$post, $time = 0) {
250
+ return self::m2t($post->post_date_gmt) <= $time;
251
+ }
252
+
253
+ static function get_post_image($post_id = null, $size = 'thumbnail', $alternative = null) {
254
+ global $post;
255
+
256
+ if (empty($post_id)) $post_id = $post->ID;
257
+ if (empty($post_id)) return $alternative;
258
+
259
+ $image_id = function_exists('get_post_thumbnail_id') ? get_post_thumbnail_id($post_id) : false;
260
+ if ($image_id) {
261
+ $image = wp_get_attachment_image_src($image_id, $size);
262
+ return $image[0];
263
+ } else {
264
+ $attachments = get_children(array('post_parent' => $post_id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID'));
265
+
266
+ if (empty($attachments)) {
267
+ return $alternative;
268
+ }
269
+
270
+ foreach ($attachments as $id => $attachment) {
271
+ $image = wp_get_attachment_image_src($id, $size);
272
+ return $image[0];
273
+ }
274
+ }
275
+ }
276
+
277
+ function get_styles() {
278
+
279
+ $list = array(''=>'none');
280
+
281
+ $dir = NEWSLETTER_DIR . '/' . $this->module . '/styles';
282
+ $handle = @opendir($dir);
283
+
284
+ if ($handle !== false) {
285
+ while ($file = readdir($handle)) {
286
+ if ($file == '.' || $file == '..') continue;
287
+ if (substr($file, -4) != '.css') continue;
288
+ $list[$file] = substr($file, 0, strlen($file) - 4);
289
+ }
290
+ closedir($handle);
291
+ }
292
+
293
+ $dir = WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/styles';
294
+ $handle = @opendir($dir);
295
+
296
+ if ($handle !== false) {
297
+ while ($file = readdir($handle)) {
298
+ if ($file == '.' || $file == '..') continue;
299
+ if (isset($list[$file])) continue;
300
+ if (substr($file, -4) != '.css') continue;
301
+ $list[$file] = substr($file, 0, strlen($file) - 4);
302
+ }
303
+ closedir($handle);
304
+ }
305
+ return $list;
306
+ }
307
+
308
+ function get_style_url($style) {
309
+ if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/styles/' . $style))
310
+ return WP_CONTENT_URL . '/extensions/newsletter/' . $this->module . '/styles/' . $style;
311
+ else return NEWSLETTER_URL . '/' . $this->module . '/styles/' . $style;
312
+ }
313
+
314
+ }
315
+
316
+ /**
317
+ * Kept for compatibility.
318
+ *
319
+ * @param type $post_id
320
+ * @param type $size
321
+ * @param type $alternative
322
+ * @return type
323
+ */
324
+ function nt_post_image($post_id = null, $size = 'thumbnail', $alternative = null) {
325
+ return NewsletterModule::get_post_image($post_id, $size, $alternative);
326
+ }
327
+
328
+ function newsletter_get_post_image($post_id = null, $size = 'thumbnail', $alternative = null) {
329
+ echo NewsletterModule::get_post_image($post_id, $size, $alternative);
330
+ }
includes/store.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ @require_once NEWSLETTER_INCLUDES_DIR . '/logger.php';
4
+
5
+ class NewsletterStore {
6
+
7
+ static $instance = null;
8
+
9
+ /**
10
+ * @var NewsletterLogger
11
+ */
12
+ var $logger;
13
+
14
+ /**
15
+ *
16
+ * @return NewsletterStore
17
+ */
18
+ static function instance() {
19
+ if (self::$instance == null) {
20
+ self::$instance = new NewsletterStore();
21
+ }
22
+ return self::$instance;
23
+ }
24
+
25
+ static function singleton() {
26
+ return self::instance();
27
+ }
28
+
29
+ function __construct() {
30
+ $this->logger = new NewsletterLogger('store');
31
+ }
32
+
33
+ function get_field($table, $id, $field_name) {
34
+ global $wpdb;
35
+ $r = $wpdb->get_var("select $field_name from $table where id=" . (int)$id . " limit 1");
36
+ if ($wpdb->last_error) {
37
+ $this->logger->error($wpdb->last_error);
38
+ return false;
39
+ }
40
+ return $r;
41
+ }
42
+
43
+ function get_single($table, $id, $format = OBJECT) {
44
+ return $this->get_single_by_query("select * from $table where id=$id limit 1", $format);
45
+ }
46
+
47
+ function get_single_by_field($table, $field_name, $field_value) {
48
+ return $this->get_single_by_query("select * from $table where $field_name='" . $wpdb->escape($field_value) . "' limit 1", $format);
49
+ }
50
+
51
+ function get_count($table, $where = null) {
52
+ global $wpdb;
53
+ $r = $wpdb->get_var("select count(*) from $table " . ($where != null ? $where : ''));
54
+ if ($wpdb->last_error) {
55
+ $this->logger->error($wpdb->last_error);
56
+ return false;
57
+ }
58
+ return $r;
59
+ }
60
+
61
+ /**
62
+ * Returns a single record executing the given query or null if no row can be found. If more rows are matching
63
+ * the query, only the first one is returned. Returns "false" on error (use the strict type checking ===) and a log
64
+ * is written.
65
+ *
66
+ * @global wpdb $wpdb
67
+ * @param string $query
68
+ * @param type $format
69
+ * @return boolean|mixed
70
+ */
71
+ function get_single_by_query($query, $format=OBJECT) {
72
+ global $wpdb;
73
+ $r = $wpdb->get_row($query, $format);
74
+ if ($wpdb->last_error) {
75
+ $this->logger->error($wpdb->last_error);
76
+ return false;
77
+ }
78
+ return $r;
79
+ }
80
+
81
+ /**
82
+ * Save a record on given table, updating it id the "id" value is set (as key or object property) or inserting it
83
+ * if "id" is not set. Accepts objects or associative arrays as data.
84
+ *
85
+ * Returns "false" is an error occurred or the saved data re-read from the database in given format.
86
+ *
87
+ * @global wpdb $wpdb
88
+ * @param type $table
89
+ * @param type $data
90
+ */
91
+ function save($table, $data, $return_format = OBJECT) {
92
+ global $wpdb;
93
+ if (is_object($data)) {
94
+ $data = (array) $data;
95
+ }
96
+
97
+ if (isset($data['id'])) {
98
+ $id = $data['id'];
99
+ unset($data['id']);
100
+ $wpdb->update($table, $data, array('id' => $id));
101
+ //$this->logger->debug('save: ' . $wpdb->last_query);
102
+ } else {
103
+ $wpdb->insert($table, $data);
104
+ $id = $wpdb->insert_id;
105
+ }
106
+ if ($wpdb->last_error) {
107
+ $this->logger->error('save: ' . $wpdb->last_error);
108
+ return false;
109
+ }
110
+
111
+ return $this->get_single($table, $id, $return_format);
112
+ }
113
+
114
+ function increment($table, $id, $field) {
115
+ global $wpdb;
116
+ $result = $wpdb->query("update $table set $field=$field+1 where id=$id");
117
+
118
+ if ($wpdb->last_error) {
119
+ $this->logger->error($wpdb->last_error);
120
+ return false;
121
+ }
122
+
123
+ return $result;
124
+ }
125
+
126
+ function delete($table, $id) {
127
+ global $wpdb;
128
+ $wpdb->delete($table, array('id' => $id));
129
+ if ($wpdb->last_error) {
130
+ $this->logger->error($wpdb->last_error);
131
+ return false;
132
+ }
133
+ return $wpdb->rows_affected;
134
+ }
135
+
136
+ /**
137
+ *
138
+ * @global wpdb $wpdb
139
+ * @param type $table
140
+ * @param type $order_by
141
+ * @param type $format
142
+ * @return type
143
+ */
144
+ function get_all($table, $where=null, $format = OBJECT) {
145
+ global $wpdb;
146
+ if ($where == null) {
147
+ $result = $wpdb->get_results("select * from $table", $format);
148
+ } else {
149
+ $result = $wpdb->get_results("select * from $table $where", $format);
150
+ }
151
+ return $result;
152
+ }
153
+
154
+ function set_field($table, $id, $field, $value)
155
+ {
156
+ global $wpdb;
157
+ $result = $wpdb->query($wpdb->prepare("update $table set $field=%s where id=$id", $value));
158
+
159
+ if ($wpdb->last_error) {
160
+ $this->logger->error($wpdb->last_error);
161
+ return false;
162
+ }
163
+
164
+ return $result;
165
+
166
+ }
167
+ function query($query) {
168
+ global $wpdb;
169
+ $result = $wpdb->query($query);
170
+ if ($wpdb->last_error) {
171
+ $this->logger->error($wpdb->last_error);
172
+ return false;
173
+ }
174
+ return $result;
175
+ }
176
+
177
+ }
178
+
includes/themes.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class NewsletterThemes {
4
+
5
+ var $module;
6
+
7
+ function __construct($module) {
8
+ $this->module = $module;
9
+ }
10
+
11
+ /** Loads all themes of a module (actually only "emails" module makes sense). Themes are located inside the subfolder
12
+ * named as the module on plugin folder and on a subfolder named as the module on wp-content/newsletter folder (which
13
+ * must be manually created).
14
+ *
15
+ * @param type $module
16
+ * @return type
17
+ */
18
+ function get_all() {
19
+ $list = array();
20
+
21
+ $dir = NEWSLETTER_DIR . '/' . $this->module . '/themes';
22
+ $handle = @opendir($dir);
23
+
24
+ if ($handle !== false) {
25
+ while ($file = readdir($handle)) {
26
+ if ($file == '.' || $file == '..') continue;
27
+ if (!is_file($dir . '/' . $file . '/theme.php')) continue;
28
+
29
+ $list[$file] = $file;
30
+ }
31
+ closedir($handle);
32
+ }
33
+
34
+ $dir = WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/themes';
35
+ $handle = @opendir($dir);
36
+
37
+ if ($handle !== false) {
38
+ while ($file = readdir($handle)) {
39
+ if ($file == '.' || $file == '..') continue;
40
+ if (isset($list[$file])) continue;
41
+ if (!is_file($dir . '/' . $file . '/theme.php')) continue;
42
+ $list[$file] = $file;
43
+ }
44
+ closedir($handle);
45
+ }
46
+ return $list;
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param type $theme
52
+ * @param type $options
53
+ * @param type $module
54
+ */
55
+ function save_options($theme, &$options) {
56
+ add_option('newsletter_' . $this->module . '_theme_' . $theme, array(), null, 'no');
57
+ $theme_options = array();
58
+ foreach ($options as $key => &$value) {
59
+ if (substr($key, 0, 6) != 'theme_') continue;
60
+ $theme_options[$key] = $value;
61
+ }
62
+ update_option('newsletter_' . $this->module . '_theme_' . $theme, $theme_options);
63
+ }
64
+
65
+ function get_options($theme) {
66
+ $options = get_option('newsletter_' . $this->module . '_theme_' . $theme);
67
+ // To avoid merge problems.
68
+ if (!is_array($options)) return array();
69
+ return $options;
70
+ }
71
+
72
+ function get_file_path($theme, $file) {
73
+ $path = WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/themes/' . $theme . '/' . $file;
74
+ if (is_file($path)) return $path;
75
+ else return NEWSLETTER_DIR . '/' . $this->module . '/themes/' . $theme . '/' . $file;
76
+ }
77
+
78
+ function get_theme_url($theme) {
79
+ $path = NEWSLETTER_DIR . '/' . $this->module . '/themes/' . $theme;
80
+ if (is_dir($path)) {
81
+ return NEWSLETTER_URL . '/' . $this->module . '/themes/' . $theme;
82
+ }
83
+ else {
84
+ return WP_CONTENT_URL . '/extensions/newsletter/' . $this->module . '/themes/' . $theme;
85
+ }
86
+ }
87
+
88
+ function get_default_options() {
89
+ $path1 = NEWSLETTER_DIR . '/' . $this->module . '/themes/' . $theme . '/languages';
90
+ $path2 = WP_CONTENT_DIR . '/extensions/newsletter/' . $this->module . '/themes/' . $theme . '/languages';
91
+ @include $path1 . '/en_US.php';
92
+ @include $path2 . '/en_US.php';
93
+ @include $path1 . '/' . WPLANG . '.php';
94
+ @include $path2 . '/' . WPLANG . '.php';
95
+
96
+ if (!is_array($options)) return array();
97
+ return $options;
98
+ }
99
+
100
+ }
101
+
102
+ function nt_option($name, $def = null) {
103
+ $options = get_option('newsletter_email');
104
+ $option = $options['theme_' . $name];
105
+ if (!isset($option)) return $def;
106
+ else return $option;
107
+ }
intro.php DELETED
@@ -1,504 +0,0 @@
1
- <div class="wrap">
2
- <h2>Newsletter/Newsletter Pro User Guide</h2>
3
-
4
- <?php include dirname(__FILE__) . '/header.php'; ?>
5
-
6
- <p>Welcome to Newsletter/Neswletter Pro from Stefano Lissa.</p>
7
- <p>
8
- I hope Newsletter/Neswletter Pro will be a powerful tool for your business. I made the whole configuration
9
- as simple as possible but keeping an eye on flexibility, specially in respect of all the
10
- world languages. I'm Italian and I know how much stressing job is the plug-in translation!
11
- </p>
12
- <p>
13
- This guide is common to Newsletter and Newsletter Pro, so here you will find some chapters with
14
- instructions on how to operate with Newsletter Pro features: if you're running Newsletter free, just
15
- skip them.
16
- </p>
17
- <p>
18
- If you want to know more about Newsletter Pro, take a look to
19
- <a href="http://www.satollo.net/plugins/newsletter" target="_blank">this page</a> (opens on a new window)
20
- or go directly to the <a href="http://members.satollo.net" target="_blank">Member's site</a> (opens in a new window).
21
- </p>
22
- <p>
23
- <strong>References to pages where leave comments or find support can be find
24
- on <a href="http://www.satollo.net/plugins/newsletter" target="_blank">this page</a> (opens on a new window).</strong>
25
- </p>
26
- <p>
27
- Every non obvious options you find on configuration panels has a little
28
- documentation box. Many users asked me to include the documentation on Newsletter panels
29
- and even if that make them a little bit "verbose", I think it's of great help.
30
- </p>
31
- <p>
32
- Please, take the time to read the info box of each option, specially on main configuration
33
- panel, because some values, even if formally correct, can be the cause of errors (due to
34
- your hosting provider policy or limits).
35
- </p>
36
- <p>
37
- <strong>If you have questions due to missing part on this documentation, send me an email to
38
- stefano@satollo.net so I can complete it and clear any doubt</strong>.
39
- </p>
40
-
41
- <h3>F.A.Q.</h3>
42
- <p><strong>Nothing is working!</strong></p>
43
- <p>
44
- The plugin is working on my main site (<a href="http://www.satollo.net" target="_blank">www.satollo.net</a>),
45
- I use there the <strong>free version</strong> just to be sure it
46
- works for all. So, have you DEACTIVATED and REACTIVATED it after a manual update (with
47
- WordPress automatic upgrade, WordPress takes care of it for you - but you can try that manually).
48
- </p>
49
-
50
- <p><strong>Where is the version history?</strong></p>
51
- <p>On readme.txt file.</p>
52
-
53
- <p><strong>Email are not sent (but test emails are).</strong></p>
54
- <p>
55
- On email list panel there is a delivery engine next run. If it is negative or empty or zero (always)
56
- the WordPress cron system is not working. Read below about delivery engine and the WordPress
57
- cron system.
58
- </p>
59
-
60
- <p><strong>Multisite WordPress, nothing work.</strong></p>
61
- <p>
62
- It's a bit tricky: you must activate the plugin with your super admin account, then enter every blog dashboard,
63
- and deactivate and reactivate the plugin.
64
- </p>
65
-
66
- <h3>Newsletter configuration structure</h3>
67
-
68
- <p>
69
- Newsletter panels are organized as described below. It is separated in modules, so if you don't
70
- need the feed by mail service or you don't need the follow up service, you can ignore them safely.<br />
71
- Every panel contains it's own documentation, but here you can find special cases or examples.
72
- </p>
73
- <ul>
74
- <li><strong>User Guide.</strong> It's the panel where you are now...</li>
75
- <li><strong>Main Configuration.</strong> Really important. It's the first panel you need to check. Almost every value has a preset or can
76
- be left empty but you at least make some sending test. Other advanced functions are configurable on main panel:
77
- <ul>
78
- <li>SMTP (only Newsletter Pro). To use an external SMTP to send emails.</li>
79
- <li>Locked content (only Newsletter Pro). To create premium content on your blog locking out parts of posts letting only
80
- subscriber to see them.</li>
81
- </ul>
82
- </li>
83
-
84
- <li><strong>User Profile/Subscription Form.</strong> Really important. It's where you set what user's data you want to collect on subscription. There
85
- you can translate almost every thing of Newsletter.</li>
86
- <li><strong>Subscription Process.</strong> Really important. It's where you decide how the subscription process works. There you
87
- can set double or single opt in, emails and messages that are involved on subscription and cancellation.</li>
88
- <li><strong>Emails.</strong> Where to create and send emails. For Newsletter Pro owners there is access to single email statistics (
89
- clicks, links clicked, ...).</li>
90
- <li><strong>Users Management.</strong> There you can search, add, edit, remove subscribers. For Newsletter Pro owners there is a statistics
91
- sub-panel.</li>
92
- <li><strong>Feed by mail (only Newsletter Pro).</strong> Configure if and how you subscriber will receive a summary of you
93
- blog latest posts. There you can create your feed by mail theme (programming skills needed) as no other
94
- services can do!</li>
95
- <li><strong>Follow up (only Newsletter Pro).</strong> Don't let your subscribers without messages for long time after they
96
- signed up. On this panel you can program a series of emails to be sent automatically.</li>
97
- <li><strong>Import/Export.</strong> Some functionalities to import subscribers from CSV file and to export them.</li>
98
-
99
- <li><strong>Forms.</strong> You can manually create subscription forms to be recalled on different places. Before use that panel remember that
100
- Newsletter enables you to customize the subscription form on every configuration which require it (eg. the widget).</li>
101
- </ul>
102
-
103
-
104
- <h3>Main configuration panel</h3>
105
- <p>
106
- Every setting in the main configuration panel is adequately described there, just be sure to read every note because some
107
- apparently legal values can block the emails from your account.
108
- </p>
109
- <p>
110
- One important parameter is the number of email per hour you want Newsletter to send. This limit is applied to
111
- newsletters, feed by mail and follow up emails.
112
- </p>
113
-
114
- <h4>Sending process and SMTP</h4>
115
- <p>
116
- Newsletter Pro uses the mailing functions of WordPress to send emails so you can use any plugin
117
- that extend the WordPress mailing system and it will act on Newsletter Pro emails too.
118
- </p>
119
- <p>
120
- Optionally, on main configuration panel, you can choose to use an "external" SMTP service. In that case
121
- Newsletter Pro sends emails on it's own, using directly the WordPress included libraries. Using the SMTP
122
- of Newsletter Pro than installing a plugin that forces WordPress standard mailing function to use the same
123
- SMTP is usually more efficient. Newsletter Pro will use that SMTP for any message it needs to send (not only newsletters
124
- even welcome and confirmation messages will be sent via SMTP).
125
- </p>
126
- <p>
127
- If the Mailer plugin is installed, Newsletter Pro adds some special headers on outgoing emails so Mailer
128
- can detect them and schedule correctly every message. Newsletters are send with priority 2 while
129
- any other message (usually confirmation and welcome messages) is sent with priority 0 (real time).
130
- </p>
131
- <p>
132
- Mailer or other plugins that throttles emails going out from your blog are not required, since Newsletter has it's
133
- own email throttling system.
134
- </p>
135
-
136
- <h4>Locked content</h4>
137
-
138
- <p>
139
- <strong>Read carefully if you use a cache system!</strong>
140
- </p>
141
- <p>
142
- With Newsletter Pro you can lock out some content of you blog, making it available only
143
- to confirmed subscriber. The feature can be configured on main configuration panel.
144
- </p>
145
- <p>
146
- Using the feature is very simple: on a post identify the content you want to lock out and
147
- surround it with shot code [newsletter_lock]...[/newsletter_lock]. You can lock out multiple
148
- piece of content, too.
149
- </p>
150
- <p>
151
- In place of the hidden content a short message is shown, as configured in main configuration panel
152
- (where there are some tips on what to write in it). When a user subscribe and confirm the subscription or
153
- click on his personal unlocking url ({unlock_url} that you should put only on welcome email) a cookie
154
- is added to his browser and the lock is removed every where on the blog.
155
- </p>
156
- <p>
157
- <strong>Warning</strong>. Be sure to not cache the posts with locked content, otherwise there are chances that
158
- subscribers see always the lock message or, worse, the unlocked content is shown to every one. Newsletter
159
- Pro is already integrated with Hyper Cache, for other cache systems just add a cache bypass based on
160
- presence of "newsletter" cookie.
161
- </p>
162
-
163
-
164
-
165
-
166
-
167
-
168
- <h3>The subscription process</h3>
169
-
170
- <p>
171
- The main thing you should care of is the subscription configuration. It's not so hard but
172
- there are some choices you need to take and that suite your audience and may be your
173
- local laws.
174
- </p>
175
- <p>
176
- Subscription can be single opt in or double opt in. Choosing the one or the other will change
177
- the configuration panel to show you only the needed options.
178
- </p>
179
- <p>
180
- Single opt in is not too much legal, since you assume that the subscribed email address is correct and
181
- owned by who performed the subscription. Double opt in subscription (which is required for example by DreamHost)
182
- activate the subscriber only after he confirm his email address (by an activation email send by Newsletter).
183
- </p>
184
-
185
-
186
-
187
- <h3>User profile/Subscription Form</h3>
188
-
189
- <p>
190
- User profile is the set of data you can collect about subscribers during the subscription or on their profile panel:
191
- </p>
192
-
193
- <ul>
194
- <li>email, first name, last name</li>
195
- <li>sex</li>
196
- <li>privacy check box (for countries which requires it)</li>
197
- <li>lists/topics preference (up to 9)</li>
198
- <li>generic textual/selection list profile fields (up to 19)</li>
199
- <li>ip address and date of subscription (for legal purposes)</li>
200
- </ul>
201
- <p>
202
- Even if Newsletter Pro lets you to collect all that data, it's recommended to ask the subscriber
203
- the smallest set of fields possible, to avoid subscription loss. It's usually more profitable to give
204
- the subscriber a complete profile form where to fill in more data on a second time. You
205
- can offer the complete profile form just after the sign up or invite the user to complete his data
206
- with a follow up email or with a link to the profile form on newsletters you'll send.
207
- </p>
208
-
209
- <p>
210
- Subscription and profile forms, as generated by Newsletter Pro, are controlled under the "user profile"
211
- panel. There you can decide what fields to ask on subscription time and what fields on profile editing step.
212
- </p>
213
-
214
- <p>
215
- You can also <strong>translate every single word</strong> in you language!
216
- </p>
217
-
218
- <p>
219
- Check the hints in the panel for detailed explanation of every single field.
220
- </p>
221
-
222
- <h3>Tags</h3>
223
- <p>
224
- Subscritpion texts, email bodies, email subjects and so on accept (usually) a set of tag that will be replaced
225
- with user specific content (like her name).
226
- </p>
227
- <ul>
228
- <li><strong>{name}</strong> The user name</li>
229
- <li><strong>{surname}</strong> The user surname</li>
230
- <li><strong>{email}</strong> The user email</li>
231
- <li><strong>{ip}</strong> The IP address from where the subscription started</li>
232
- <li><strong>{id}</strong> The user id</li>
233
- <li><strong>{token}</strong> The user secret token</li>
234
- <li><strong>{profile_N}</strong> The user profile field number N (from 1 to 19)</li>
235
- <li><strong>{date}</strong> the current date formatted as specified on WordPress general options</li>
236
- <li><strong>{date_'format'}</strong> the current date formatted with 'format' format compatible with PHP date formatting specifications.
237
- </ul>
238
-
239
- <h4>Action URLs and forms</h4>
240
- <p>
241
- <strong>{subscription_confirm_url}</strong>
242
- URL to build a link to confirmation of subscription when double opt-in is used. To be used on confirmation email.<br />
243
- <strong>{unsubscription_url}</strong>
244
- URL to build a link to start the cancellation process. To be used on every newsletter to let the user to cancel.<br />
245
- <strong>{unsubscription_confirm_url}</strong>
246
- URL to build a link to an immediate cancellation action. Can be used on newsletters if you want an immediate cancellation or
247
- on cancellation page (displayed on {unsubscription_url}) to ask a cancellation confirmation.<br />
248
- <strong>{profile_url}</strong>
249
- URL to build a link to user's profile page (see the User Profile panel)<br />
250
- <strong>{unlock_url}</strong>
251
- Special URL to build a link that on click unlocks protected contents. See Main Configuration panel.<br />
252
- <strong>{profile_form}</strong>
253
- Insert the profile form with user's data. Usually it make sense only on welcome page.<br />
254
- </p>
255
-
256
-
257
- <h3>Custom forms</h3>
258
- <p>
259
- You need HTML skills to create custom forms, but it is so easy that a consultant
260
- should charge a very low fee to do it for you (or ask to a nephew...).
261
- </p>
262
- <p>
263
- As general rule, you can create a custom form <strong>on every subscription point</strong>: the
264
- Newsletter Pro main page, on Newsletter Pro widgets, on alternative messages for
265
- locked content.
266
- </p>
267
- <p>
268
- To create a custom form is very easy, here an example that asks the user only it's email:
269
- </p>
270
- <p>
271
- <code>
272
- &lt;form&gt;<br />
273
- &lt;input type="text" name="ne"/&gt;<br />
274
- &lt;input type="submit"/&gt;<br />
275
- &lt;/form&gt;<br />
276
- </code>
277
- as you can see the form tag has not attributes (method, action, ...): they are added
278
- automatically by Newsletter Pro. If you need to fire a JavaScript call before the form submission
279
- add an "onclick" event to the submit button.
280
- </p>
281
-
282
- <p>
283
- The field names you can add to a custom form are:
284
- </p>
285
- <ul>
286
- <li><strong>ne</strong> is the user email</li>
287
- <li><strong>nn</strong> is the user name (first name or complete name)</li>
288
- <li><strong>ns</strong> is the user surname/last name</li>
289
- <li><strong>nx</strong> is the user sex (can assume f, m, n values) and usually it should be a "select"
290
- <li><strong>npN</strong> where N go from 1 to 19, are the custom profile fields (be aware they
291
- are not the same thing of profile fields in Newsletter Pro 2.1)</li>
292
- <li><strong>nl[]</strong> (as written!)) must be check box field name when they represent a list/option/topic; the field value must be a number from
293
- 1 to 9 (the lists)</li>
294
- </ul>
295
- <p>
296
- For lists on a custom form you can ask the user to check what lists he want to subscribe or
297
- put an "hidden" list field to "force" the subscription on that list. The latter option is used
298
- when different forms collect users on different lists without asking directly to the subscriber.
299
- </p>
300
- <p>
301
- An example of check box field for a list is:
302
- </p>
303
- <p>
304
- <code>&lt;input type="checkbox" name="nl[]" value="3"/&gt;</code>
305
- </p>
306
-
307
- <h3>Emails</h3>
308
- <p>
309
- Emails are created from the "emails" panel. When you enter the panel you'll se the emails archived and their status.
310
- </p>
311
- <p>
312
- Each email has a subject and a body, but some other information are stored: targeted users, if link clicks can be tracked,
313
- a status, the number of receivers and how many copies have already been sent.
314
- </p>
315
- <p>
316
- You can create as many email as you want and you can even send many of them simultaneously.
317
- </p>
318
-
319
- <h4>Email status</h4>
320
- <p>
321
- An email has few possible statuses:
322
- </p>
323
- <ul>
324
- <li>new - when it has just been created</li>
325
- <li>sending - when you start the sending process and Newsletter Pro is taking care of it</li>
326
- <li>sent - when the sending engine has completed the work</li>
327
- <li>paused - if you want to pause the sending process, may be to correct an error</li>
328
- </ul>
329
- <p>
330
- When you abort an email sending, the email return to the "new" status and every sending progress information is reset.
331
- </p>
332
-
333
- <h3>Email auto composer and themes</h3>
334
- <p>
335
- When a new email is create, it can be composed starting from a blank sheet or can be auto composed with
336
- a theme. I call it auto compose because a theme can generate actual content getting it from the blog
337
- (a list of latest posts, tag cloud and so on) or simply prepare an already structured content.
338
- </p>
339
- <p>
340
- Themes are PHP file stored under "themes" folder. There are some pre packaged themes that can be used as
341
- starting point for your specific theme.
342
- </p>
343
- <h4>How to create a custom theme</h4>
344
- <p>
345
- To create a new theme follow the steps below (names must be lowercase):
346
- </p>
347
-
348
- <ol>
349
- <li>create a folder named "newsletter-custom" under your WordPress plugins directory</li>
350
- <li>create a folder named "themes" under the previous created "newsletter-custom"</li>
351
- <li>inside "themes" create a folder with a name of your choice (the name will be your custom theme name), for example "my-theme": that will be your theme folder</li>
352
- <li>in your theme folder there must be the file "theme.php" which will be the main file of your theme (and usually the only one)</li>
353
- </ol>
354
-
355
- <p>
356
- To start with an already working theme, start with "theme.php" file of "themes/theme-1" folder.
357
- </p>
358
-
359
- <h4>Theme style file (style.css)</h4>
360
- <p>
361
- Theme used to compose an email is store with the email data. If a theme has a style.css file in
362
- its folder, the <strong>content</strong> of this file is added to outgoing emails. Not all email readers
363
- respect the style added in this way... GMail is an example of them.
364
- </p>
365
- <p>
366
- The style.css file is used while editing the email too to make the visual editor show the content as looking
367
- like the resulting email opened in a mail reader.
368
- </p>
369
-
370
-
371
- <h3>Follow up or auto responder (only Pro version)</h3>
372
- <p>
373
- Follow up or auto-responder is when you send a sequence of emails to new subscribers. A follow up can be a series
374
- of lessons on a topic, a product/service presentation broken up on small parts or anything else.
375
- Those emails are typically sent every few days (configurable, of course).
376
- </p>
377
-
378
- <p>
379
- Once you have created your follow up emails (up to 10) and activated the system,
380
- it starts to work for you contacting the new subscribers as if you're writing to each of them all in
381
- autopilot.
382
- </p>
383
-
384
- <p>
385
- A subscriber can unsubscribe from the follow up without removing him self from the list:
386
- simply the "follow up" status will be set to "stop". This point is of great importance,
387
- because you can let the user to stop annoying (to them) messages without loosing him.
388
- That "follow up unsubscription" is done via a link you should add to each follow up email.
389
- The link is inserted on every occurrence of {followup_unsubscription_url} place holder.
390
- </p>
391
-
392
-
393
- <h4>Follow up theme</h4>
394
- <p>
395
- To give a common skin to each follow up message, the autoresponder applies a theme to every email
396
- body on configuration panel, so they can be considered only the "content" of follow up messages.
397
- </p>
398
-
399
- <p>
400
- Follow up themes are store under the folder "themes-followup" and prepackaged there are a couple of themes, one
401
- almost empty (it contains only a footer text with unsubscription link) and the other a little bit
402
- richer.
403
- </p>
404
-
405
- <p>
406
- Any theme must contain a special tag, {message}, which will be replaced with the current follow up
407
- email content.
408
- </p>
409
-
410
- <p>
411
- To modify a theme follow the same guide lines for feed by mail themes, just use a themes-followup folder
412
- instead of themes-feed.
413
- </p>
414
-
415
-
416
- <h3>Feed by mail (only Pro version)</h3>
417
-
418
- <p>
419
- Feed by mail is a Newsletter Pro service that sends an excerpt of last posts
420
- to subscribers who signed up for it. It's something like Google FeedBurner and other
421
- external services. What makes the difference is:
422
- </p>
423
- <ul>
424
- <li>you can choose on what days of the week you want to send the summary (you can choose the delivery hour too)</li>
425
- <li>you can easily track links on those auto generated emails and see clicks statistics</li>
426
- <li>you can program with PHP your own theme to generate the summary adding other contents of your blog, for example a tag cloud</li>
427
- <li>subscribers can sign in and sign out of feed by mail service still remaining subscribed to your newsletter</li>
428
- <li>programming a specific theme (with PHP) you can compose summary emails totally different for each user set (for example, males and females)</li>
429
- <li>you can automatically add the service to every new subscriber</li>
430
- </ul>
431
- <p>
432
- On feed by mail panel all options are documented, I suggest to subscribe only your self to feed by mail and see the messages Newsletter
433
- Pro delivers to your mailbox.
434
- </p>
435
-
436
- <h4>How to create a new feed by mail theme</h4>
437
- <p>
438
- Packaged feed by mail themes are stored under the themes-feed folder. Every theme is a subfolder containing,
439
- at least, the theme.php file. Packaged themes should be your start point for a new theme, but do not modify
440
- them directly, otherwise on next Newsletter Pro version upgrade modifications will be lost.
441
- </p>
442
-
443
- <p>
444
- To create a new theme, as for generic newsletter themes, follow the steps below (names must be lowercase):
445
- </p>
446
-
447
- <ol>
448
- <li>create a folder named "newsletter-custom" under your WordPress plugins directory</li>
449
- <li>create a folder named "themes-feed" under the previous created "newsletter-custom"</li>
450
- <li>inside "themes-feed" create a folder with a name of your choice (the name will be your custom feed by mail theme name), for example "my-feed-theme": that will be your theme folder</li>
451
- <li>in your theme folder there must be the file "theme.php" which will be the main file of your theme (and usually the only one)</li>
452
- </ol>
453
-
454
- <p>
455
- To start with an already working theme, start with "theme.php" file of "themes-feed/feed-1" folder or the more complex
456
- "themes-feed/feed-2" folder: they are well documented.
457
- </p>
458
-
459
- <p>
460
- Do not use one of the "theme.php" files for normal newsletters, the ones you can found under "themes"
461
- folder, because they do not work!
462
- </p>
463
-
464
-
465
- <h3>Delivery engine and WordPress cron system</h3>
466
- <p>
467
- Newsletter relies on WordPress cron service to automatically send emails respecting the
468
- emails per hour value you set on main configuration panel.
469
- </p>
470
- <p>
471
- That WordPress service works only if your blog has traffic, if not it usually works bad. To make
472
- it running as required, you must trigger it with a regular external call (very five minutes) to:</p>
473
- <p>
474
- <?php echo get_option('siteurl'); ?>/wp-cron.php
475
- </p>
476
- <p>
477
- Any decent provider can setup that call or has a configurable cron service on it's panel, refer to your provider
478
- support.
479
- </p>
480
-
481
-
482
- <h3>Themes tech details</h3>
483
- <p>
484
- Themes for feed by mail and follow up e-mails are "executed" for each user when it's time to generate
485
- an email body. So the generated text can be customized user by user accessing the "current user" data.
486
- </p>
487
-
488
- <p>
489
- The "current user" is an object stored under the $newsletter->user variable and object properties are
490
- the values of columns of the table "wp_newsletter" (the prefix "wp_" can be different in your blog).
491
- </p>
492
- <p>The user object properties are (use them with the syntax $newsletter->user->property_name):</p>
493
- <table>
494
- <tr><td>id</td><td>the user unique identification number</td></tr>
495
- <tr><td>name</td><td>the user first name</td></tr>
496
- <tr><td>surname</td><td>the user last name</td></tr>
497
- <tr><td>sex</td><td>the user sex: m, f, n</td></tr>
498
- <tr><td>list_n</td><td>list n subscription status: 1 means he's subscribed</td></tr>
499
- <tr><td>email</td><td>the user email</td></tr>
500
- <tr><td>followup</td><td>follow up subscription status: 1 means he's subscribed</td></tr>
501
- <tr><td>feed</td><td>feed by mail subscription status: 1 means he's subscribed</td></tr>
502
- </table>
503
-
504
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/cs_CZ.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
- // Those default options are used ONLY on FIRST setup and on plugin updates but limited to
3
- // new options that may have been added between your and new version.
4
- //
5
- // This is the main language file, too, which is always loaded by Newsletter. Other language
6
- // files are loaded according the WPLANG constant defined in wp-config.php file. Those language
7
- // specific files are "merged" with this one and the language specific configuration
8
- // keys override the ones in this file.
9
- //
10
- // Language specific files only need to override configurations containing texts
11
- // language dependant.
12
- //
13
- // All language file are UTF-8 encoded!
14
-
15
- $defaults_profile['profile_text'] = '{profile_form}<p>Pokud už si neprejete odebírat informace ze sveta forexu, <a href="{unsubscription_confirm_url}">kliknete zde.</a></p>';
16
- $defaults_profile['email'] = 'Email'; // Email field label
17
- $defaults_profile['email_error'] = 'Špatne napsaný email, prosím zkontrolujte ho.';
18
- $defaults_profile['name_status'] = 1;
19
- $defaults_profile['name'] = 'Jméno';
20
- $defaults_profile['name_error'] = 'Vaše jméno nemuže zustat prázdné';
21
- $defaults_profile['surname'] = 'Príjmení';
22
- $defaults_profile['surname_status'] = 0;
23
- $defaults_profile['sex_status'] = 0;
24
- $defaults_profile['sex'] = 'I\'m';
25
- $defaults_profile['sex_male'] = 'Muž';
26
- $defaults_profile['sex_female'] = 'Žena';
27
- $defaults_profile['privacy_status'] = 0;
28
- $defaults_profile['privacy'] = 'Prihlášením k odberu informací souhlasíte se zpracováním osobních informací.';
29
- $defaults_profile['privacy_error'] = 'K prihlásení k odberu informací musíte souhlasit se zpracováním osobních informací.';
30
- $defaults_profile['subscribe'] = 'Prihlásit k odberu!';
31
- $defaults_profile['save'] = 'Uložit'; // Profile "save" button
32
-
33
-
34
- $defaults_main['lock_message'] = '<div style="margin: 15px; padding: 15px; background-color: #ff9; border-color: 1px solid #000">
35
- Tento obsah je chránený, pouze lidé prihlášení k odberu newsletteru mohou vstoupit. Prihlašte se nyní!
36
- [newsletter_form]
37
- </div>';
38
-
39
-
40
- // Subscription page introductory text (befor the subscription form)
41
- $defaults['subscription_text'] =
42
- "<p>Zde se mužete prihlásit k odberu novinek.</p>
43
- <p>Bude vám odeslán konfirmacní email, prosím o jeho potvrzení.</p>";
44
-
45
- // Message show after a subbscription request has made.
46
- $defaults['subscribed_text'] =
47
- "<p>Úspešne jste se prihlásili k odberu newsletteru. Behem pár minut obdržíte confirmacní email. Klidnete na link pro potvrzení emailu. Pokud vám confirmacní email neprijde do 15 minut, zkontrolujte si složku se spamem.
48
- </p>";
49
-
50
- // Confirmation email subject (double opt-in)
51
- $defaults['confirmation_subject'] =
52
- "Potvrzení zájmu o odber novinek z {blog_title}";
53
-
54
- // Confirmation email body (double opt-in)
55
- $defaults['confirmation_message'] =
56
- "<p>Dobrý den {name},</p>
57
- <p>Obrželi jsem žádost o zasílání novinek pro tento email. Mužete jí potvrdit kliknutím
58
- <a href=\"{subscription_confirm_url}\"><strong>zde</strong></a>.
59
- Pokud se vám nedarí klinout na link, použijte následující odkaz:</p>
60
- <p>{subscription_confirm_url}</p>
61
- <p>Pokud žádost o zasílání novinek nevyšla od vás, stací jenom ignorovat tento email.</p>
62
- <p>Predem moc dekujeme.</p>";
63
-
64
-
65
- // Subscription confirmed text (after a user clicked the confirmation link
66
- // on the email he received
67
- $defaults['confirmed_text'] =
68
- "<p>Vaše žádost byla potvrzena!
69
- Dekujeme {name}!</p>";
70
-
71
- $defaults['confirmed_subject'] =
72
- "Vítejte {name},";
73
-
74
- $defaults['confirmed_message'] =
75
- "<p>Tato zpráva potvrzuje vyhovení vaší žádosti o {blog_title} newsletter.</p>
76
- <p>Díky!</p>
77
- <p>Pokud si už nadále neprejete dostávat novinky, <a href=\"{unsubscription_url}\">kliknete zde</a>, pokud si prejete zmenit své vstupní data, <a href=\"{profile_url}\">kliknete zde</a>.</p>";
78
-
79
- // Unsubscription request introductory text
80
- $defaults['unsubscription_text'] =
81
- "<p>Prosím potvrtte, že se chcete odhlásit z odebírání novinek
82
- <a href=\"{unsubscription_confirm_url}\">zde</a>.";
83
-
84
- // When you finally loosed your subscriber
85
- $defaults['unsubscribed_text'] =
86
- "<p>Velice nás to mrzí, ale byl jste práve odebrán z odberu novinek.</p>";
87
-
88
- $defaults['unsubscribed_subject'] =
89
- "Nashledanou {name},";
90
-
91
- $defaults['unsubscribed_message'] =
92
- "<p>Tento email potvrzuje vaše odhlášení z {blog_title} newslettru.</p>
93
- <p>Nashledanou!</p>";
94
-
95
-
96
-
97
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/en_US.php DELETED
@@ -1,118 +0,0 @@
1
- <?php
2
- // Those default options are used ONLY on FIRST setup and on plugin updates but limited to
3
- // new options that may have been added between your and new version.
4
- //
5
- // This is the main language file, too, which is always loaded by Newsletter. Other language
6
- // files are loaded according the WPLANG constant defined in wp-config.php file. Those language
7
- // specific files are "merged" with this one and the language specific configuration
8
- // keys override the ones in this file.
9
- //
10
- // Language specific files only need to override configurations containing texts
11
- // language dependant.
12
- //
13
- // All language file are UTF-8 encoded!
14
-
15
- $defaults_profile = array();
16
- $defaults_profile['profile_text'] = '{profile_form}<p>If you want to cancel your subscription, <a href="{unsubscription_confirm_url}">click here</a></p>';
17
- $defaults_profile['email'] = 'Email'; // Email field label
18
- $defaults_profile['email_error'] = 'Your email seems wrong, check it please.';
19
- $defaults_profile['name_status'] = 1;
20
- $defaults_profile['name'] = 'Name';
21
- $defaults_profile['name_error'] = 'Your name cannot be empty';
22
- $defaults_profile['surname'] = 'Last Name';
23
- $defaults_profile['surname_status'] = 0;
24
- $defaults_profile['sex_status'] = 0;
25
- $defaults_profile['sex'] = 'I\'m';
26
- $defaults_profile['sex_male'] = 'Male';
27
- $defaults_profile['sex_female'] = 'Female';
28
- $defaults_profile['privacy_status'] = 0;
29
- $defaults_profile['privacy'] = 'Subscribing you accept the privacy informative.';
30
- $defaults_profile['privacy_error'] = 'You must accept the privacy informative to subscribe.';
31
- $defaults_profile['subscribe'] = 'Subscribe now!';
32
- $defaults_profile['save'] = 'Save'; // Profile "save" button
33
-
34
- // Default values for main configuration
35
- $sitename = strtolower($_SERVER['SERVER_NAME']);
36
- if (substr($sitename, 0, 4) == 'www.') $sitename = substr($sitename, 4);
37
-
38
- $defaults_main = array(
39
- 'smtp_enabled'=>0,
40
- 'return_path'=>'',
41
- 'reply_to'=>'',
42
- 'test_email_0'=>get_option('admin_email'),
43
- 'test_name_0'=>'Subscriber',
44
- 'sender_email'=>'newsletter@' . $sitename,
45
- 'sender_name'=>get_option('blogname'),
46
- 'theme'=>'page-1',
47
- 'lock_message'=>'<div style="margin: 15px; padding: 15px; background-color: #ff9; border-color: 1px solid #000">
48
- This content is protected, only newsletter subscribers can access it. Subscribe now!
49
- [newsletter_form]
50
- </div>'
51
- );
52
-
53
-
54
- // Default values for subscription panel (transaled on other language files)
55
- $defaults = array();
56
- // Subscription page introductory text (befor the subscription form)
57
- $defaults['subscription_text'] =
58
- "<p>Subscribe to my newsletter by filling the form below.
59
- I'll try to make you happy.</p>
60
- <p>A confirmation email will be sent to your mailbox:
61
- please read the instructions to complete the subscription.</p>";
62
-
63
- // Message show after a subbscription request has made.
64
- $defaults['subscribed_text'] =
65
- "<p>You successfully subscribed to my newsletter.
66
- You'll receive in few minutes a confirmation email. Follow the link
67
- in it to confirm the subscription. If the email takes more than 15
68
- minutes to appear in your mailbox, check the spam folder.</p>";
69
-
70
- // Confirmation email subject (double opt-in)
71
- $defaults['confirmation_subject'] =
72
- "Confirm now your subscription to {blog_title}";
73
-
74
- // Confirmation email body (double opt-in)
75
- $defaults['confirmation_message'] =
76
- "<p>Hi {name},</p>
77
- <p>I received a subscription request for this email address. You can confirm it
78
- <a href=\"{subscription_confirm_url}\"><strong>clicking here</strong></a>.
79
- If you cannot click the link, use the following link:</p>
80
- <p>{subscription_confirm_url}</p>
81
- <p>If this subscription request has not been made from you, just ignore this message.</p>
82
- <p>Thank you.</p>";
83
-
84
-
85
- // Subscription confirmed text (after a user clicked the confirmation link
86
- // on the email he received
87
- $defaults['confirmed_text'] =
88
- "<p>Your subscription has been confirmed!
89
- Thank you {name}!</p>";
90
-
91
- $defaults['confirmed_subject'] =
92
- "Welcome aboard, {name}";
93
-
94
- $defaults['confirmed_message'] =
95
- "<p>The message confirm your subscription to {blog_title} newsletter.</p>
96
- <p>Thank you!</p>
97
- <p>If you want to cancel your unsubscription, <a href=\"{unsubscription_url}\">click here</a>, if you want to change your
98
- subscription data, <a href=\"{profile_url}\">click here</a>.</p>";
99
-
100
- // Unsubscription request introductory text
101
- $defaults['unsubscription_text'] =
102
- "<p>Please confirm you want to unsubscribe my newsletter
103
- <a href=\"{unsubscription_confirm_url}\">clicking here</a>.";
104
-
105
- // When you finally loosed your subscriber
106
- $defaults['unsubscribed_text'] =
107
- "<p>That make me cry, but I have removed your subscription...</p>";
108
-
109
- $defaults['unsubscribed_subject'] =
110
- "Goodbye, {name}";
111
-
112
- $defaults['unsubscribed_message'] =
113
- "<p>The message confirm your unsubscription to {blog_title} newsletter.</p>
114
- <p>Good bye!</p>";
115
-
116
- $defaults['email_theme'] = '{message}'; // do not translate!
117
-
118
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/it_IT.php DELETED
@@ -1,72 +0,0 @@
1
- <?php
2
-
3
- // Errors on subscription
4
- $defaults_profile = array();
5
- $defaults_profile['email_error'] = 'L\'indirizzo email non è corretto.';
6
- $defaults_profile['error_name'] = 'Il nome non è stato inserito.';
7
-
8
- $defaults_profile['profile_text'] = '{profile_form}<p>Se vuoi eliminare la tua iscrizione <a href="{unsubscription_confirm_url}">clicca qui</a></p>';
9
- $defaults_profile['email'] = 'Email'; // Email field label
10
- $defaults_profile['email_error'] = 'L\'indirizzo email non è corretto';
11
- $defaults_profile['name_status'] = 1;
12
- $defaults_profile['name'] = 'Nome';
13
- $defaults_profile['name_error'] = 'Il nome non può essere vuoto';
14
- $defaults_profile['surname'] = 'Cognome';
15
- $defaults_profile['surname_status'] = 0;
16
- $defaults_profile['sex_status'] = 0;
17
- $defaults_profile['sex'] = 'I\'m';
18
- $defaults_profile['sex_male'] = 'Maschio';
19
- $defaults_profile['sex_female'] = 'Femmina';
20
- $defaults_profile['privacy_status'] = 0;
21
- $defaults_profile['privacy'] = 'Accetto l\'informativa sulla privacy.';
22
- $defaults_profile['privacy_error'] = 'Devi accettare l\'informativa sulla privacy per iscriverti.';
23
- $defaults_profile['subscribe'] = 'Procedi';
24
- $defaults_profile['save'] = 'Salva'; // Profile "save" button
25
-
26
-
27
- $defaults = array();
28
- // Subscription page introductory text
29
- $defaults['subscription_text'] =
30
- "<p>Per iscriversi alla newsletter, lascia nome ed email qui sotto:
31
- riceverai una email con la quale potrai confermare l'iscrizione.</p>";
32
-
33
- // Subscription registration message
34
- $defaults['subscribed_text'] =
35
- "<p>L'iscrizione è quasi completa: controlla la tua
36
- casella di posta, c'è un messaggio per te con il quale confermare l'iscrizione.</p>";
37
-
38
- // Confirmation email (double opt-in)
39
- $defaults['confirmation_subject'] =
40
- "{name}, conferma l'iscrizione alle newsletter di {blog_title}";
41
-
42
- $defaults['confirmation_message'] =
43
- "<p>Ciao {name},</p>
44
- <p>hai richiesto l'iscrizione alla newsletter di {blog_title}.
45
- Conferma l'iscrizione <a href=\"{subscription_confirm_url}\"><strong>cliccando qui</strong></a>
46
- oppure copia il link qui sotto nel tu programma di navigazione:</p>
47
- <p>{subscription_confirm_url}</p>
48
- <p>Grazie!</p>";
49
-
50
- $defaults['confirmed_subject'] =
51
- "Benvenuto {name}!";
52
-
53
- $defaults['confirmed_message'] =
54
- "<p>Con questo messaggio ti confermo l'iscrizione alla newsletter.</p>
55
- <p>Grazie!</p>";
56
-
57
- // Subscription confirmed text
58
- $defaults['confirmed_text'] =
59
- "<p>{name}, la tua iscrizione è stata confermata.
60
- Buona lettura!</p>";
61
-
62
-
63
- $defaults['unsubscription_text'] =
64
- "<p>{name}, vuoi eliminare la tua iscrizione?
65
- Se sì... mi dispace, ma non ti trattengo oltre:</p>
66
- <p><a href=\"{unsubscription_confirm_url}\">Sì, voglio eliminare la mia iscrizione per sempre</a>.</p>";
67
-
68
- $defaults['unsubscribed_text'] =
69
- "<p>La tua iscrizione è stata definitivamente eliminata.</p>";
70
-
71
-
72
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/pt_PT.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- $defaults_profile['email_error'] = 'Endereço de email incorreto.';
3
- $defaults_profile['name_error'] = 'O nome não pode estar vazio.';
4
-
5
- // Subscription page introductory text (befor the subscription form)
6
- $defaults['subscription_text'] =
7
- "<p>Inscreva-se na newsletter preenchendo os campos abaixo.</p>
8
- <p>Um email de confirmação será enviado para a sua caixa de email:
9
- por favor leia as instruções e complete seu registro.</p>";
10
-
11
- // Message show after a subbscription request has made.
12
- $defaults['subscribed_text'] =
13
- "<p>Foi inscrito corretamente na newsletter.
14
- Dentro de alguns minutos irá receber um email de confirmação. Siga o link no email para confirmar a inscrição.
15
- Se o email demorar mais do que 15 minutos a chegar, verifique a sua caixa de SPAM.</p>";
16
-
17
- // Confirmation email subject (double opt-in)
18
- $defaults['confirmation_subject'] =
19
- "{name}, confirme sua inscrição no site {blog_title}";
20
-
21
- // Confirmation email body (double opt-in)
22
- $defaults['confirmation_message'] =
23
- "<p>Olá {name},</p>
24
- <p>Recebemos um pedido de inscrição no nosso sistema proveniente deste email. Para confirmar
25
- <a href=\"{subscription_confirm_url}\"><strong>clicando aqui</strong></a>.
26
- Se não consegue abrir o link, acesse através deste endereço:</p>
27
- <p>{subscription_confirm_url}</p>
28
- <p>Se o pedido de inscrição não é proveniente de si, apenas ignore esta mensagem.</p>
29
- <p>Obrigado.</p>";
30
-
31
-
32
- // Subscription confirmed text (after a user clicked the confirmation link
33
- // on the email he received
34
- $defaults['confirmed_text'] =
35
- "<p>Sua inscrição foi confirmada!
36
- Obrigado {name}.</p>";
37
-
38
- $defaults['confirmed_subject'] =
39
- "Bem vindo(a), {name}";
40
-
41
- $defaults['confirmed_message'] =
42
- "<p>A mensagem confirma a sua inscrição no nosso sistema.</p>
43
- <p>Obrigado.</p>";
44
-
45
- // Unsubscription request introductory text
46
- $defaults['unsubscription_text'] =
47
- "<p>Cancele a sua inscrição no sistema
48
- <a href=\"{unsubscription_confirm_url}\">clicando aqui</a>.";
49
-
50
- // When you finally loosed your subscriber
51
- $defaults['unsubscribed_text'] =
52
- "<p>Sua inscrição foi cancelada. Inscreva-se novamente quando quiser.</p>";
53
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
log.txt DELETED
@@ -1 +0,0 @@
1
- ---
 
main.php CHANGED
@@ -1,14 +1,12 @@
1
  <?php
 
2
 
3
- @include_once 'commons.php';
4
 
5
- $nc = new NewsletterControls();
6
-
7
- if (!$nc->is_action()) {
8
- $nc->data = get_option('newsletter_main');
9
- }
10
- else {
11
- if ($nc->is_action('remove')) {
12
 
13
  $wpdb->query("delete from " . $wpdb->prefix . "options where option_name like 'newsletter%'");
14
 
@@ -20,383 +18,350 @@ else {
20
  return;
21
  }
22
 
23
- if ($nc->is_action('save')) {
24
  $errors = null;
25
 
26
  // Validation
27
- $nc->data['sender_email'] = $newsletter->normalize_email($nc->data['sender_email']);
28
- if (!$newsletter->is_email($nc->data['sender_email'])) {
29
- $errors = __('Sender email is not correct');
30
  }
31
 
32
- $nc->data['return_path'] = $newsletter->normalize_email($nc->data['return_path']);
33
- if (!$newsletter->is_email($nc->data['return_path'], true)) {
34
- $errors = __('Return path email is not correct');
35
  }
36
- // With some providers the return path must be left empty
37
- //if (empty($options['return_path'])) $options['return_path'] = $options['sender_email'];
38
 
39
- $nc->data['test_email'] = $newsletter->normalize_email($nc->data['test_email']);
40
- if (!$newsletter->is_email($nc->data['test_email'], true)) {
41
- $errors = __('Test email is not correct');
42
  }
43
 
44
- $nc->data['reply_to'] = $newsletter->normalize_email($nc->data['reply_to']);
45
- if (!$newsletter->is_email($nc->data['reply_to'], true)) {
46
- $errors = __('Reply to email is not correct');
47
  }
48
 
49
- $nc->data['mode'] = (int)$nc->data['mode'];
50
- $nc->data['logs'] = (int)$nc->data['logs'];
51
-
52
- if ($errors == null) {
53
- update_option('newsletter_main', $nc->data);
54
  }
55
  }
56
 
57
- if ($action == 'test') {
58
- for ($i=0; $i<5; $i++) {
59
- if (!empty($nc->data['test_email_' . $i])) {
60
- $r = $newsletter->mail($nc->data['test_email_' . $i],
61
- 'Test email from Newsletter Plugin', '<p>This is a test message from Newsletter Plugin. You are reading it, so the plugin is working.</p>',
62
- true, null, 1);
63
- }
64
- }
65
- $messages = 'Test emails sent. Check the test mailboxes.';
66
- }
67
- }
68
 
 
 
 
69
 
70
- $nc->errors($errors);
71
- $nc->messages($messages);
72
- ?>
 
 
 
 
 
 
 
73
 
74
- <div class="wrap">
75
 
76
- <h2>Newsletter Main Configuration</h2>
77
-
78
- <?php include dirname(__FILE__) . '/header.php'; ?>
79
-
80
- <p><a href="javascript:void(jQuery('.hints').toggle())">Show/hide detailed documentation</a></p>
81
-
82
- <form method="post" action="">
83
- <?php $nc->init(); ?>
84
-
85
-
86
- <h3>Main settings</h3>
87
-
88
- <p class="intro">
89
- Configurations on this sub panel can block emails sent by Newsletter Pro. It's not a plugin limit but odd restrictions imposed by
90
- hosting providers. It's advisable to careful read the detailed documentation you'll found under every options, specially on the "return path"
91
- field. Try different combination of setting below before send a support request and do it in this way: one single change - test - other single
92
- change - test, and so on. Thank you for your collaboration.
93
- </p>
94
-
95
- <table class="form-table">
96
- <tr valign="top">
97
- <th>Sender name and address</th>
98
- <td>
99
- email address (required): <?php $nc->text('sender_email', 40); ?>
100
- name (optional): <?php $nc->text('sender_name', 40); ?>
101
-
102
- <div class="hints">
103
- These are the name and email address a subscriber will see on emails he'll receive.
104
- Be aware that hosting providers can block email with a sender address not of the same domain of the blog.<br />
105
- For example, if your blog is www.myblog.com, using as sender email "info@myblog.com" or
106
- "newsletter@myblog.com" is safer than using "myaccount@gmail.com". The name is optional but is more professional
107
- to set it (even if some providers with bugged mail server do not send email with a sender name set as reported by
108
- a customer).
109
- </div>
110
- </td>
111
- </tr>
112
- <tr>
113
- <th>Generic test subscribers</th>
114
- <td>
115
- <?php for ($i=0; $i<5; $i++) { ?>
116
- email: <?php $nc->text('test_email_' . $i, 30); ?> name: <?php $nc->text('test_name_' . $i, 30); ?>
117
- sex: <?php $nc->select('test_sex_' . $i, array('n'=>'None', 'f'=>'Female', 'm'=>'Male')); ?><br />
118
- <?php } ?>
119
- <div class="hints">
120
- These names and addresses are used by test functionalities on configuration panel. Be sure to fill at least the first
121
- test subscriber.<br />
122
- <strong>Do not use as email address the same address set as "sender"</strong> (see above), usually it does not work.<br />
123
- <strong>You should make a test every time you change one of the settings above</strong>.
124
- </div>
125
- </td>
126
- </tr>
127
- <tr valign="top">
128
- <th>Max emails per hour</th>
129
- <td>
130
- <?php $nc->text('scheduler_max', 5); ?>
131
- <div class="hints">
132
- The internal engine of Newsletter Pro sends email with the specified rate to stay under
133
- provider limits. The default value is 100 a very low value. The right value for you
134
- depends on your provider or server capacity.<br />
135
- Some examples. Hostgator: 500. Dreamhost: 100, asking can be raised to 200. Go Daddy: 1000 per day using their SMTP,
136
- unknown per hour rate. Gmail: 500 per day using their SMTP, unknown per hour rate.<br />
137
- My sites are on Hostgator or Linode VPS.<br />
138
- If you have a service with no limits on the number of emails, still PHP have memory and time limits. Newsletter Pro
139
- does it's best to detect those limits and to respect them so it can send out less emails per hour than excepted.
140
- </div>
141
- </td>
142
- </tr>
143
- <tr valign="top">
144
- <th>Newsletter user interaction page</th>
145
- <td>
146
- <?php $nc->page_themes('theme'); ?><br />
147
- or specify a blog page address:<br />
148
- WordPress page URL: <?php $nc->text('url', 70); ?> (eg. <?php echo get_option('home') . '/newsletter'; ?>, optional)
149
-
150
- <div class="hints">
151
- Newsletter Pro needs to interact with subscribers: subscription form, welcome messages, cancellation messages,
152
- profile editing form. If you want all those interactions within you blog theme, create a WordPress page and put
153
- in its body <strong>only</strong> the short code [newsletter] (as is). Then open that page in your browser and copy the
154
- page address (URL) in this field.<br />
155
- If you prefer to keep all those interaction out of your blog in a specific designed web page, use the text area
156
- to create a full valid HTML page. That page must contain the tag {message} used by Newspetter Pro to insert its
157
- messages. A basic template is already there for your convenience.
158
- </div>
159
- </td>
160
- </tr>
161
- <tr valign="top">
162
- <th>Return path</th>
163
- <td>
164
- <?php $nc->text('return_path', 40); ?> (valid email address)
165
- <div class="hints">
166
- This is the email address where delivery error messages are sent. Error message are sent back from mail systems when
167
- an email cannot be delivered to the receiver (full mailbox, unrecognized user and invalid address are the most common
168
- errors).<br />
169
- <strong>Some providers do not accept this field and block emails is present or if the email address has a
170
- different domain of the blog</strong> (see above the sender field notes). If you experience problem sending emails
171
- (just do some tests), try to leave it blank.
172
- </div>
173
- </td>
174
- </tr>
175
- <tr valign="top">
176
- <th>Reply to</th>
177
- <td>
178
- <?php $nc->text('reply_to', 40); ?> (valid email address)
179
- <div class="hints">
180
- This is the email address where subscribers will reply (eg. if they want to reply to a newsletter). Leave it blank if
181
- you don't want to specify a different address from the sender email above. As for return path, come provider do not like this
182
- setting active.
183
- </div>
184
- </td>
185
- </tr>
186
-
187
-
188
- </table>
189
- <p class="submit">
190
- <?php $nc->button('save', 'Save'); ?>
191
- <?php $nc->button('test', 'Send a test email'); ?>
192
- </p>
193
 
 
194
 
 
 
 
 
 
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- <h3>General parameters</h3>
198
-
199
- <table class="form-table">
200
- <!--
201
- <tr valign="top">
202
- <th><?php _e('Popup form number', 'newsletter'); ?></th>
203
- <td>
204
- <?php $nc->text('popup_form', 40); ?>
205
- <br />
206
- <?php _e('
207
- Form to be used for integration with wp-super-popup. Leave it empty to use the default form'); ?>
208
- </td>
209
- </tr>
210
- -->
211
- <tr valign="top">
212
- <th>Force receiver</th>
213
- <td>
214
- <?php $nc->text('receiver', 40); ?> (valid email address)
215
- <div class="hints">
216
- If set, EVERY email sent by newsletter will be sent to this address. Set this only if you need to test
217
- the plugin but already have a list of regular subscribers and you want to see what happens sending real
218
- newsletters.<br />
219
- If set, the subscription process works but new subscribers won't receive confirmation or welcome email!
220
- </div>
221
- </td>
222
- </tr>
223
- <tr valign="top">
224
- <th>Notifications</th>
225
- <td>
226
- <?php $nc->yesno('notify'); ?>
227
- <div class="hints">
228
- Enable or disable notifications of subscription, unsubscription and other events to blog administrator.
229
- </div>
230
- </td>
231
- </tr>
232
- <tr valign="top">
233
- <th>Enable access to editors?</th>
234
- <td>
235
- <?php $nc->yesno('editor'); ?>
236
- </td>
237
- </tr>
238
- <tr valign="top">
239
- <th>Logging</th>
240
- <td>
241
- <?php $nc->select('logs', array(0=>'None', 1=>'Only errors', 2=>'Normal', 3=>'Debug')); ?>
242
- <div class="hints">
243
- Be aware of two things: debug level may expose in your log file subscribers data and the file can
244
- grow very quickly (tens of megabytes).
245
- </div>
246
- </td>
247
- </tr>
248
-
249
- <tr valign="top">
250
- <th>API key</th>
251
- <td>
252
- <?php $nc->text('api_key', 40); ?>
253
- <div class="hints">
254
- When non-empty can be used to directly call the API for external integration. See API documentation on
255
- documentation panel.
256
- </div>
257
- </td>
258
- </tr>
259
-
260
- <tr>
261
- <th>Styling</th>
262
- <td>
263
- <?php $nc->textarea('css'); ?>
264
- <div class="hints">
265
- Add here your own css to style the forms. The whole form is enclosed in a div with class
266
- "newsletter" and it's made with a table (guys, I know about your table less design
267
- mission, don't blame me too much!)
268
- </div>
269
- </td>
270
- </tr>
271
- </table>
272
- <p class="submit">
273
- <?php $nc->button('save', 'Save'); ?>
274
- </p>
275
-
276
-
277
- <h3>Content locking</h3>
278
 
279
- <p class="intro">
280
- Content locking is a special feature that permits to "lock out" pieces of post content hiding them and unveiling
281
- them only to newsletter subscribers. I use it to hide special content on some post inviting the reader to subscribe the newsletter
282
- to read them.<br />
283
- Content on post can be hidden surrounding it with [newsletter_lock] and [/newsletter_lock] short codes.<br />
284
- A subscribe can see the hidden content after sign up or following a link on newsletters and welcome email generated by
285
- {unlock_url} tag. That link bring the user to the URL below that should be a single premium post/page where there is the hidden
286
- content or a list of premium posts with hidden content. The latter option can be implemented tagging all premium posts with a
287
- WordPress tag or adding them to a specific WordPress category.
288
- </p>
289
- <table class="form-table">
290
- <tr valign="top">
291
- <th>Unlock destination URL</th>
292
- <td>
293
- <?php $nc->text('lock_url', 70); ?>
294
- <div class="hints">
295
- This is a web address (URL) where users are redirect when they click on unlocking URL ({unlock_url})
296
- inserted in newsletters and welcome message. Usually you will redirect the user on a URL with with locked content
297
- (that will become visible) or in a place with a list of link to premium content. I send them on a tag page
298
- (http://www.satollo.net/tag/reserved) since I tag every premium content with "reserved".
299
- </div>
300
- </td>
301
- </tr>
302
- <tr valign="top">
303
- <th>Denied content message</th>
304
- <td>
305
- <?php $nc->textarea('lock_message'); ?>
306
- <div class="hints">
307
- This message is shown in place of protected post or page content which is surrounded with
308
- [newsletter_lock] and [/newsletter_lock] short codes.<br />
309
- Use HTML to format the message. PHP code is accepted and executed. WordPress short codes provided
310
- by other plugins work as well. It's a good
311
- practice to add the short code [newsletter_embed] to show a subscription form so readers can sign
312
- up the newsletter directly.<br />
313
- You can also add a subscription HTML form right here, like:<br />
314
- <br />
315
- &lt;form&gt;<br />
316
- Your email: &lt;input type="text" name="ne"/&gt;<br />
317
- &lt;input type="submit" value="Subscribe now!"/&gt;<br />
318
- &lt;/form&gt;<br />
319
- <br />
320
- There is no need to specify a form method or action, Newsletter Pro will take care of. To give more evidence of your
321
- alternative content you can style it:<br />
322
- <br />
323
- &lt;div style="margin: 15px; padding: 15px; background-color: #ff9; border-color: 1px solid #000"&gt;<br />
324
- blah, blah, blah...<br />
325
- &lt;/div&gt;
326
- </div>
327
- </td>
328
- </tr>
329
- </table>
330
- <p class="submit">
331
- <?php $nc->button('save', 'Save'); ?>
332
- </p>
333
 
 
334
 
 
335
 
 
 
 
 
 
 
336
 
337
- <h3>System check</h3>
338
-
339
- <table class="form-table">
340
- <tr valign="top">
341
- <th>Cron</th>
342
- <td>
343
- <?php if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) { ?>
344
- <strong>The WordPress cron system is disabled.</strong> Emails won't be
345
- sent without a cron system active, check your wp-config.php file for definition
346
- of DISABLE_WP_CRON and remove it.
347
- <?php } ?>
348
- </td>
349
- </tr>
350
- <tr valign="top">
351
- <th>Database</th>
352
- <td>
353
- <?php $wait_timeout = $wpdb->get_var("select @@wait_timeout"); ?>
354
- Wait timeout: <?php echo $wait_timeout; ?> seconds
355
- <br />
356
- <?php if ($wait_timeout > 300) { ?>
357
- The timeout is ok
358
- <?php } else { ?>
359
- <?php $wpdb->query("set session wait_timeout=300"); ?>
360
- <?php if (300 != $wpdb->get_var("select @@wait_timeout")) { ?>
361
- Cannot rise wait timout, problems may occur while sending.
362
- <?php } else { ?>
363
- Wait timeout can be changed
364
- <?php } ?>
365
- <?php } ?>
366
- <div class="hints">
367
- Connections to database have a idle time limit. If an email takes long time to be sent (due to
368
- SMTP or local mail system slowness) this limit can be reached. Losing a connection is a bad thing for
369
- Newsletter Pro, so it tries to raise this limit and to keep the connection alive sending queries.
370
- </div>
371
- </td>
372
- </tr>
373
- <tr valign="top">
374
- <th>PHP Execution time</th>
375
- <td>
376
- Max execution time: <?php echo ini_get('max_execution_time'); ?> seconds
377
- <div class="hints">
378
- Even if PHP execution max time can usually be changed web servers can have external
379
- controller that will kill PHP scripts if they run too long (like
380
- fastcgi). Time limit can be a problem while using external SMTPs, if they are slow. Newsletter
381
- Pro, while sending, continously check the time limit and stops it self as the timeout is approaching.
382
- </div>
383
- </td>
384
- </tr>
385
- <tr valign="top">
386
- <th>Memory limit</th>
387
- <td>
388
- <?php echo @ini_get('memory_limit'); ?>
389
- <div class="hints">
390
- Newsletter Pro tries (as does WordPress on admin side) to raise the memory limit to
391
- 256 megabytes while sending.
392
- </div>
393
- </td>
394
- </tr>
395
-
396
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
 
398
  <p class="submit">
399
- <?php $nc->button_confirm('remove', 'Totally remove this plugin', 'Really sure to totally remove this plugin. All data will be lost!'); ?>
 
400
  </p>
401
 
402
  </form>
1
  <?php
2
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
 
4
+ $controls = new NewsletterControls();
5
 
6
+ if (!$controls->is_action()) {
7
+ $controls->data = get_option('newsletter_main');
8
+ } else {
9
+ if ($controls->is_action('remove')) {
 
 
 
10
 
11
  $wpdb->query("delete from " . $wpdb->prefix . "options where option_name like 'newsletter%'");
12
 
18
  return;
19
  }
20
 
21
+ if ($controls->is_action('save')) {
22
  $errors = null;
23
 
24
  // Validation
25
+ $controls->data['sender_email'] = $newsletter->normalize_email($controls->data['sender_email']);
26
+ if (!$newsletter->is_email($controls->data['sender_email'])) {
27
+ $controls->errors .= 'The sender email address is not correct.<br />';
28
  }
29
 
30
+ $controls->data['return_path'] = $newsletter->normalize_email($controls->data['return_path']);
31
+ if (!$newsletter->is_email($controls->data['return_path'], true)) {
32
+ $controls->errors .= 'Return path email is not correct.<br />';
33
  }
 
 
34
 
35
+ $controls->data['test_email'] = $newsletter->normalize_email($controls->data['test_email']);
36
+ if (!$newsletter->is_email($controls->data['test_email'], true)) {
37
+ $controls->errors .= 'Test email is not correct.<br />';
38
  }
39
 
40
+ $controls->data['reply_to'] = $newsletter->normalize_email($controls->data['reply_to']);
41
+ if (!$newsletter->is_email($controls->data['reply_to'], true)) {
42
+ $controls->errors .= 'Reply to email is not correct.<br />';
43
  }
44
 
45
+ if (empty($controls->errors)) {
46
+ update_option('newsletter_main', $controls->data);
 
 
 
47
  }
48
  }
49
 
50
+ if ($controls->is_action('smtp_test')) {
 
 
 
 
 
 
 
 
 
 
51
 
52
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
53
+ require_once ABSPATH . WPINC . '/class-smtp.php';
54
+ $mail = new PHPMailer();
55
 
56
+ $mail->IsSMTP();
57
+ $mail->SMTPDebug = true;
58
+ $mail->CharSet = 'UTF-8';
59
+ $message = 'This Email is sent by PHPMailer of WordPress';
60
+ $mail->IsHTML(false);
61
+ $mail->Body = $message;
62
+ $mail->From = $controls->data['sender_email'];
63
+ $mail->FromName = $controls->data['sender_name'];
64
+ if (!empty($controls->data['return_path'])) $mail->Sender = $options['return_path'];
65
+ if (!empty($controls->data['reply_to'])) $mail->AddReplyTo($controls->data['reply_to']);
66
 
67
+ $mail->Subject = '[' . get_option('blogname') . '] SMTP test';
68
 
69
+ $mail->Host = $controls->data['smtp_host'];
70
+ if (!empty($controls->data['smtp_port'])) $mail->Port = (int) $controls->data['smtp_port'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ $mail->SMTPSecure = $controls->data['smtp_secure'];
73
 
74
+ if (!empty($controls->data['smtp_user'])) {
75
+ $mail->SMTPAuth = true;
76
+ $mail->Username = $controls->data['smtp_user'];
77
+ $mail->Password = $controls->data['smtp_pass'];
78
+ }
79
 
80
+ $mail->SMTPKeepAlive = true;
81
+ $mail->ClearAddresses();
82
+ $mail->AddAddress($controls->data['test_email']);
83
+ ob_start();
84
+ $mail->Send();
85
+ $mail->SmtpClose();
86
+ $debug = htmlspecialchars(ob_get_clean());
87
+ ob_end_clean();
88
+
89
+ if ($mail->IsError()) $controls->errors = $mail->ErrorInfo;
90
+ else $controls->messages = 'Success.';
91
+
92
+ $controls->messages .= '<textarea style="width:100%;height:250px;font-size:10px">';
93
+ $controls->messages .= $debug;
94
+ $controls->messages .= '</textarea>';
95
+ }
96
+ }
97
+ ?>
98
 
99
+ <div class="wrap">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletter-configuration'; ?>
102
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
+ <h2>Newsletter Main Configuration</h2>
105
 
106
+ <?php $controls->show(); ?>
107
 
108
+ <div class="preamble">
109
+ <p>
110
+ Do not be scared by all those configurations. Only <strong>basic settings</strong> are important and should be reviewed to
111
+ make Newsletter plugin to work correctly. If something seems to now work, run a test reading what you should expect from it.
112
+ </p>
113
+ </div>
114
 
115
+ <form method="post" action="">
116
+ <?php $controls->init(); ?>
117
+
118
+ <div id="tabs">
119
+
120
+ <ul>
121
+ <li><a href="#tabs-1">Basic settings</a></li>
122
+ <li><a href="#tabs-2">Advanced settings</a></li>
123
+ <li><a href="#tabs-5">SMTP</a></li>
124
+ <li><a href="#tabs-3">Content locking</a></li>
125
+ </ul>
126
+
127
+ <div id="tabs-1">
128
+
129
+ <!-- Main settings -->
130
+
131
+ <p class="intro">
132
+ Configurations on this sub panel can block emails sent by Newsletter Pro. It's not a plugin limit but odd restrictions imposed by
133
+ hosting providers. It's advisable to careful read the detailed documentation you'll found under every options, specially on the "return path"
134
+ field. Try different combination of setting below before send a support request and do it in this way: one single change - test - other single
135
+ change - test, and so on. Thank you for your collaboration.
136
+ </p>
137
+
138
+ <table class="form-table">
139
+
140
+ <tr valign="top">
141
+ <th>Sender name and address</th>
142
+ <td>
143
+ email address (required): <?php $controls->text_email('sender_email', 40); ?>
144
+ name (optional): <?php $controls->text('sender_name', 40); ?>
145
+
146
+ <div class="hints">
147
+ These are the name and email address a subscriber will see on emails he'll receive.
148
+ Be aware that hosting providers can block email with a sender address not of the same domain of the blog.<br />
149
+ For example, if your blog is www.myblog.com, using as sender email "info@myblog.com" or
150
+ "newsletter@myblog.com" is safer than using "myaccount@gmail.com". The name is optional but is more professional
151
+ to set it (even if some providers with bugged mail server do not send email with a sender name set as reported by
152
+ a customer).
153
+ </div>
154
+ </td>
155
+ </tr>
156
+ <tr valign="top">
157
+ <th>Max emails per hour</th>
158
+ <td>
159
+ <?php $controls->text('scheduler_max', 5); ?>
160
+ <div class="hints">
161
+ The internal engine of Newsletter Pro sends email with the specified rate to stay under
162
+ provider limits. The default value is 100 a very low value. The right value for you
163
+ depends on your provider or server capacity.<br />
164
+ Some examples. Hostgator: 500. Dreamhost: 100, asking can be raised to 200. Go Daddy: 1000 per day using their SMTP,
165
+ unknown per hour rate. Gmail: 500 per day using their SMTP, unknown per hour rate.<br />
166
+ My sites are on Hostgator or Linode VPS.<br />
167
+ If you have a service with no limits on the number of emails, still PHP have memory and time limits. Newsletter Pro
168
+ does it's best to detect those limits and to respect them so it can send out less emails per hour than excepted.
169
+ </div>
170
+ </td>
171
+ </tr>
172
+ <tr valign="top">
173
+ <th>Return path</th>
174
+ <td>
175
+ <?php $controls->text_email('return_path', 40); ?> (valid email address)
176
+ <div class="hints">
177
+ This is the email address where delivery error messages are sent. Error message are sent back from mail systems when
178
+ an email cannot be delivered to the receiver (full mailbox, unrecognized user and invalid address are the most common
179
+ errors).<br />
180
+ <strong>Some providers do not accept this field and block emails is present or if the email address has a
181
+ different domain of the blog</strong> (see above the sender field notes). If you experience problem sending emails
182
+ (just do some tests), try to leave it blank.
183
+ </div>
184
+ </td>
185
+ </tr>
186
+ <tr valign="top">
187
+ <th>Reply to</th>
188
+ <td>
189
+ <?php $controls->text_email('reply_to', 40); ?> (valid email address)
190
+ <div class="hints">
191
+ This is the email address where subscribers will reply (eg. if they want to reply to a newsletter). Leave it blank if
192
+ you don't want to specify a different address from the sender email above. As for return path, come provider do not like this
193
+ setting active.
194
+ </div>
195
+ </td>
196
+ </tr>
197
+
198
+ </table>
199
+ </div>
200
+
201
+ <div id="tabs-2">
202
+
203
+ <!-- General parameters -->
204
+
205
+ <table class="form-table">
206
+
207
+ <tr valign="top">
208
+ <th>Enable access to editors?</th>
209
+ <td>
210
+ <?php $controls->yesno('editor'); ?>
211
+ </td>
212
+ </tr>
213
+
214
+ <tr valign="top">
215
+ <th>API key</th>
216
+ <td>
217
+ <?php $controls->text('api_key', 40); ?>
218
+ <div class="hints">
219
+ When non-empty can be used to directly call the API for external integration. See API documentation on
220
+ documentation panel.
221
+ </div>
222
+ </td>
223
+ </tr>
224
+
225
+ <tr>
226
+ <th>Styling</th>
227
+ <td>
228
+ <?php $controls->textarea('css'); ?>
229
+ <div class="hints">
230
+ Add here your own css to style the forms. The whole form is enclosed in a div with class
231
+ "newsletter" and it's made with a table (guys, I know about your table less design
232
+ mission, don't blame me too much!)
233
+ </div>
234
+ </td>
235
+ </tr>
236
+ <tr valign="top">
237
+ <th>Email body content encoding</th>
238
+ <td>
239
+ <?php $controls->select('content_transfer_encoding', array('' => 'Default', '8bit' => '8 bit', 'base64' => 'Base 64')); ?>
240
+ <div class="hints">
241
+ Used only by some modules. Choose base64 to have chunked email body when server reports too long email line.
242
+ </div>
243
+ </td>
244
+ </tr>
245
+
246
+ </table>
247
+
248
+ </div>
249
+
250
+
251
+ <div id="tabs-5">
252
+ <div class="tab-preamble">
253
+ <p>
254
+ To use an external SMTP (mail sending service), fill in the SMTP data and activate it. SMTP will be used for any
255
+ messages sent by Newsletter (subscription messages and newsletters). SMTP is required to send email with Gmail or
256
+ GoDaddy hosting account.
257
+ Read more <a href="http://www.satollo.net/godaddy-using-smtp-external-server-on-shared-hosting" target="_blank">here</a>.
258
+ Test button below sends an email to the first test address configured above and works even if SMTP is not enabled. If you get a "connection refused"
259
+ message, check the SMTP settings if they are correct and then contact your hosting provider. If you get a "relay denied" contact your
260
+ SMTP service provider.
261
+ </p>
262
+ <p>
263
+ Consider <a href="http://sendgrid.tellapal.com/a/clk/3ZVbH7" target="_blank">SendGrid</a> for a serious and reliable SMTP service.
264
+ </p>
265
+ </div>
266
+
267
+ <table class="form-table">
268
+ <tr>
269
+ <th>Enable external SMTP?</th>
270
+ <td><?php $controls->yesno('smtp_enabled'); ?></td>
271
+ </tr>
272
+ <tr>
273
+ <th>SMTP host/port</th>
274
+ <td>
275
+ host: <?php $controls->text('smtp_host', 30); ?>
276
+ port: <?php $controls->text('smtp_port', 6); ?>
277
+ <?php $controls->select('smtp_secure', array('' => 'No secure protocol', 'tls' => 'TLS protocol', 'ssl' => 'SSL protocol')); ?>
278
+ <div class="hints">
279
+ Leave port empty for default value (25). To use Gmail try host "smtp.gmail.com" and port "465" and SSL protocol (without quotes).
280
+ For GoDaddy use "relay-hosting.secureserver.net".
281
+ </div>
282
+ </td>
283
+ </tr>
284
+ <tr>
285
+ <th>Authentication</th>
286
+ <td>
287
+ user: <?php $controls->text('smtp_user', 30); ?>
288
+ password: <?php $controls->text('smtp_pass', 30); ?>
289
+ <div class="hints">
290
+ If authentication is not required, leave "user" field blank.
291
+ </div>
292
+ </td>
293
+ </tr>
294
+ </table>
295
+ <?php $controls->button('smtp_test', 'Test'); ?>
296
+
297
+ </div>
298
+
299
+
300
+ <div id="tabs-3">
301
+ <!-- Content locking -->
302
+ <div class="tab-preamble">
303
+ <p><a href="http://www.satollo.net/plugins/newsletter/newsletter-locked-content" target="_blank">Read more about locked content</a>.</p>
304
+ <p>
305
+ Content locking is a special feature that permits to "lock out" pieces of post content hiding them and unveiling
306
+ them only to newsletter subscribers. I use it to hide special content on some post inviting the reader to subscribe the newsletter
307
+ to read them.<br />
308
+ Content on post can be hidden surrounding it with [newsletter_lock] and [/newsletter_lock] short codes.<br />
309
+ A subscribe can see the hidden content after sign up or following a link on newsletters and welcome email generated by
310
+ {unlock_url} tag. That link bring the user to the URL below that should be a single premium post/page where there is the hidden
311
+ content or a list of premium posts with hidden content. The latter option can be implemented tagging all premium posts with a
312
+ WordPress tag or adding them to a specific WordPress category.
313
+ </p>
314
+ </div>
315
+ <table class="form-table">
316
+ <tr valign="top">
317
+ <th>Unlock destination URL</th>
318
+ <td>
319
+ <?php $controls->text('lock_url', 70); ?>
320
+ <div class="hints">
321
+ This is a web address (URL) where users are redirect when they click on unlocking URL ({unlock_url})
322
+ inserted in newsletters and welcome message. Usually you will redirect the user on a URL with with locked content
323
+ (that will become visible) or in a place with a list of link to premium content. I send them on a tag page
324
+ (http://www.satollo.net/tag/reserved) since I tag every premium content with "reserved".
325
+ </div>
326
+ </td>
327
+ </tr>
328
+ <tr valign="top">
329
+ <th>Denied content message</th>
330
+ <td>
331
+ <?php $controls->textarea('lock_message'); ?>
332
+ <div class="hints">
333
+ This message is shown in place of protected post or page content which is surrounded with
334
+ [newsletter_lock] and [/newsletter_lock] short codes.<br />
335
+ Use HTML to format the message. PHP code is accepted and executed. WordPress short codes provided
336
+ by other plugins work as well. It's a good
337
+ practice to add the short code [newsletter_embed] to show a subscription form so readers can sign
338
+ up the newsletter directly.<br />
339
+ You can also add a subscription HTML form right here, like:<br />
340
+ <br />
341
+ &lt;form&gt;<br />
342
+ Your email: &lt;input type="text" name="ne"/&gt;<br />
343
+ &lt;input type="submit" value="Subscribe now!"/&gt;<br />
344
+ &lt;/form&gt;<br />
345
+ <br />
346
+ There is no need to specify a form method or action, Newsletter Pro will take care of. To give more evidence of your
347
+ alternative content you can style it:<br />
348
+ <br />
349
+ &lt;div style="margin: 15px; padding: 15px; background-color: #ff9; border-color: 1px solid #000"&gt;<br />
350
+ blah, blah, blah...<br />
351
+ &lt;/div&gt;
352
+ </div>
353
+ </td>
354
+ </tr>
355
+ </table>
356
+
357
+ </div>
358
+
359
+
360
+ </div> <!-- tabs -->
361
 
362
  <p class="submit">
363
+ <?php $controls->button('save', 'Save'); ?>
364
+ <?php $controls->button_confirm('remove', 'Totally remove this plugin', 'Really sure to totally remove this plugin. All data will be lost!'); ?>
365
  </p>
366
 
367
  </form>
main/languages/en_US.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Default values for main configuration
4
+ $sitename = strtolower($_SERVER['SERVER_NAME']);
5
+ if (substr($sitename, 0, 4) == 'www.') $sitename = substr($sitename, 4);
6
+
7
+ $options = array(
8
+ 'smtp_enabled'=>0,
9
+ 'return_path'=>'',
10
+ 'reply_to'=>'',
11
+ 'sender_email'=>'newsletter@' . $sitename,
12
+ 'sender_name'=>get_option('blogname'),
13
+ 'lock_message'=>'<div style="margin: 15px; padding: 15px; background-color: #ff9; border-color: 1px solid #000">
14
+ This content is protected, only newsletter subscribers can access it. Subscribe now!
15
+ [newsletter_form]
16
+ </div>'
17
+ );
options.php DELETED
@@ -1,338 +0,0 @@
1
- <?php
2
-
3
- @include_once 'commons.php';
4
-
5
- $options = get_option('newsletter');
6
-
7
- if ($action == 'save') {
8
- $options = stripslashes_deep($_POST['options']);
9
- $options['confirmed_url'] = trim($options['confirmed_url']);
10
- if ($errors == null) {
11
- update_option('newsletter', $options);
12
- }
13
- }
14
-
15
- if ($action == 'reset') {
16
- @include_once(dirname(__FILE__) . '/languages/en_US_options.php');
17
- if (WPLANG != '') @include_once(dirname(__FILE__) . '/languages/' . WPLANG . '_options.php');
18
- $options = array_merge($options, $newsletter_default_options);
19
- update_option('newsletter', $options);
20
- }
21
-
22
- $nc = new NewsletterControls($options);
23
- ?>
24
-
25
- <?php if ($options['novisual'] != 1) { ?>
26
- <script type="text/javascript" src="<?php echo get_option('siteurl'); ?>/wp-content/plugins/newsletter/tiny_mce/tiny_mce.js"></script>
27
-
28
- <script type="text/javascript">
29
- tinyMCE.init({
30
- mode : "specific_textareas",
31
- editor_selector : "visual",
32
- theme : "advanced",
33
- theme_advanced_disable : "styleselect",
34
- relative_urls : false,
35
- remove_script_host : false,
36
- theme_advanced_buttons3: "",
37
- theme_advanced_toolbar_location : "top",
38
- theme_advanced_resizing : true,
39
- theme_advanced_statusbar_location: "bottom",
40
- document_base_url : "<?php echo get_option('home'); ?>/",
41
- content_css : "<?php echo get_option('blogurl'); ?>/wp-content/plugins/newsletter/editor.css?" + new Date().getTime()
42
- });
43
- </script>
44
- <?php } ?>
45
-
46
- <div class="wrap">
47
-
48
- <?php $nc->errors($errors); ?>
49
-
50
- <h2>Newsletter Subscription and Cancellation Process</h2>
51
- <p>
52
- In this panel you can configure the subscription and cancellation process, setting every message, the single or double opt in and
53
- even a customized subscription form.<br />
54
- All tags that can be used on texts below are listed under <a href="#documentation">documentation</a> paragraph.
55
- </p>
56
-
57
-
58
- <form method="post" action="">
59
- <?php $nc->init(); ?>
60
-
61
- <h3>Working mode</h3>
62
- <div>
63
- <p>Choose how the subscription process to your newsletter works.</p>
64
- <table class="form-table">
65
- <tr valign="top">
66
- <th>Opt In</th>
67
- <td>
68
- <?php $nc->select('noconfirmation', array(0=>'Double Opt In', 1=>'Single Opt In')); ?>
69
- <div class="hints">
70
- <strong>Double Opt In</strong> means subscribers need to confirm their email address by an activation link sent them on a activation email message.<br />
71
- <strong>Single Opt In</strong> means subscribers do not need to confirm their email address.<br />
72
- </div>
73
- </td>
74
- </tr>
75
- </table>
76
- <p class="submit">
77
- <?php $nc->button('save', __('Save', 'newsletter')); ?>
78
- </p>
79
- </div>
80
-
81
- <h3>Subscription</h3>
82
- <div>
83
- <table class="form-table">
84
- <tr valign="top">
85
- <th>Subscription page</th>
86
- <td>
87
- <?php $nc->editor('subscription_text'); ?>
88
- <div class="hints">
89
- This is the text shown to subscriber before the subscription form (which is added automatically). To create a custom form,
90
- code it directly editing the text in HTML mode (Newsletter will auto discover it).
91
- See documentation about custom forms. A little example:<br />
92
- &lt;form&gt;<br />
93
- Your email: &lt;input type="text" name="ne"/&gt;<br />
94
- &lt;input type="submit" value="Subscribe now!"/&gt;<br />
95
- &lt;/form&gt;<br />
96
- Field names are: "ne" email, "nn" name, "ns" surname, "nx" sex (values: f, m, n),
97
- "nl[]" list (the field value must be the list number, you can use checkbox, radio, select or even hidden
98
- HTML input tag), "npN" custom profile (with N from 1 to 19).
99
- </div>
100
- </td>
101
- </tr>
102
- </table>
103
-
104
- <p class="submit">
105
- <?php $nc->button('save', 'Save'); ?>
106
- </p>
107
- </div>
108
-
109
-
110
-
111
- <h3>Confirmation (only for double opt-in)</h3>
112
- <div>
113
- <table class="form-table">
114
- <tr valign="top">
115
- <th>Confirmation required message</th>
116
- <td>
117
- <?php $nc->editor('subscribed_text'); ?>
118
- <div class="hints">
119
- This is the text showed to a user who has pressed "subscribe me" on the previous
120
- step informing that an email to confirm subscription has just been sent. Remember
121
- the user to check the spam folder and to follow the email instructions.
122
- </div>
123
- </td>
124
- </tr>
125
-
126
- <!-- CONFIRMATION EMAIL -->
127
- <tr valign="top">
128
- <th>Confirmation email</th>
129
- <td>
130
- <?php $nc->email('confirmation'); ?>
131
- <div class="hints">
132
- Message sent by email to new subscribers with instructions to confirm their subscription
133
- (for double opt-in process). Do not forget to add the <strong>{subscription_confirm_url}</strong>
134
- that users must click to activate their subscription.<br />
135
- Sometime can be useful to add a <strong>{unsubscription_url}</strong> to let users to
136
- cancel if they wrongly subscribed your service.
137
- </div>
138
- </td>
139
- </tr>
140
- </table>
141
-
142
- <p class="submit">
143
- <?php $nc->button('save', 'Save'); ?>
144
- </p>
145
- </div>
146
-
147
-
148
-
149
- <h3>Welcome message/page</h3>
150
- <div>
151
- <table class="form-table">
152
- <tr valign="top">
153
- <th>Welcome message</th>
154
- <td>
155
- <?php $nc->editor('confirmed_text'); ?>
156
- <div class="hints">
157
- Showed when the user follow the confirmation URL sent to him with previous email
158
- settings or if signed up directly with no double opt-in process. You can use the <strong>{profile_form}</strong> tag to let the user to
159
- complete it's profile.
160
- </div>
161
- </td>
162
- </tr>
163
-
164
- <tr valign="top">
165
- <th>Alternative custom welcome page</th>
166
- <td>
167
- <?php $nc->text('confirmed_url', 70); ?>
168
- <div class="hints">
169
- A full page address (http://yourblog.com/welcome) to be used instead of message above. If empty the message is
170
- used.
171
- </div>
172
- </td>
173
- </tr>
174
-
175
- <tr valign="top">
176
- <th>Conversion tracking code<br/><small>ADVANCED</small></th>
177
- <td>
178
- <?php $nc->textarea('confirmed_tracking'); ?>
179
- <div class="hints">
180
- The code is injected AS-IS in welcome page and can be used to track conversion
181
- (you can use PHP if needed). Conversion code is usually supply by tracking services,
182
- like Google AdWords, Google Analytics and so on.</div>
183
- </td>
184
- </tr>
185
-
186
- <!-- WELCOME/CONFIRMED EMAIL -->
187
- <tr valign="top">
188
- <th>
189
- Welcome email<br /><small>The right place where to put bonus content link</small>
190
- </th>
191
- <td>
192
- <?php $nc->email('confirmed'); ?>
193
- <div class="hints">
194
- Email sent to the user to confirm his subscription, the successful confirmation
195
- page, the welcome email. This is the right message where to put a <strong>{unlock_url}</strong> link to remember to the
196
- user where is the premium content (if any, main configuration panel).<br />
197
- It's a good idea to add the <strong>{unsubscription_url}</strong> too and the <strong>{profile_url}</strong>
198
- letting users to cancel or manage/complete their profile.
199
- </div>
200
- </td>
201
- </tr>
202
-
203
- </table>
204
-
205
- <p class="submit">
206
- <?php $nc->button('save', 'Save'); ?>
207
- </p>
208
- </div>
209
-
210
-
211
- <h3>Cancellation</h3>
212
- <div>
213
- <p class="intro">
214
- A user starts the cancellation process clicking the unsubscription link in
215
- a newsletter. This link contains the email to unsubscribe and some unique information
216
- to avoid hacking. The user are required to confirm the unsubscription: this is the last
217
- step where YOU can communicate with your almost missed user.
218
- <br />
219
- To create immediate cancellation, you can use the <strong>{unsubscription_confirm_url}</strong>
220
- in your newsletters and upon click on that link goodbye message and email are used directly
221
- skipping the confirm request.
222
- </p>
223
-
224
- <table class="form-table">
225
- <tr valign="top">
226
- <th>Cancellation message</th>
227
- <td>
228
- <?php $nc->editor('unsubscription_text'); ?>
229
- <div class="hints">
230
- This text is show to users who click on a "unsubscription link" in a newsletter
231
- email. You <strong>must</strong> insert a link in the text that user can follow to confirm the
232
- unsubscription request using the tag <strong>{unsubscription_confirm_url}</strong>.
233
- </div>
234
- </td>
235
- </tr>
236
-
237
- <!-- Text showed to the user on successful unsubscription -->
238
- <tr valign="top">
239
- <th>Goodbye message</th>
240
- <td>
241
- <?php $nc->editor('unsubscribed_text'); ?>
242
- <div class="hints">
243
- Shown to users after the cancellation has been completed.
244
- </div>
245
- </td>
246
- </tr>
247
-
248
- <!-- GOODBYE EMAIL -->
249
- <tr valign="top">
250
- <th>Goodbye email</th>
251
- <td>
252
- <?php $nc->email('unsubscribed'); ?>
253
- <div class="hints">
254
- Sent after a cancellation, is the last message you send to the user before his removal
255
- from your newsletter subscribers. Leave the subject empty to disable this message.
256
- </div>
257
- </td>
258
- </tr>
259
- </table>
260
- <p class="submit">
261
- <?php $nc->button('save', 'Save'); ?>
262
- </p>
263
- </div>
264
-
265
- <h3>Other configurations (advanced)</h3>
266
- <div>
267
- <table class="form-table">
268
- <!--
269
- <tr>
270
- <th>Email theme</th>
271
- <td>
272
- <?php if ($nc->data['email_theme_novisual'] == 1) $nc->textarea('email_theme'); else $nc->editor('email_theme'); ?><br />
273
- <?php $nc->select('email_theme_novisual', array(0=>'Edit with visual editor', 1=>'Edit as plain text')); ?> (save to apply)
274
- <div class="hints">
275
- Subscription and cancellation processes send out emails as you configured above. To apply a general theme to those
276
- emails, you can create an HTML layout here. You can also use PHP code, just remember to disable the visual editor and to
277
- keep it disabled.<br />
278
- <strong>Messages are inserted in the theme where you put the {message} tag, don't forget it!</strong>
279
- </div>
280
- </td>
281
- </tr>
282
- -->
283
- <tr valign="top">
284
- <th>Disable visual editors?</th>
285
- <td>
286
- <?php $nc->yesno('novisual'); ?>
287
- </td>
288
- </tr>
289
- </table>
290
-
291
-
292
- <p class="submit">
293
- <?php $nc->button('save', 'Save'); ?>
294
- <?php $nc->button_confirm('reset', 'Reset all', 'Are you sure you want to reset all?'); ?>
295
- </p>
296
- </div>
297
-
298
- <a name="documentation"></a>
299
- <h3>Documentation</h3>
300
- <div>
301
- <h4>User's data</h4>
302
- <p>
303
- <strong>{name}</strong>
304
- The user name<br />
305
- <strong>{surname}</strong>
306
- The user surname<br />
307
- <strong>{email}</strong>
308
- The user email<br />
309
- <strong>{ip}</strong>
310
- The IP address from where the subscription started<br />
311
- <strong>{id}</strong>
312
- The user id<br />
313
- <strong>{token}</strong>
314
- The user secret token<br />
315
- <strong>{profile_N}</strong>
316
- The user profile field number N (from 1 to 19)<br />
317
- </p>
318
-
319
- <h4>Action URLs and forms</h4>
320
- <p>
321
- <strong>{subscription_confirm_url}</strong>
322
- URL to build a link to confirmation of subscription when double opt-in is used. To be used on confirmation email.<br />
323
- <strong>{unsubscription_url}</strong>
324
- URL to build a link to start the cancellation process. To be used on every newsletter to let the user to cancel.<br />
325
- <strong>{unsubscription_confirm_url}</strong>
326
- URL to build a link to an immediate cancellation action. Can be used on newsletters if you want an immediate cancellation or
327
- on cancellation page (displayed on {unsubscription_url}) to ask a cancellation confirmation.<br />
328
- <strong>{profile_url}</strong>
329
- URL to build a link to user's profile page (see the User Profile panel)<br />
330
- <strong>{unlock_url}</strong>
331
- Special URL to build a link that on click unlocks protected contents. See Main Configuration panel.<br />
332
- <strong>{profile_form}</strong>
333
- Insert the profile form with user's data. Usually it make sense only on welcome page.<br />
334
- </p>
335
- </div>
336
-
337
- </form>
338
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-activate.inc.php DELETED
@@ -1,152 +0,0 @@
1
- <?php
2
- global $charset_collate;
3
-
4
- require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
5
-
6
- $version = get_option('newsletter_version', 0);
7
-
8
- $sql = "CREATE TABLE `" . $wpdb->prefix . "newsletter` (
9
- `id` int(11) NOT NULL AUTO_INCREMENT,
10
- `name` varchar(100) NOT NULL DEFAULT '',
11
- `surname` varchar(100) NOT NULL DEFAULT '',
12
- `email` varchar(100) NOT NULL DEFAULT '',
13
- `sex` char(1) NOT NULL DEFAULT 'n',
14
- `token` varchar(50) NOT NULL DEFAULT '',
15
- `status` varchar(1) NOT NULL DEFAULT 'S',
16
- `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
17
- `followup_time` bigint(20) NOT NULL DEFAULT '0',
18
- `followup_step` tinyint(4) NOT NULL DEFAULT '0',
19
- `followup` tinyint(4) NOT NULL DEFAULT '0',
20
- `feed` tinyint(4) NOT NULL DEFAULT '0',
21
- `feed_time` bigint(20) NOT NULL DEFAULT '0',
22
- `list_1` tinyint(4) NOT NULL DEFAULT '0',
23
- `list_2` tinyint(4) NOT NULL DEFAULT '0',
24
- `list_3` tinyint(4) NOT NULL DEFAULT '0',
25
- `list_4` tinyint(4) NOT NULL DEFAULT '0',
26
- `list_5` tinyint(4) NOT NULL DEFAULT '0',
27
- `list_6` tinyint(4) NOT NULL DEFAULT '0',
28
- `list_7` tinyint(4) NOT NULL DEFAULT '0',
29
- `list_8` tinyint(4) NOT NULL DEFAULT '0',
30
- `list_9` tinyint(4) NOT NULL DEFAULT '0',
31
- `profile_1` varchar(255) NOT NULL DEFAULT '',
32
- `profile_2` varchar(255) NOT NULL DEFAULT '',
33
- `profile_3` varchar(255) NOT NULL DEFAULT '',
34
- `profile_4` varchar(255) NOT NULL DEFAULT '',
35
- `profile_5` varchar(255) NOT NULL DEFAULT '',
36
- `profile_6` varchar(255) NOT NULL DEFAULT '',
37
- `profile_7` varchar(255) NOT NULL DEFAULT '',
38
- `profile_8` varchar(255) NOT NULL DEFAULT '',
39
- `profile_9` varchar(255) NOT NULL DEFAULT '',
40
- `profile_10` varchar(255) NOT NULL DEFAULT '',
41
- `profile_11` varchar(255) NOT NULL DEFAULT '',
42
- `profile_12` varchar(255) NOT NULL DEFAULT '',
43
- `profile_13` varchar(255) NOT NULL DEFAULT '',
44
- `profile_14` varchar(255) NOT NULL DEFAULT '',
45
- `profile_15` varchar(255) NOT NULL DEFAULT '',
46
- `profile_16` varchar(255) NOT NULL DEFAULT '',
47
- `profile_17` varchar(255) NOT NULL DEFAULT '',
48
- `profile_18` varchar(255) NOT NULL DEFAULT '',
49
- `profile_19` varchar(255) NOT NULL DEFAULT '',
50
- `referrer` varchar(50) NOT NULL DEFAULT '',
51
- `ip` varchar(50) NOT NULL DEFAULT '',
52
- `test` tinyint(4) NOT NULL DEFAULT 0,
53
- PRIMARY KEY (`id`),
54
- UNIQUE KEY `email` (`email`)
55
- ) $charset_collate;";
56
-
57
- dbDelta($sql);
58
-
59
- $sql = "alter table " . $wpdb->prefix . "newsletter CONVERT TO CHARACTER SET utf8";
60
- @$wpdb->query($sql);
61
-
62
- $sql = 'drop table if exists ' . $wpdb->prefix . 'newsletter_work';
63
- @$wpdb->query($sql);
64
-
65
-
66
- // NEWSLETTER_PROFILES
67
- $sql = 'create table if not exists ' . $wpdb->prefix . 'newsletter_profiles (
68
- `newsletter_id` int NOT NULL,
69
- `name` varchar (100) NOT NULL DEFAULT \'\',
70
- `value` text,
71
- primary key (newsletter_id, name)
72
- ) DEFAULT charset=utf8';
73
- @$wpdb->query($sql);
74
-
75
- $sql = "alter table " . $wpdb->prefix . "newsletter_profiles CONVERT TO CHARACTER SET utf8";
76
- @$wpdb->query($sql);
77
-
78
- // NEWSLETTER_EMAILS
79
- $sql = "CREATE TABLE " . $wpdb->prefix . "newsletter_emails (
80
- `id` int auto_increment,
81
- `subject` varchar(255) NOT NULL DEFAULT '',
82
- `message` text,
83
- `name` varchar(255) NOT NULL DEFAULT '',
84
- `subject2` varchar(255) NOT NULL DEFAULT '',
85
- `message2` text,
86
- `name2` varchar(255) NOT NULL DEFAULT '',
87
- `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
88
- `status` enum('new','sending','sent','paused') NOT NULL DEFAULT 'new',
89
- `total` int NOT NULL DEFAULT 0,
90
- `last_id` int NOT NULL DEFAULT 0,
91
- `sent` int NOT NULL DEFAULT 0,
92
- `track` int NOT NULL DEFAULT 0,
93
- `list` int NOT NULL DEFAULT 0,
94
- `type` enum('email','feed','followup') NOT NULL DEFAULT 'email',
95
- `query` varchar(255) NOT NULL DEFAULT '',
96
- `editor` tinyint NOT NULL DEFAULT 0,
97
- `sex` char(1) NOT NULL DEFAULT '',
98
- `theme` varchar(50) NOT NULL DEFAULT '',
99
- PRIMARY KEY (id)
100
- ) $charset_collate;";
101
-
102
- dbDelta($sql);
103
-
104
- $sql = "alter table " . $wpdb->prefix . "newsletter_emails CONVERT TO CHARACTER SET utf8";
105
- @$wpdb->query($sql);
106
-
107
- // Load DEFAULT options (language specific)
108
- include dirname(__FILE__) . '/languages/en_US.php';
109
- @include dirname(__FILE__) . '/languages/' . WPLANG . '.php';
110
-
111
- // MAIN OPTIONS
112
- $options = get_option('newsletter_main', array());
113
-
114
- if ($version < 250) {
115
- // Migration of "protect" configuration
116
- if (!isset($options['lock_url'])) {
117
- $protect = get_option('newsletter_protect', array());
118
- $options['lock_message'] = $protect['message'];
119
- $options['lock_url'] = $protect['url'];
120
- delete_option('newsletter_protect');
121
- }
122
- }
123
- if (empty($options['theme'])) $options['theme'] = $defaults_main['theme'];
124
- if (empty($options['sender_email'])) $options['sender_email'] = $defaults_main['sender_email'];
125
-
126
- update_option('newsletter_main', array_merge($defaults_main, $options));
127
-
128
- // SUBSCRIPTION OPTIONS
129
- update_option('newsletter', array_merge($defaults, get_option('newsletter', array())));
130
-
131
- wp_clear_scheduled_hook('newsletter');
132
- wp_schedule_event(time() + 30, 'newsletter', 'newsletter');
133
-
134
- $options = get_option('newsletter_profile', array());
135
- if (empty($options)) {
136
- $lists = get_option('newsletter_lists', array());
137
- for ($i=1; $i<=9; $i++) {
138
- $options['list_' . $i] = $lists['name_' . $i];
139
- $options['list_type_' . $i] = $lists['type_' . $i];
140
- }
141
- }
142
- add_option('newsletter_profile', array(), '', 'no');
143
- update_option('newsletter_profile', array_merge($defaults_profile, array_filter($options)));
144
-
145
- // OLD
146
- delete_option('newsletter_batch');
147
- $sql = "update " . $wpdb->prefix . "options set autoload='no' where option_name like 'newsletter%'";
148
- @$wpdb->query($sql);
149
-
150
- // Update the version number
151
- add_option('newsletter_version', Newsletter::VERSION, '', 'no');
152
- update_option('newsletter_version', Newsletter::VERSION);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-export.inc.php DELETED
@@ -1,83 +0,0 @@
1
- <?php
2
-
3
- header('Content-Type: application/octet-stream');
4
- header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');
5
-
6
- $keys = $wpdb->get_results("select distinct name from " . $wpdb->prefix . "newsletter_profiles order by name");
7
-
8
- // CSV header
9
- echo '"Email";"Name";"Surname";"Sex";Status";"Date";"Token";';
10
-
11
- // In table profiles
12
- for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
13
- echo '"Profile ' . $i . '";'; // To adjust with field name
14
- }
15
-
16
- // Lists
17
- for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
18
- echo '"List ' . $i . '";';
19
- }
20
-
21
- echo '"Feed by mail";"Follow up"';
22
-
23
- // Old profiles
24
- foreach ($keys as $key) {
25
- // Remove some keys?
26
- echo $key->name . ';';
27
- }
28
- echo "\n";
29
-
30
- $page = 0;
31
- while (true) {
32
- $query = "select * from " . $wpdb->prefix . "newsletter";
33
- if (!empty($_POST['options']['list'])) {
34
- $query .= " where list_" . $_POST['options']['list'] . "=1";
35
- }
36
- $recipients = $wpdb->get_results($query . " order by email limit " . $page * 500 . ",500");
37
- for ($i = 0; $i < count($recipients); $i++) {
38
- echo '"' . $recipients[$i]->email . '";"' . newsletter_sanitize_csv($recipients[$i]->name) .
39
- '";"' . newsletter_sanitize_csv($recipients[$i]->surname) .
40
- '";"' . $recipients[$i]->sex .
41
- '";"'. $recipients[$i]->status . '";"' . $recipients[$i]->created . '";"' . $recipients[$i]->token . '";';
42
-
43
- for ($j = 1; $j <= NEWSLETTER_PROFILE_MAX; $j++) {
44
- $column = 'profile_' . $j;
45
- echo newsletter_sanitize_csv($recipients[$i]->$column) . ';';
46
- }
47
-
48
- for ($j = 1; $j <= NEWSLETTER_LIST_MAX; $j++) {
49
- $list = 'list_' . $j;
50
- echo $recipients[$i]->$list . ';';
51
- }
52
-
53
- echo $recipients[$i]->feed . ';';
54
- echo $recipients[$i]->followup . ';';
55
-
56
- $profile = $wpdb->get_results("select name,value from " . $wpdb->prefix . "newsletter_profiles where newsletter_id=" . $recipients[$i]->id . " order by name");
57
- $map = array();
58
- foreach ($profile as $field) {
59
- $map[$field->name] = $field->value;
60
- }
61
-
62
- foreach ($keys as $key) {
63
- if (isset($map[$key->name])) {
64
- echo '"' . newsletter_sanitize_csv($map[$key->name]) . '";';
65
- }
66
- else echo '"";';
67
- }
68
- echo "\n";
69
- flush();
70
- }
71
- if (count($recipients) < 500) break;
72
- $page++;
73
- }
74
- die();
75
-
76
- function newsletter_sanitize_csv($text) {
77
- $text = str_replace('"', "'", $text);
78
- $text = str_replace("\n", ' ', $text);
79
- $text = str_replace("\r", ' ', $text);
80
- $text = str_replace(";", ' ', $text);
81
- return $text;
82
- }
83
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-head.inc.php DELETED
@@ -1,19 +0,0 @@
1
- <?php $options = get_option('newsletter_profile'); ?>
2
- <script type="text/javascript">
3
- //<![CDATA[
4
- function newsletter_check(f) {
5
- var re = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-]{1,})+\.)+([a-zA-Z0-9]{2,})+$/;
6
- if (!re.test(f.elements["ne"].value)) {
7
- alert("<?php echo addslashes($options['email_error']); ?>");
8
- return false;
9
- }
10
- if (f.elements["ny"] && !f.elements["ny"].checked) {
11
- alert("<?php echo addslashes($options['privacy_error']); ?>");
12
- return false;
13
- }
14
- return true;
15
- }
16
- //]]></script>
17
- <style type="text/css">
18
- <?php echo $this->options_main['css']; ?>
19
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin-menu.inc.php CHANGED
@@ -2,18 +2,44 @@
2
 
3
  $level = $this->options_main['editor'] ? 7 : 10;
4
 
5
- add_menu_page('Newsletter', 'Newsletter', $level, 'newsletter/intro.php', '', '');
6
- add_submenu_page('newsletter/intro.php', 'User Guide', 'User Guide', $level, 'newsletter/intro.php');
7
 
8
- add_submenu_page('newsletter/intro.php', 'Main Configuration', 'Main Configuration', $level, 'newsletter/main.php');
9
- add_submenu_page('newsletter/intro.php', 'Subscription Process', 'Subscription Process', $level, 'newsletter/options.php');
10
- add_submenu_page('newsletter/intro.php', 'Subscription Form', 'Subscription Form', $level, 'newsletter/profile.php');
11
 
12
- add_submenu_page('newsletter/intro.php', 'Emails', 'Emails', $level, 'newsletter/emails.php');
13
- add_submenu_page('newsletter/emails.php', 'Email Edit', 'Email Edit', $level, 'newsletter/emails-edit.php');
14
 
15
- add_submenu_page('newsletter/intro.php', 'Subscribers', 'Subscribers', $level, 'newsletter/users.php');
16
- add_submenu_page('newsletter/users.php', 'Subscribers Edit', 'Subscribers Edit', $level, 'newsletter/users-edit.php');
 
 
17
 
18
- add_submenu_page('newsletter/intro.php', 'Import/Export', 'Import/Export', $level, 'newsletter/import.php');
19
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  $level = $this->options_main['editor'] ? 7 : 10;
4
 
5
+ add_menu_page('Newsletter', 'Newsletter', $level, 'newsletter/welcome.php', '', '');
6
+ //add_submenu_page('newsletter/welcome.php', 'User Guide', 'User Guide', $level, 'newsletter/main.php');
7
 
8
+ add_submenu_page('newsletter/welcome.php', 'Welcome & Support', 'Welcome & Support', $level, 'newsletter/welcome.php');
 
 
9
 
10
+ add_submenu_page('newsletter/welcome.php', 'Configuration', 'Configuration', $level, 'newsletter/main.php');
 
11
 
12
+ add_submenu_page('newsletter/welcome.php', 'Subscription', 'Subscription', $level, 'newsletter/subscription/options.php');
13
+ add_submenu_page(null, 'Subscription Form', 'Subscription Form', $level, 'newsletter/subscription/profile.php');
14
+ add_submenu_page('newsletter/subscription/options.php', 'Forms', 'Forms', $level, 'newsletter/subscription/forms.php');
15
+ add_submenu_page('newsletter/subscription/options.php', 'Forms', 'Forms', $level, 'newsletter/subscription/form-code.php');
16
 
17
+ add_submenu_page('newsletter/welcome.php', 'Newsletters', 'Newsletters', $level, 'newsletter/emails/index.php');
18
+ add_submenu_page(null, 'Email Edit', 'Email Edit', $level, 'newsletter/emails/old-emails.php');
19
+ add_submenu_page(null, 'Email Edit', 'Email Edit', $level, 'newsletter/emails/old-edit.php');
20
+
21
+ add_submenu_page(null, 'Email List', 'Email List', $level, 'newsletter/emails/list.php');
22
+ add_submenu_page(null, 'Email New', 'Email New', $level, 'newsletter/emails/new.php');
23
+ add_submenu_page(null, 'Email Edit', 'Email Edit', $level, 'newsletter/emails/edit.php');
24
+ add_submenu_page(null, 'Email Theme', 'Email Theme', $level, 'newsletter/emails/theme.php');
25
+
26
+ add_submenu_page(null, 'Email statistics', 'Email statistics', $level, 'newsletter/statistics/statistics-email.php');
27
+
28
+ add_submenu_page('newsletter/welcome.php', 'Subscribers', 'Subscribers', $level, 'newsletter/users/index.php');
29
+ add_submenu_page('newsletter/users/index.php', 'New subscriber', 'New subscriber', $level, 'newsletter/users/new.php');
30
+ add_submenu_page('newsletter/users/index.php', 'Subscribers Edit', 'Subscribers Edit', $level, 'newsletter/users/edit.php');
31
+ add_submenu_page('newsletter/users/index.php', 'Subscribers Statistics', 'Subscribers Statistics', $level, 'newsletter/users/stats.php');
32
+ add_submenu_page('newsletter/users/index.php', 'Massive Management', 'Massive Management', $level, 'newsletter/users/massive.php');
33
+ add_submenu_page('newsletter/users/index.php', 'Import', 'Import', $level, 'newsletter/users/import.php');
34
+ add_submenu_page('newsletter/users/index.php', 'Export', 'Export', $level, 'newsletter/users/export.php');
35
+
36
+ // Statistics
37
+ //add_submenu_page('newsletter/welcome.php', 'Statistics', 'Statistics', $level, 'newsletter/statistics/statistics-index.php');
38
+ //add_submenu_page('newsletter/statistics/statistics-index.php', 'Statistics', 'Statistics', $level, 'newsletter/statistics/statistics-view.php');
39
+
40
+ // Updates
41
+ //add_submenu_page('newsletter/welcome.php', 'Updates', 'Updates', $level, 'newsletter/updates/updates-index.php');
42
+ //add_submenu_page('newsletter/updates/updates-index.php', 'Updates', 'Updates', $level, 'newsletter/updates/updates-edit.php');
43
+ //add_submenu_page('newsletter/updates/updates-index.php', 'Updates', 'Updates', $level, 'newsletter/updates/updates-emails.php');
44
+
45
+ ?>
plugin.php CHANGED
@@ -1,193 +1,398 @@
1
  <?php
 
2
  /*
3
  Plugin Name: Newsletter
4
  Plugin URI: http://www.satollo.net/plugins/newsletter
5
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="http://www.satollo.net/plugins/newsletter#update">this page</a> to know what's changed.</strong>
6
- Version: 2.5.2.7
7
- Author: Satollo
8
  Author URI: http://www.satollo.net
9
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
10
 
11
- Copyright 2011 Stefano Lissa (email: stefano@satollo.net, web: http://www.satollo.net)
12
  */
13
 
14
- define('NEWSLETTER_LIST_MAX', 9);
15
- define('NEWSLETTER_PROFILE_MAX', 19);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- global $newsletter;
18
- $newsletter = new Newsletter();
19
 
20
- class Newsletter {
21
- const VERSION = 250;
 
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  var $time_limit;
24
- var $email_limit = 10; // Per run
25
- var $relink_email_id;
26
- var $relink_user_id;
 
 
 
 
27
  var $mailer;
28
- var $options_main;
29
  var $message;
30
  var $user;
31
  var $error;
 
 
 
 
 
 
 
32
 
33
- function Newsletter() {
34
- global $wpdb;
 
 
 
 
 
 
 
35
 
 
36
  // Early possible
37
  $max_time = (int) (@ini_get('max_execution_time') * 0.9);
38
  if ($max_time == 0) $max_time = 600;
39
  $this->time_limit = time() + $max_time;
40
 
41
- register_activation_hook(__FILE__, array(&$this, 'hook_activate'));
42
- register_deactivation_hook(__FILE__, array(&$this, 'hook_deactivate'));
43
 
44
- add_action('init', array(&$this, 'hook_init'));
45
- add_action('admin_init', array(&$this, 'hook_admin_init'));
46
- add_action('mailer_bounce_email', array(&$this, 'mailer_bounce_email'));
47
 
48
- add_filter('cron_schedules', array(&$this, 'hook_cron_schedules'), 1000);
 
 
 
 
49
  add_action('newsletter', array(&$this, 'hook_newsletter'), 1);
50
 
51
  // This specific event is created by "Feed by mail" panel on configuration
52
- add_action('template_redirect', array(&$this, 'hook_template_redirect'));
 
 
 
 
 
 
 
 
 
53
  add_action('wp_head', array(&$this, 'hook_wp_head'));
54
- add_shortcode('newsletter', array(&$this, 'shortcode_newsletter'));
55
  add_shortcode('newsletter_lock', array(&$this, 'shortcode_newsletter_lock'));
56
- add_shortcode('newsletter_form', array(&$this, 'shortcode_newsletter_form'));
57
- add_shortcode('newsletter_embed', array(&$this, 'shortcode_newsletter_form'));
58
- add_action('shutdown', array(&$this, 'hook_shutdown'));
59
- if (is_admin ()) {
60
  add_action('admin_menu', array(&$this, 'hook_admin_menu'));
61
  add_action('admin_head', array(&$this, 'hook_admin_head'));
62
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
- $this->options_main = get_option('newsletter_main', array());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
66
 
67
  function hook_admin_head() {
68
- if (strpos($_GET['page'], 'newsletter/') === 0) {
69
- echo '<link type="text/css" rel="stylesheet" href="' .
70
- get_option('siteurl') . '/wp-content/plugins/newsletter/style.css"/>';
71
  }
72
  }
73
 
74
  function hook_admin_menu() {
75
  include 'plugin-menu.inc.php';
 
 
 
 
 
76
  }
77
 
78
  function hook_wp_head() {
79
- include 'plugin-head.inc.php';
80
- }
 
 
 
81
 
82
- function hook_newsletter_feed() {
 
 
 
 
83
  }
84
 
85
- function check_transient($name, $time) {
86
- usleep(rand(0, 1000000));
87
- if (get_transient($name) !== false) {
88
- $this->log('Called too quickly');
89
- return false;
90
- }
91
- set_transient($name, 1, $time);
92
- return true;
93
  }
94
 
 
 
 
95
  function hook_newsletter() {
96
  global $wpdb;
97
 
98
- //$this->log();
99
- if (!$this->check_transient('newsletter', 60)) return;
100
 
101
- $max = $this->options_main['scheduler_max'];
102
- if (!is_numeric($max)) $max = 100;
103
- $this->email_limit = max(floor($max / 12), 1);
104
-
105
- $this->set_limits();
106
 
107
  // Retrieve all email in "sending" status
108
- $emails = $wpdb->get_results("select * from " . $wpdb->prefix . "newsletter_emails where status='sending' order by id desc");
109
- foreach ($emails as $email) {
 
 
110
  if (!$this->send($email)) return;
111
  }
 
 
 
 
 
 
112
  }
113
 
 
 
 
 
 
 
 
 
 
 
114
  function send($email, $users = null) {
115
  global $wpdb;
116
 
117
- $this->log();
118
 
119
- if ($this->limits_exceeded()) return false;
 
120
 
121
  if ($users == null) {
122
- // Fake value representing the WordPress users target
123
- if ($email->list == -1) {
124
- if (!empty($email->query)) $query = "select * from " . $wpdb->prefix . "users " . $email->query . " and id>" . $email->last_id . " order by id limit " . $this->email_limit;
125
- else $query = "select * from " . $wpdb->prefix . "users where id>" . $email->last_id . " order by id limit " . $this->email_limit;
126
- $this->log($query, 3);
127
- $wp_users = $wpdb->get_results($query);
128
- $users = array();
129
- foreach ($wp_users as &$wp_user) {
130
- $user = new stdClass();
131
- $user->email = $wp_user->user_email;
132
- $user->name = $wp_user->user_login;
133
- $user->id = -$wp_user->ID;
134
- $users[] = $user;
135
- }
136
  }
137
- else {
138
- if (!empty($email->query)) $query = "select * from " . $wpdb->prefix . "newsletter " . $email->query;
139
- else {
140
- $query = "select * from " . $wpdb->prefix . "newsletter where status='C'";
141
- if ($email->list != 0) $query .= " and list_" . $email->list . "=1";
142
- if (!empty($email->sex)) $query .= " and sex='" . $email->sex . "'";
143
- }
144
- $query .= " and id>" . $email->last_id . " order by id limit " . $this->email_limit;
145
- $this->log($query, 3);
146
- $users = $wpdb->get_results($query);
147
  }
148
  }
149
 
150
- if (empty($users)) {
151
- $this->log('No more users');
152
- $wpdb->query("update " . $wpdb->prefix . "newsletter_emails set status='sent' where id=" . $email->id);
153
- return;
154
- }
155
 
156
- foreach ($users as $user) {
157
- $headers = array('List-Unsubscribe' => '<' .
158
- $this->add_qs($this->options_main['url'], 'na=u&ni=' . $user->id . '&nt=' . $user->token) . '>');
159
 
160
- $m = $this->execute($email->message, $user);
161
- if (empty($m)) continue;
162
- $m = $this->replace($m, $user);
163
 
164
- if ($email->track == 1) $m = $this->relink($m, $email->id, $user->id);
 
 
165
 
166
- // Add CSS
167
- if ($email->theme[0] == '*') $file = 'newsletter-custom/themes/' . substr($email->theme, 1) . '/style.css';
168
- else $file = 'newsletter/themes/' . $email->theme . '/style.css';
169
- $css = @file_get_contents(ABSPATH . 'wp-content/plugins/' . $file);
170
 
171
- $m = '<html><head><style type="text/css">' . $css .
172
- '</style></head><body>' . $m . '</body></html>';
173
 
174
  $s = $this->replace($email->subject, $user);
175
- $x = $this->mail($user->email, $s, $m, true, $headers, 2);
176
 
177
- $wpdb->query("update " . $wpdb->prefix . "newsletter_emails set sent=sent+1, last_id=" . abs($user->id) . " where id=" . $email->id);
 
178
  $this->email_limit--;
179
- if ($this->limits_exceeded()) return false;
180
  }
181
- return true;
182
- }
183
 
184
- function feed_send($email, $users = null) {
185
- }
 
 
 
186
 
187
- function followup_send($users = null, $options=null) {
188
  }
189
 
190
- function execute($text, $user=null) {
191
  global $wpdb;
192
  ob_start();
193
  $r = eval('?' . '>' . $text);
@@ -202,95 +407,140 @@ class Newsletter {
202
  }
203
 
204
  /**
205
- * Return true if the execution timeout is reached or the maximum number of email
206
- * has been sent.
207
  */
208
  function limits_exceeded() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  if (time() > $this->time_limit) {
210
- $this->log('Timeout', 2);
211
  return true;
212
  }
213
- if ($this->email_limit < 0) {
214
- $this->log('Email limit reached', 3);
 
215
  return true;
216
  }
217
  return false;
218
  }
219
 
220
- function mail($to, $subject, $message, $html=true, $headers=null, $priority=0) {
 
 
 
 
 
 
 
 
221
 
222
- $this->log('To: ' . $to, 3);
223
- $this->log('Subject: ' . $subject, 3);
224
  if (empty($subject)) {
225
- $this->log('Subject empty, skipped', 3);
226
  return true;
227
  }
228
 
229
- if (!empty($this->options_main['receiver'])) $to = $this->options_main['receiver'];
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
- $h = '';
233
- if (!empty($headers)) {
234
- foreach ($headers as $key => $value)
235
- $h .= $key . ': ' . $value . "\n";
236
  }
 
237
 
238
- $h .= "From: " . $this->options_main['sender_name'] . " <" . $this->options_main['sender_email'] . ">\n";
239
 
240
- if (!empty($this->options_main['reply_to'])) {
241
- $h .= "Reply-To: " . $this->options_main['reply_to'] . "\n";
 
 
242
  }
243
- if (!empty($this->options_main['return_path'])) {
244
- $h .= "Return-Path: " . $this->options_main['return_path'] . "\n";
245
- }
246
- $h .= "X-MailerPriority: " . $priority . "\n";
247
- $h .= "X-MailerGroup: newsletter\n";
248
- $h .= "MIME-Version: 1.0\n";
249
- if ($html) $h .= "Content-type: text/html; charset=UTF-8\n";
250
- else $h .= "Content-type: text/plain; charset=UTF-8\n";
251
- $this->log('Headers: ' . $h, 3);
252
- $r = wp_mail($to, $subject, $message, $h);
253
- $this->log($r ? 'Mail sent' : 'Mail sending failed', 1);
254
- return $r;
255
- }
256
 
257
- function mailer_init() {
258
- }
 
259
 
260
- function relink($text, $email_id, $user_id) {
261
- return $text;
 
 
 
 
 
 
262
  }
263
 
264
- function relink_callback($matches) {
265
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
- /**
268
- * Levels are: 1 for errors, 2 for normal activity, 3 for debug.
269
- */
270
- function log($text='', $level=2) {
271
- if ((int) $this->options_main['logs'] < $level) return;
272
 
273
- //$db = debug_backtrace(false);
274
- $time = date('d-m-Y H:i:s ');
275
- switch ($level) {
276
- case 1: $time .= '- ERROR';
277
- break;
278
- case 2: $time .= '- INFO ';
279
- break;
280
- case 3: $time .= '- DEBUG';
281
- break;
282
- }
283
- if (is_array($text) || is_object($text)) $text = print_r($text, true);
284
- file_put_contents(dirname(__FILE__) . '/log.txt', $time . ' - ' . $text . "\n", FILE_APPEND | FILE_TEXT);
285
- }
286
 
287
- function hook_activate() {
288
- global $wpdb;
289
- include 'plugin-activate.inc.php';
290
  }
291
 
292
  function hook_deactivate() {
293
  wp_clear_scheduled_hook('newsletter');
 
294
  }
295
 
296
  function hook_cron_schedules($schedules) {
@@ -301,416 +551,134 @@ class Newsletter {
301
  return $schedules;
302
  }
303
 
304
- /**
305
- * Generate the profile editing form.
306
- */
307
- function profile_form($user) {
308
- $options = get_option('newsletter_profile');
309
-
310
- $buffer .= '<div class="newsletter newsletter-profile">';
311
- $buffer .= '<form action="' . $this->options_main['url'] . '" method="post"><input type="hidden" name="na" value="ps"/>';
312
- $buffer .= '<input type="hidden" name="ni" value="' . $user->id . '"/>';
313
- $buffer .= '<input type="hidden" name="nt" value="' . $user->token . '"/>';
314
- $buffer .= '<table>';
315
- $buffer .= '<tr><th align="right">' . $options['email'] . '</th><td><input type="text" size="30" name="ne" value="' . htmlspecialchars($user->email) . '"/></td></tr>';
316
- if ($options['name_status'] >= 1) {
317
- $buffer .= '<tr><th align="right">' . $options['name'] . '</th><td><input type="text" size="30" name="nn" value="' . htmlspecialchars($user->name) . '"/></td></tr>';
318
- }
319
- if ($options['surname_status'] >= 1) {
320
- $buffer .= '<tr><th align="right">' . $options['surname'] . '</th><td><input type="text" size="30" name="ns" value="' . htmlspecialchars($user->surname) . '"/></td></tr>';
321
- }
322
- if ($options['sex_status'] >= 1) {
323
- $buffer .= '<tr><th align="right">' . $options['sex'] . '</th><td><select name="nx" class="newsletter-sex">';
324
- // if (!empty($options['sex_none'])) {
325
- // $buffer .= '<option value="n"' . ($user->sex == 'n' ? ' selected' : '') . '>' . $options['sex_none'] . '</option>';
326
- // }
327
- $buffer .= '<option value="f"' . ($user->sex == 'f' ? ' selected' : '') . '>' . $options['sex_female'] . '</option>';
328
- $buffer .= '<option value="m"' . ($user->sex == 'm' ? ' selected' : '') . '>' . $options['sex_male'] . '</option>';
329
- $buffer .= '</select></td></tr>';
330
- }
331
-
332
- // Profile
333
- for ($i = 1; $i <= 19; $i++) {
334
- if ($options['profile_' . $i . '_status'] == 0) continue;
335
-
336
- $buffer .= '<tr><th align="right">' . $options['profile_' . $i] . '</th><td>';
337
- //if ($options['list_type_' . $i] != 'public') continue;
338
- $field = 'profile_' . $i;
339
-
340
- if ($options['profile_' . $i . '_type'] == 'text') {
341
- $buffer .= '<input type="text" size="40" name="np' . $i . '" value="' . htmlspecialchars($user->$field) . '"/>';
342
- }
343
- if ($options['profile_' . $i . '_type'] == 'select') {
344
- $buffer .= '<select name="np' . $i . '">';
345
- $opts = explode(',', $options['profile_' . $i . '_options']);
346
- for ($j = 0; $j < count($opts); $j++) {
347
- $opts[$j] = trim($opts[$j]);
348
- $buffer .= '<option';
349
- if ($opts[$j] == $user->$field) $buffer .= ' selected';
350
- $buffer .= '>' . $opts[$j] . '</option>';
351
- }
352
- $buffer .= '</select>';
353
- }
354
-
355
- $buffer .= '</td></tr>';
356
- }
357
-
358
- // Lists
359
- $buffer .= '<tr><th>&nbsp;</th><td>';
360
- for ($i = 1; $i <= 9; $i++) {
361
- if ($options['list_' . $i . '_status'] == 0) continue;
362
- $buffer .= '<input type="checkbox" name="nl[]" value="' . $i . '"';
363
- $list = 'list_' . $i;
364
- if ($user->$list == 1) $buffer .= ' checked';
365
- $buffer .= '/> ' . htmlspecialchars($options['list_' . $i]) . '<br />';
366
- }
367
- $buffer .= '</td></tr>';
368
-
369
- $buffer .= '<tr><td colspan="2" align="center"><input type="submit" value="' . $options['save'] . '"/></td></tr>';
370
- $buffer .= '</table></form></div>';
371
-
372
- return $buffer;
373
- }
374
-
375
- function subscription_form() {
376
- $options_profile = get_option('newsletter_profile');
377
- $options = get_option('newsletter');
378
- $buffer = '<div class="newsletter newsletter-subscription"><form method="post" action="' . $this->options_main['url'] . '" onsubmit="return newsletter_check(this)"><input type="hidden" name="na" value="s"/>';
379
- $buffer .= '<table>';
380
- if ($options_profile['name_status'] == 2) {
381
- $buffer .= '<tr><th>' . $options_profile['name'] . '</th><td><input type="text" name="nn" size="30"/></td></tr>';
382
- }
383
- if ($options_profile['surname_status'] == 2) {
384
- $buffer .= '<tr><th>' . $options_profile['surname'] . '</th><td><input type="text" name="ns" size="30"/></td></tr>';
385
- }
386
-
387
- $buffer .= '<tr><th>' . $options_profile['email'] . '</th><td align="left"><input type="text" name="ne" size="30"/></td></tr>';
388
-
389
- if ($options_profile['sex_status'] == 2) {
390
- $buffer .= '<tr><th>' . $options_profile['sex'] . '</th><td><select name="nx" class="newsletter-sex">';
391
- $buffer .= '<option value="m">' . $options_profile['sex_male'] . '</option>';
392
- $buffer .= '<option value="f">' . $options_profile['sex_female'] . '</option>';
393
- $buffer .= '</select></td></tr>';
394
- }
395
- $lists = '';
396
- for ($i = 1; $i <= 9; $i++) {
397
- if ($options_profile['list_' . $i . '_status'] != 2) continue;
398
- $lists .= '<input type="checkbox" name="nl[]" value="' . $i . '"/>&nbsp;' . $options_profile['list_' . $i] . '<br />';
399
- }
400
- if (!empty($lists)) $buffer .= '<tr><th>&nbsp;</th><td>' . $lists . '</td></tr>';
401
-
402
- // Extra profile fields
403
- for ($i = 1; $i <= 19; $i++) {
404
- if ($options_profile['profile_' . $i . '_status'] != 2) continue;
405
- if ($options_profile['profile_' . $i . '_type'] == 'text') {
406
- $buffer .= '<tr><th>' . $options_profile['profile_' . $i] . '</th><td><input type="text" size="30" name="np' . $i . '"/></td></tr>';
407
- }
408
- if ($options_profile['profile_' . $i . '_type'] == 'select') {
409
- $buffer .= '<tr><th>' . $options_profile['profile_' . $i] . '</th><td><select name="np' . $i . '">';
410
- $opts = explode(',', $options_profile['profile_' . $i . '_options']);
411
- for ($j = 0; $j < count($opts); $j++) {
412
- $buffer .= '<option>' . trim($opts[$j]) . '</option>';
413
- }
414
- $buffer .= '</select></td></tr>';
415
- }
416
- }
417
-
418
- $buffer .= '<tr><td colspan="2" style="text-align: center">';
419
- if ($options_profile['privacy_status'] == 1) {
420
- $buffer .= '<input type="checkbox" name="ny"/>&nbsp;' . $options_profile['privacy'] . '<br />';
421
- }
422
- if (strpos($options_profile['subscribe'], 'http://') !== false) {
423
- $buffer .= '<input type="image" src="' . $options_profile['subscribe'] . '"/></td></tr>';
424
- } else {
425
- $buffer .= '<input type="submit" value="' . $options_profile['subscribe'] . '"/></td></tr>';
426
- }
427
- $buffer .= '</table></form></div>';
428
- return $buffer;
429
- }
430
-
431
- function mailer_bounce_email($email) {
432
- }
433
-
434
- function hook_template_redirect() {
435
- if (!empty($this->message) && empty($this->options_main['url'])) {
436
- if ($this->options_main['theme'][0] == '*') $file = ABSPATH . 'wp-content/plugins/newsletter-custom/themes-page/' . substr($this->options_main['theme'], 1) . '/theme.php';
437
- else $file = dirname(__FILE__) . '/themes-page/' . $this->options_main['theme'] . '/theme.php';
438
-
439
- // Include the labels, language dependend
440
- @include(dirname($file) . '/en_US.php');
441
- if (defined('WPLANG') && WPLANG != '') @include(dirname($file) . '/' . WPLANG . '.php');
442
-
443
- ob_start();
444
- @include($file);
445
- $m = ob_get_contents();
446
- ob_end_clean();
447
-
448
- echo $this->execute(str_replace('{message}', $this->message, $m));
449
- die();
450
- }
451
- }
452
-
453
- function shortcode_newsletter() {
454
- if (!empty($this->message)) return $this->message;
455
-
456
- $options = get_option('newsletter');
457
- // If there is an "embedded" form, adjust it and ignore the standard subscription form
458
- if (stripos($options['subscription_text'], '<form') !== false) {
459
- $buffer = str_ireplace('<form', '<form method="post" action="' . $this->options_main['url'] . '" onsubmit="return newsletter_check(this)"', $options['subscription_text']);
460
- return str_ireplace('</form>', '<input type="hidden" name="na" value="s"/></form>', $buffer);
461
- }
462
-
463
- if (strpos($buffer, '{subscription_form}') !== false) return str_replace('{subscription_form}', $this->subscription_form(), $options['subscription_text']);
464
- else return $options['subscription_text'] . $this->subscription_form();
465
-
466
- return $buffer;
467
- }
468
-
469
  function shortcode_newsletter_form($attrs, $content) {
470
  return $this->form($attrs['form']);
471
  }
472
 
473
- function form($number=null) {
474
  if ($number == null) return $this->subscription_form();
475
  $options = get_option('newsletter_forms');
476
- $options_profile = get_option('newsletter_profile');
477
 
478
- $form = str_replace('{newsletter_url}', $this->options_main['url'], $options['form_' . $number]);
479
 
480
- $lists = '';
481
- for ($i = 1; $i <= 9; $i++) {
482
- if ($options_profile['list_' . $i . '_status'] != 2) continue;
483
- $lists .= '<input type="checkbox" name="nl[]" value="' . $i . '"/>&nbsp;' . $options_profile['list_' . $i] . '<br />';
 
484
  }
485
- $form = str_replace('{lists}', $lists, $form);
486
- return $form;
487
- }
488
 
489
- function hook_init() {
490
- global $cache_stop, $hyper_cache_stop, $wpdb;
491
 
492
- $action = $_REQUEST['na'];
493
- if (empty($action) || is_admin()) return;
494
-
495
- $hyper_cache_stop = true;
496
- $cache_stop = true;
497
-
498
- $this->log($action);
499
-
500
- $options = get_option('newsletter', array()); // Subscription options, emails and texts
501
-
502
- // Subscription request from a subscription form (in page or widget), can be
503
- // a direct subscription with no confirmation
504
- if ($action == 's') {
505
- $email = $this->normalize_email(stripslashes($_REQUEST['ne']));
506
- if ($email == null) die('Wrong email');
507
- $user = $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix . "newsletter where email=%s", $email));
508
- if ($user == null) {
509
- $this->log("not found");
510
- $user = array('email' => $email);
511
-
512
- $user['name'] = $this->normalize_name(stripslashes($_REQUEST['nn']));
513
- $user['surname'] = $this->normalize_name(stripslashes($_REQUEST['ns']));
514
- if (!empty($_REQUEST['nx'])) $user['sex'] = $_REQUEST['nx'][0];
515
- $user['referrer'] = $_REQUEST['nr'];
516
-
517
- $options_profile = get_option('newsletter_profile');
518
-
519
- // New profiles
520
- for ($i = 1; $i <= 19; $i++) {
521
- if ($options_profile['profile_' . $i . '_status'] == 0) continue;
522
- $user['profile_' . $i] = trim(stripslashes($_REQUEST['np' . $i]));
523
- }
524
-
525
- // Lists (field names are nl[] and values the list number so special forms with radio button can work)
526
- if (is_array($_REQUEST['nl'])) {
527
- for ($i = 1; $i <= 9; $i++) {
528
- if ($options_profile['list_' . $i . '_status'] != 2) continue;
529
- if (in_array($i, $_REQUEST['nl'])) $user['list_' . $i] = 1;
530
- }
531
- }
532
-
533
- $user['token'] = md5(rand());
534
- $user['ip'] = $_SERVER['REMOTE_ADDR'];
535
- $user['status'] = $options['noconfirmation'] == 1 ? 'C' : 'S';
536
-
537
- $wpdb->insert($wpdb->prefix . 'newsletter', $user);
538
- $user = $this->get_user($wpdb->insert_id); // back to an object
539
- // Notification to admin (only for new subscriptions)
540
- if ($user->status == 'C') {
541
- $this->notify_admin($user, 'Newsletter subscription');
542
- }
543
- }
544
-
545
- $this->log($user);
546
-
547
- $prefix = ($user->status == 'C') ? 'confirmed_' : 'confirmation_';
548
- $message = $options[$prefix . 'message'];
549
- $subject = $options[$prefix . 'subject'];
550
-
551
- //setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
552
-
553
- $this->mail($user->email, $this->replace($subject, $user), $this->replace($message, $user));
554
-
555
- if ($user->status == 'C') {
556
- if (!empty($options['confirmed_url'])) {
557
- header('Location: ' . $options['confirmed_url']);
558
- die();
559
- }
560
- $this->message = $this->replace($options['confirmed_text'], $user);
561
- }
562
- else $this->message = $this->replace($options['subscribed_text'], $user);
563
-
564
- return;
565
- }
566
-
567
- // Actions below need a user. This code loads the user checking parameter or cookies.
568
- $user = $this->check_user();
569
- if ($user == null) die('No user');
570
 
571
- if ($action == 'c') {
572
- setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
 
 
573
 
574
- if (!empty($options['confirmed_url'])) {
575
- header('Location: ' . $options['confirmed_url']);
576
- die();
577
- }
578
- $this->message = $this->replace($options['confirmed_text'], $user);
579
- return;
 
 
 
 
 
 
 
580
  }
581
 
582
- // Unsubscription request
583
- if ($action == 'u') {
584
- $this->message = $this->replace($options['unsubscription_text'], $user);
585
- return;
586
  }
587
 
588
- // Unsubscription confirm
589
- if ($action == 'uc') {
590
- setcookie("newsletter", "", time() - 3600);
591
- $this->message = $this->replace($options['unsubscribed_text'], $user);
592
- return;
593
  }
594
 
595
- // Profile saving
596
- if ($action == 'ps') {
597
- $options_profile = get_option('newsletter_profile', array());
598
- // Javascript checked
599
- if (!$this->is_email($_REQUEST['ne'])) die('Wrong email address.');
600
-
601
- // General data
602
- $data['email'] = $this->normalize_email(stripslashes($_REQUEST['ne']));
603
- $data['name'] = $this->normalize_name(stripslashes($_REQUEST['nn']));
604
- $data['surname'] = $this->normalize_name(stripslashes($_REQUEST['ns']));
605
- if ($options_profile['sex_status'] >= 1) {
606
- $data['sex'] = $_REQUEST['nx'][0];
607
- // Wrong data injection check
608
- if ($data['sex'] != 'm' && $data['sex'] != 'f') die('Wrong sex field');
609
- }
610
-
611
- // Lists
612
- if (is_array($_REQUEST['nl'])) {
613
- for ($i = 1; $i <= 9; $i++) {
614
- if ($options_profile['list_' . $i . '_status'] == 0) continue;
615
- $data['list_' . $i] = in_array($i, $_REQUEST['nl']) ? 1 : 0;
616
- }
617
- }
618
-
619
- // Profile
620
- for ($i = 1; $i <= 19; $i++) {
621
- if ($options_profile['profile_' . $i . '_status'] == 0) continue;
622
- $data['profile_' . $i] = stripslashes($_REQUEST['np' . $i]);
623
  }
624
-
625
- $wpdb->update($wpdb->prefix . 'newsletter', $data, array('id' => $user->id));
626
- $url = empty($this->options_main['url']) ? get_option('home') : $this->options_main['url'];
627
- $url = $this->add_qs($url, 'na=pe&ni=' . $user->id . '&nt=' . $user->token, false);
628
- header('Location: ' . $url);
629
- die();
630
- }
631
-
632
- // Profile editing.
633
- if ($action == 'pe') {
634
- $options_profile = get_option('newsletter_profile');
635
- if (empty($options_profile['profile_text'])) $options_profile['profile_text'] = '{profile_form}';
636
- $this->message = $this->replace($options_profile['profile_text'], $user);
637
- return;
638
- }
639
-
640
- if ($action == 'm') {
641
- if ($user->status == 'C') setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
642
- header('Location: ' . $this->options_main['lock_url']);
643
- die();
644
  }
645
- }
646
 
647
- function set_limits() {
648
- global $wpdb;
649
-
650
- $wpdb->query("set session wait_timeout=300");
651
- // From default-constants.php
652
- if (function_exists('memory_get_usage') && ( (int) @ini_get('memory_limit') < 128 )) @ini_set('memory_limit', '128M');
653
  }
654
 
655
- function hook_admin_init() {
656
- global $wpdb;
657
- if ($_REQUEST['act'] == 'export' && check_admin_referer()) {
658
- include 'plugin-export.inc.php';
 
 
 
 
659
  }
660
- }
661
-
662
- /**
663
- * Return a user if there are request parameters or cookie with identification data otherwise null.
664
- */
665
- function check_user() {
666
- global $wpdb;
667
-
668
- $id = (int) $_REQUEST['ni'];
669
- $token = $_REQUEST['nt'];
670
- if (empty($id) || empty($token)) list ($id, $token) = @explode('-', $_COOKIE['newsletter'], 2);
671
-
672
- return $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix . "newsletter where id=%d and token=%s", $id, $token));
673
- }
674
-
675
- function get_user($id) {
676
- global $wpdb;
677
- return $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix . "newsletter where id=%d", $id));
678
  }
679
 
680
  /**
681
  * Replace any kind of newsletter placeholder in a text.
682
  */
683
- function replace($text, $user=null) {
684
  global $wpdb;
685
 
686
- if (is_array($user)) $user = $this->get_user($user['id']);
687
  $text = str_replace('{home_url}', get_option('home'), $text);
688
  $text = str_replace('{blog_title}', get_option('blogname'), $text);
689
- $text = str_replace('{date}', date_i18n(get_option('date_format')), $text);
690
  $text = str_replace('{blog_description}', get_option('blogdescription'), $text);
 
691
 
692
- // Date processing
693
- $x = 0;
694
- while (($x = strpos($text, '{date_', $x)) !== false) {
695
- $y = strpos($text, '}', $x);
696
- if ($y === false) continue;
697
- $f = substr($text, $x+6, $y-$x-6);
698
- $text = substr($text, 0, $x) . date($f) . substr($text, $y+1);
699
- }
700
 
701
  if ($user != null) {
702
  $text = str_replace('{email}', $user->email, $text);
703
- $text = str_replace('{name}', $user->name, $text);
 
 
 
 
 
704
  $text = str_replace('{surname}', $user->surname, $text);
705
  $text = str_replace('{token}', $user->token, $text);
706
  $text = str_replace('%7Btoken%7D', $user->token, $text);
707
  $text = str_replace('{id}', $user->id, $text);
708
  $text = str_replace('%7Bid%7D', $user->id, $text);
709
  $text = str_replace('{ip}', $user->ip, $text);
 
 
710
 
711
- if (strpos($text, '{profile_form}') !== false) $text = str_replace('{profile_form}', $this->profile_form($user), $text);
 
712
 
713
- for ($i = 1; $i < 20; $i++) {
714
  $p = 'profile_' . $i;
715
  $text = str_replace('{profile_' . $i . '}', $user->$p, $text);
716
  }
@@ -722,20 +690,38 @@ class Newsletter {
722
 
723
  $text = preg_replace('/\\{np_.+\}/i', '', $text);
724
 
725
- $base = $this->options_main['url'];
726
- if ($base == '') $base = get_option('home');
727
  $id_token = '&amp;ni=' . $user->id . '&amp;nt=' . $user->token;
 
728
 
729
- $text = $this->replace_url($text, 'SUBSCRIPTION_CONFIRM_URL', $this->add_qs(plugins_url('do.php', __FILE__), 'a=c' . $id_token));
730
- $text = $this->replace_url($text, 'UNSUBSCRIPTION_CONFIRM_URL', $this->add_qs(plugins_url('do.php', __FILE__), 'a=uc' . $id_token));
 
 
 
 
731
 
732
- $text = $this->replace_url($text, 'UNSUBSCRIPTION_URL', $this->add_qs($base, 'na=u' . $id_token));
733
- $text = $this->replace_url($text, 'PROFILE_URL', $this->add_qs($base, 'na=pe' . $id_token));
734
- $text = $this->replace_url($text, 'UNLOCK_URL', $this->add_qs($this->options_main['url'], 'na=m' . $id_token));
 
 
735
 
736
- for ($i = 1; $i <= 9; $i++) {
737
- $text = $this->replace_url($text, 'LIST_' . $i . '_SUBSCRIPTION_URL', $this->add_qs($base, 'na=ls&amp;nl=' . $i . $id_token));
738
- $text = $this->replace_url($text, 'LIST_' . $i . '_UNSUBSCRIPTION_URL', $this->add_qs($base, 'na=lu&amp;nl=' . $i . $id_token));
 
 
 
 
 
 
 
 
 
 
 
 
739
  }
740
  }
741
  return $text;
@@ -747,6 +733,7 @@ class Newsletter {
747
  $text = str_replace($home . '{' . $tag_lower . '}', $url, $text);
748
  $text = str_replace($home . '%7B' . $tag_lower . '%7D', $url, $text);
749
  $text = str_replace('{' . $tag_lower . '}', $url, $text);
 
750
 
751
  // for compatibility
752
  $text = str_replace($home . $tag, $url, $text);
@@ -754,26 +741,15 @@ class Newsletter {
754
  return $text;
755
  }
756
 
757
- function add_qs($url, $qs, $amp=true) {
758
- if (strpos($url, '?') !== false) {
759
- if ($amp) return $url . '&amp;' . $qs;
760
- else return $url . '&' . $qs;
761
- }
762
- else return $url . '?' . $qs;
763
- }
764
-
765
- function post_is_old() {
766
- }
767
-
768
  function hook_shutdown() {
769
  if ($this->mailer != null) $this->mailer->SmtpClose();
770
  }
771
 
772
- function shortcode_newsletter_lock($attrs, $content=null) {
773
- global $hyper_cache_stop, $lite_cache_stop;
774
 
775
  $hyper_cache_stop = true;
776
- $lite_cache_stop = true;
777
 
778
  $user = $this->check_user();
779
  if ($user != null && $user->status == 'C') {
@@ -784,41 +760,26 @@ class Newsletter {
784
  ob_start();
785
  eval('?>' . $buffer . "\n");
786
  $buffer = ob_get_clean();
787
- $buffer = str_ireplace('<form', '<form method="post" action="' . $this->options_main['url'] . '"', $buffer);
788
- $buffer = str_ireplace('</form>', '<input type="hidden" name="na" value="s"/></form>', $buffer);
789
  return do_shortcode($buffer);
790
  }
791
 
792
- function normalize_email($email) {
793
- $email = strtolower(trim($email));
794
- if (!is_email($email)) return null;
795
- return $email;
796
- }
797
-
798
- function normalize_name($name) {
799
- $name = str_replace(';', ' ', $name);
800
- $name = strip_tags($name);
801
- return $name;
802
- }
803
 
804
- function is_email($email, $empty_ok=false) {
805
- $email = strtolower(trim($email));
806
- if ($empty_ok && $email == '') return true;
807
 
808
- if (!is_email($email)) return false;
809
- if (strpos($email, 'mailinator.com') !== false) return false;
810
- if (strpos($email, 'guerrillamailblock.com') !== false) return false;
811
- if (strpos($email, 'emailtemporanea.net') !== false) return false;
812
- return true;
813
- }
814
 
815
- function m2t($s) {
816
- $s = explode(' ', $s);
817
- $d = explode('-', $s[0]);
818
- $t = explode(':', $s[1]);
819
- return gmmktime((int) $t[0], (int) $t[1], (int) $t[2], (int) $d[1], (int) $d[2], (int) $d[0]);
820
  }
821
 
 
 
 
822
  function query($query) {
823
  global $wpdb;
824
 
@@ -827,67 +788,239 @@ class Newsletter {
827
  }
828
 
829
  function notify_admin($user, $subject) {
830
- if ($this->options_main['notify'] != 1) return;
831
  $message = "Subscriber details:\n\n" .
832
- "email: " . $user->email . "\n" .
833
- "first name: " . $user->name . "\n" .
834
- "last name: " . $user->surname . "\n" .
835
- "gender: " . $user->sex . "\n";
836
 
837
  $options_profile = get_option('newsletter_profile');
838
 
839
- for ($i=0; $i<NEWSLETTER_PROFILE_MAX; $i++) {
840
  if ($options_profile['profile_' . $i] == '') continue;
841
  $field = 'profile_' . $i;
842
  $message .= $options_profile['profile_' . $i] . ': ' . $user->$field . "\n";
843
  }
844
 
 
 
 
 
 
 
845
  $message .= "token: " . $user->token . "\n" .
846
- "status: " . $user->status . "\n" .
847
- "\nYours, Newsletter Pro.";
848
 
849
  wp_mail(get_option('admin_email'), '[' . get_option('blogname') . '] ' . $subject, $message, "Content-type: text/plain; charset=UTF-8\n");
850
  }
851
 
852
- }
 
 
 
 
 
 
 
853
 
854
- require_once(dirname(__FILE__) . '/widget.php');
 
 
 
 
 
855
 
 
 
 
 
 
 
 
 
 
 
 
856
 
857
- /**
858
- * Find an image for a post checking the media uploaded for the post and
859
- * choosing the first image found.
860
- */
861
- function nt_post_image($post_id, $size='thumbnail', $alternative=null) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
862
 
863
- $attachments = get_children(array('post_parent' => $post_id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864
 
865
- if (empty($attachments)) {
866
- return $alternative;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
  }
868
 
869
- foreach ($attachments as $id => $attachment) {
870
- $image = wp_get_attachment_image_src($id, $size);
871
- return $image[0];
 
 
 
872
  }
873
- return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
  }
875
 
876
- function nt_option($name, $def = null) {
877
- $options = get_option('newsletter_email');
878
- $option = $options['theme_' . $name];
879
- if (!isset($option)) return $def;
880
- else return $option;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
881
  }
882
 
883
- // For compatibility
884
- function newsletter_form($number=null) {
885
- global $newsletter;
886
- echo $newsletter->form($number);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
887
  }
888
 
889
- // For compatibility
890
- function newsletter_embed_form($number=null) {
891
- global $newsletter;
892
- echo $newsletter->form($number);
 
 
 
 
 
 
893
  }
1
  <?php
2
+
3
  /*
4
  Plugin Name: Newsletter
5
  Plugin URI: http://www.satollo.net/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="http://www.satollo.net/plugins/newsletter#update">this page</a> to know what's changed.</strong>
7
+ Version: 3.0.0
8
+ Author: Stefano Lissa
9
  Author URI: http://www.satollo.net
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
11
 
12
+ Copyright 2011 Stefano Lissa (email: info@satollo.net, web: http://www.satollo.net)
13
  */
14
 
15
+ // Useed as dummy parameter on css and js links
16
+ define('NEWSLETTER_VERSION', '3.0.0');
17
+
18
+ global $wpdb, $newsletter;
19
+
20
+ //@include_once WP_CONTENT_DIR . '/extensions/newsletter/config.php';
21
+
22
+ define('NEWSLETTER_EMAILS_TABLE', $wpdb->prefix . 'newsletter_emails');
23
+ define('NEWSLETTER_USERS_TABLE', $wpdb->prefix . 'newsletter');
24
+ define('NEWSLETTER_STATS_TABLE', $wpdb->prefix . 'newsletter_stats');
25
+
26
+ // Do not use basename(dirname()) since on activation the plugin is sandboxed inside a function
27
+ define('NEWSLETTER_SLUG', 'newsletter');
28
+
29
+ define('NEWSLETTER_DIR', WP_PLUGIN_DIR . '/' . NEWSLETTER_SLUG);
30
+ define('NEWSLETTER_INCLUDES_DIR', WP_PLUGIN_DIR . '/' . NEWSLETTER_SLUG . '/includes');
31
+ define('NEWSLETTER_URL', WP_PLUGIN_URL . '/' . NEWSLETTER_SLUG);
32
+ define('NEWSLETTER_SUBSCRIPTION_POPUP_URL', NEWSLETTER_URL . '/do/subscription-popup.php');
33
+ define('NEWSLETTER_SUBSCRIBE_URL', NEWSLETTER_URL . '/do/subscribe.php');
34
+ define('NEWSLETTER_SUBSCRIBE_POPUP_URL', NEWSLETTER_URL . '/do/subscribe-popup.php');
35
+ define('NEWSLETTER_PROFILE_URL', NEWSLETTER_URL . '/do/profile.php');
36
+ define('NEWSLETTER_SAVE_URL', NEWSLETTER_URL . '/do/save.php');
37
+ define('NEWSLETTER_CONFIRM_URL', NEWSLETTER_URL . '/do/confirm.php');
38
+ define('NEWSLETTER_CHANGE_URL', NEWSLETTER_URL . '/do/change.php');
39
+ define('NEWSLETTER_UNLOCK_URL', NEWSLETTER_URL . '/do/unlock.php');
40
+ define('NEWSLETTER_UNSUBSCRIBE_URL', NEWSLETTER_URL . '/do/unsubscribe.php');
41
+ define('NEWSLETTER_UNSUBSCRIPTION_URL', NEWSLETTER_URL . '/do/unsubscription.php');
42
 
43
+ define('NEWSLETTER_EMAIL_URL', NEWSLETTER_URL . '/do/view.php');
 
44
 
45
+ if (!defined('NEWSLETTER_LIST_MAX')) define('NEWSLETTER_LIST_MAX', 20);
46
+ if (!defined('NEWSLETTER_PROFILE_MAX')) define('NEWSLETTER_PROFILE_MAX', 20);
47
+ if (!defined('NEWSLETTER_FORMS_MAX')) define('NEWSLETTER_FORMS_MAX', 10);
48
 
49
+ // Force the whole system log level to this value
50
+ //define('NEWSLETTER_LOG_LEVEL', 4);
51
+
52
+ require_once NEWSLETTER_INCLUDES_DIR . '/logger.php';
53
+ require_once NEWSLETTER_INCLUDES_DIR . '/store.php';
54
+ require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
55
+ require_once NEWSLETTER_INCLUDES_DIR . '/themes.php';
56
+
57
+ class Newsletter extends NewsletterModule {
58
+
59
+ const VERSION = '1.0.7';
60
+
61
+ // Limits to respect to avoid memory, time or provider limits
62
  var $time_limit;
63
+ var $email_limit = 10; // Per run, every 5 minutes
64
+ var $limits_set = false;
65
+ var $max_emails = 20;
66
+
67
+ /**
68
+ * @var PHPMailer
69
+ */
70
  var $mailer;
71
+ // Message shown when the interaction is inside a WordPress page
72
  var $message;
73
  var $user;
74
  var $error;
75
+ var $theme;
76
+ // Theme autocomposer variables
77
+ var $theme_max_posts;
78
+ var $theme_excluded_categories; // comma separated ids (eventually negative to exclude)
79
+ var $theme_posts; // WP_Query object
80
+ // Secret key to create a unique log file name (and may be other)
81
+ static $instance;
82
 
83
+ /**
84
+ * @return Newsletter
85
+ */
86
+ static function instance() {
87
+ if (self::$instance == null) {
88
+ self::$instance = new Newsletter();
89
+ }
90
+ return self::$instance;
91
+ }
92
 
93
+ function __construct() {
94
  // Early possible
95
  $max_time = (int) (@ini_get('max_execution_time') * 0.9);
96
  if ($max_time == 0) $max_time = 600;
97
  $this->time_limit = time() + $max_time;
98
 
99
+ // Here because the upgrade is called by the parent constructor and uses the scheduler
100
+ add_filter('cron_schedules', array(&$this, 'hook_cron_schedules'), 1000);
101
 
102
+ parent::__construct('main', self::VERSION);
 
 
103
 
104
+ $max = $this->options['scheduler_max'];
105
+ if (!is_numeric($max)) $max = 100;
106
+ $this->max_emails = max(floor($max / 12), 1);
107
+
108
+ add_action('init', array(&$this, 'hook_init'));
109
  add_action('newsletter', array(&$this, 'hook_newsletter'), 1);
110
 
111
  // This specific event is created by "Feed by mail" panel on configuration
112
+ add_action('shutdown', array(&$this, 'hook_shutdown'));
113
+
114
+ if (defined('DOING_CRON') && DOING_CRON) return;
115
+
116
+ // TODO: Meditation on how to use those ones...
117
+ //register_activation_hook(__FILE__, array(&$this, 'hook_activate'));
118
+ //register_deactivation_hook(__FILE__, array(&$this, 'hook_deactivate'));
119
+
120
+ add_action('admin_init', array(&$this, 'hook_admin_init'));
121
+
122
  add_action('wp_head', array(&$this, 'hook_wp_head'));
123
+
124
  add_shortcode('newsletter_lock', array(&$this, 'shortcode_newsletter_lock'));
125
+ add_shortcode('newsletter_profile', array(&$this, 'shortcode_newsletter_profile'));
126
+
127
+ if (is_admin()) {
 
128
  add_action('admin_menu', array(&$this, 'hook_admin_menu'));
129
  add_action('admin_head', array(&$this, 'hook_admin_head'));
130
  }
131
+ }
132
+
133
+ function upgrade() {
134
+ global $wpdb, $charset_collate;
135
+
136
+ $this->upgrade_query("create table if not exists " . $wpdb->prefix . "newsletter_emails (id int auto_increment, primary key (id)) $charset_collate");
137
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column message longtext");
138
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column message_text longtext");
139
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column subject varchar(255) not null default ''");
140
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column type varchar(50) not null default ''");
141
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column created timestamp not null default current_timestamp");
142
+
143
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column status enum('new','sending','sent','paused') not null default 'new'");
144
+
145
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column total int not null default 0");
146
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column last_id int not null default 0");
147
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column sent int not null default 0");
148
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column send_on int not null default 0");
149
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column track tinyint not null default 0");
150
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column editor tinyint not null default 0");
151
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column sex char(1) not null default 'n'");
152
+
153
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column query text");
154
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails add column preferences text");
155
+
156
+ // Cleans up old installations
157
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails drop column name");
158
+ $this->upgrade_query("drop table if exists " . $wpdb->prefix . "newsletter_work");
159
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter_emails convert to character set utf8");
160
+
161
+ // TODO: To be moved on users module.
162
+ $this->upgrade_query("alter table " . $wpdb->prefix . "newsletter convert to character set utf8");
163
+
164
+ // Some setting check to avoid the common support request for mis-configurations
165
+ $options = $this->get_options();
166
+
167
+ if (empty($options['sender_email'])) {
168
+ // That code was taken from WordPress
169
+ $sitename = strtolower($_SERVER['SERVER_NAME']);
170
+ if (substr($sitename, 0, 4) == 'www.') $sitename = substr($sitename, 4);
171
+ // WordPress build an address in the same way using wordpress@...
172
+ $options['sender_email'] = 'newsletter@' . $sitename;
173
+ $this->save_options($options);
174
+ }
175
+
176
+ if (empty($options['api_key'])) {
177
+ $options['api_key'] = self::get_token();
178
+ $this->save_options($options);
179
+ }
180
+
181
+ if (empty($options['scheduler_max'])) {
182
+ $options['scheduler_max'] = 100;
183
+ $this->save_options($options);
184
+ }
185
+
186
+ wp_clear_scheduled_hook('newsletter');
187
+ wp_schedule_event(time() + 30, 'newsletter', 'newsletter');
188
+
189
+ // $sql = 'create table if not exists ' . $wpdb->prefix . 'newsletter_profiles (
190
+ // `newsletter_id` int NOT NULL,
191
+ // `name` varchar (100) NOT NULL DEFAULT \'\',
192
+ // `value` text,
193
+ // primary key (newsletter_id, name)
194
+ // ) DEFAULT charset=utf8';
195
+
196
+ wp_mkdir_p(WP_CONTENT_DIR . '/extensions/newsletter');
197
+ wp_mkdir_p(WP_CONTENT_DIR . '/cache/newsletter');
198
+
199
+ return true;
200
+ }
201
+
202
+ /**
203
+ * Returns a set of warnings about this installtion the suser should be aware of. Return an empty string
204
+ * if there are no warnings.
205
+ */
206
+ function warnings() {
207
+ $warnings = '';
208
+ $x = wp_next_scheduled('newsletter');
209
+ if ($x === false) {
210
+ $warnings .= 'The delivery engine is off (it should never be off). See the System Check below to reactivate it.<br>';
211
+ }
212
+ else if (time() - $x > 900) {
213
+ $warnings .= 'The cron system seems not running correctly. See <a href="http://www.satollo.net/how-to-make-the-wordpress-cron-work" target="_blank">this page</a> for more information.<br>';
214
+ }
215
 
216
+ if (!empty($warnings)) {
217
+ echo '<div id="#newsletter-warnings">';
218
+ echo $warnings;
219
+ echo '</div>';
220
+ }
221
+ }
222
+
223
+ // TODO: Remove almost anything...
224
+ function hook_init() {
225
+ global $cache_stop, $hyper_cache_stop, $wpdb;
226
+
227
+
228
+ $action = $_REQUEST['na'];
229
+ if (empty($action) || is_admin()) return;
230
+
231
+ $cache_stop = true;
232
+ $hyper_cache_stop = true;
233
+
234
+ if ($action == 'of') {
235
+ echo $this->subscription_form('os');
236
+ die();
237
+ }
238
+
239
+ // Actions below need a user. This code loads the user checking parameter or cookies.
240
+ $user = $this->check_user();
241
+ if ($user == null) die('No user');
242
+
243
+ if ($action == 'fu') {
244
+ $wpdb->query("update " . $wpdb->prefix . "newsletter set followup=2 where id=" . $user->id);
245
+ $options_followup = get_option('newsletter_followup');
246
+ $this->message = $options_followup['unsubscribed_text'];
247
+ return;
248
+ }
249
+ }
250
+
251
+ function is_admin_page() {
252
+ // TODO: Use the module list to detect that...
253
+ return strpos($_GET['page'], 'newsletter_') === 0 || strpos($_GET['page'], 'newsletter-statistics/') === 0 || strpos($_GET['page'], 'newsletter/') === 0 ||
254
+ strpos($_GET['page'], 'newsletter-updates/') === 0 || strpos($_GET['page'], 'newsletter-flows/') === 0;
255
+ }
256
+
257
+ function hook_admin_init() {
258
+ if ($this->is_admin_page()) {
259
+ wp_enqueue_script('jquery-ui-tabs');
260
+ wp_enqueue_script('media-upload');
261
+ wp_enqueue_script('thickbox');
262
+ wp_enqueue_style('thickbox');
263
+ }
264
  }
265
 
266
  function hook_admin_head() {
267
+ if ($this->is_admin_page()) {
268
+ echo '<link type="text/css" rel="stylesheet" href="' . NEWSLETTER_URL . '/admin.css?' . NEWSLETTER_VERSION . '"/>';
269
+ echo '<script src="' . NEWSLETTER_URL . '/admin.js?' . NEWSLETTER_VERSION . '"></script>';
270
  }
271
  }
272
 
273
  function hook_admin_menu() {
274
  include 'plugin-menu.inc.php';
275
+
276
+ do_action('newsletter_admin_menu');
277
+
278
+ add_submenu_page('newsletter/welcome.php', 'Diagnostic', 'Diagnostic', $level, 'newsletter/diagnostic.php');
279
+
280
  }
281
 
282
  function hook_wp_head() {
283
+ if (!empty($this->options['css'])) {
284
+ echo "<style type='text/css'>\n";
285
+ echo $this->options['css'];
286
+ echo "</style>";
287
+ }
288
 
289
+ // TODO: move on subscription module
290
+ $profile_options = get_option('newsletter_profile');
291
+ if ($profile_options['style'] != '') {
292
+ echo '<link href="' . NewsletterSubscription::instance()->get_style_url($profile_options['style']) . '" type="text/css" rel="stylesheet">\n';
293
+ }
294
  }
295
 
296
+ function relink($text, $email_id, $user_id) {
297
+ return NewsletterStatistics::instance()->relink($text, $email_id, $user_id);
 
 
 
 
 
 
298
  }
299
 
300
+ /**
301
+ * Runs every 5 minutes and look for emails that need to be processed.
302
+ */
303
  function hook_newsletter() {
304
  global $wpdb;
305
 
306
+ $this->logger->debug('hook_newsletter> Starting');
 
307
 
308
+ // Do not accept job activation before at least 4 minutes are elapsed from the last run.
309
+ if (!$this->check_transient('engine', 240)) return;
 
 
 
310
 
311
  // Retrieve all email in "sending" status
312
+ $emails = $wpdb->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " where status='sending' and send_on<" . time() . " order by id asc");
313
+ $this->logger->debug('hook_newsletter> Emails found in sending status: ' . count($emails));
314
+ foreach ($emails as &$email) {
315
+ $this->logger->debug('hook_newsletter> Sending email ' . $email->id);
316
  if (!$this->send($email)) return;
317
  }
318
+
319
+ // TODO: Manage the follow-up with Newsletter 3.0.
320
+ if (defined('NEWSLETTER_FOLLOWUP_VERSION')) {
321
+ //global $newsletter_followup;
322
+ //$newsletter_followup->send();
323
+ }
324
  }
325
 
326
+ /**
327
+ * Sends an email to targeted users ot to users passed on. If a list of users is given (usually a list of test users)
328
+ * the query inside the email to retrieve users is not used.
329
+ *
330
+ * @global type $wpdb
331
+ * @global type $newsletter_feed
332
+ * @param type $email
333
+ * @param array $users
334
+ * @return boolean True if the proccess completed, false if limits was reached. On false the caller should no continue to call it with other emails.
335
+ */
336
  function send($email, $users = null) {
337
  global $wpdb;
338
 
339
+ if (is_array($email)) $email = (object) $email;
340
 
341
+ // This stops the update of last_id and sent fields since it's not a scheduled delivery but a test.
342
+ $test = $users != null;
343
 
344
  if ($users == null) {
345
+ if (empty($email->query)) $email->query = "select * from " . NEWSLETTER_EMAILS_TABLE . " where status='C'";
346
+ $query = $email->query . " and id>" . $email->last_id . " order by id limit " . $this->max_emails;
347
+ $users = $wpdb->get_results($query);
348
+
349
+ // If there was a database error, do nothing
350
+ if ($wpdb->last_error) {
351
+ $this->logger->fatal($wpdb->last_error);
352
+ return;
 
 
 
 
 
 
353
  }
354
+
355
+ if (empty($users)) {
356
+ $this->logger->info('No more users');
357
+ $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set status='sent' where id=" . $email->id . " limit 1");
358
+ return true;
 
 
 
 
 
359
  }
360
  }
361
 
362
+ foreach ($users as &$user) {
 
 
 
 
363
 
364
+ // Before try to send, check the limits.
365
+ if (!$test && $this->limits_exceeded()) return false;
 
366
 
367
+ $headers = array('List-Unsubscribe' => '<' . NEWSLETTER_UNSUBSCRIBE_URL . '?nk=' . $user->id . '-' . $user->token . '>');
 
 
368
 
369
+ if (!$test) {
370
+ $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
371
+ }
372
 
373
+ $m = $this->replace($email->message, $user, $email->id);
374
+ $mt = $this->replace($email->message_text, $user, $email->id);
 
 
375
 
376
+
377
+ if ($email->track == 1) $m = $this->relink($m, $email->id, $user->id);
378
 
379
  $s = $this->replace($email->subject, $user);
 
380
 
381
+ $this->mail($user->email, $s, array('html' => $m, 'text' => $mt), $headers);
382
+
383
  $this->email_limit--;
 
384
  }
 
 
385
 
386
+ // TODO: Integrate the feed by mail
387
+ if (defined('NEWSLETTER_FEED_VERSION')) {
388
+ //global $newsletter_feed;
389
+ //if ($email->type == 'feed') return $newsletter_feed->feed_send($email, $users);
390
+ }
391
 
392
+ return true;
393
  }
394
 
395
+ function execute($text, $user = null) {
396
  global $wpdb;
397
  ob_start();
398
  $r = eval('?' . '>' . $text);
407
  }
408
 
409
  /**
410
+ * This function checks is, during processing, we are getting to near to system limits and should stop any further
411
+ * work (when returns true).
412
  */
413
  function limits_exceeded() {
414
+ global $wpdb;
415
+
416
+ if (!$this->limits_set) {
417
+ $this->logger->debug('limits_exceeded> Setting the limits for the first time');
418
+ $max = $this->options['scheduler_max'];
419
+ if (!is_numeric($max)) $max = 100;
420
+ $this->email_limit = max(floor($max / 12), 1);
421
+ $this->logger->debug('limits_exceeded> Max number of emails can send: ' . $this->email_limit);
422
+
423
+ $wpdb->query("set session wait_timeout=300");
424
+ // From default-constants.php
425
+ if (function_exists('memory_get_usage') && ( (int) @ini_get('memory_limit') < 128 ))
426
+ @ini_set('memory_limit', '256M');
427
+
428
+ $this->limits_set = true;
429
+ }
430
+
431
+ // The time limit is set on constructor, since it has to be set as early as possible
432
  if (time() > $this->time_limit) {
433
+ $this->logger->info('limits_exceeded> Max execution time limit reached');
434
  return true;
435
  }
436
+
437
+ if ($this->email_limit <= 0) {
438
+ $this->logger->info('limits_exceeded> Max emails limit reached');
439
  return true;
440
  }
441
  return false;
442
  }
443
 
444
+ /**
445
+ *
446
+ * @param string $to
447
+ * @param string $subject
448
+ * @param string|array $message
449
+ * @param type $headers
450
+ * @return boolean
451
+ */
452
+ function mail($to, $subject, $message, $headers = null) {
453
 
454
+ $this->logger->debug('mail> To: ' . $to);
455
+ $this->logger->debug('mail> Subject: ' . $subject);
456
  if (empty($subject)) {
457
+ $this->logger->debug('mail> Subject empty, skipped');
458
  return true;
459
  }
460
 
461
+ if ($this->mailer == null) $this->mailer_init();
462
 
463
+ // Simple message is asumed to be html
464
+ if (!is_array($message)) {
465
+ $this->mailer->IsHTML(true);
466
+ $this->mailer->Body = $message;
467
+ }
468
+ else {
469
+ // Only html is present?
470
+ if (empty($message['text'])) {
471
+ $this->mailer->IsHTML(true);
472
+ $this->mailer->Body = $message['html'];
473
+ }
474
+ // Only text is present?
475
+ else if (empty($message['html'])) {
476
+ $this->mailer->IsHTML(false);
477
+ $this->mailer->Body = $message['text'];
478
+ }
479
+ else {
480
+ $this->mailer->IsHTML(true);
481
 
482
+ $this->mailer->Body = $message['html'];
483
+ $this->mailer->AltBody = $message['text'];
 
 
484
  }
485
+ }
486
 
487
+ $this->mailer->Subject = $subject;
488
 
489
+ $this->mailer->ClearCustomHeaders();
490
+ if (!empty($headers)) {
491
+ foreach ($headers as $key => $value) {
492
+ $this->mailer->AddCustomHeader($key . ': ' . $value);
493
  }
494
+ }
 
 
 
 
 
 
 
 
 
 
 
 
495
 
496
+ $this->mailer->ClearAddresses();
497
+ $this->mailer->AddAddress($to);
498
+ $this->mailer->Send();
499
 
500
+ if ($this->mailer->IsError()) {
501
+ $this->logger->error('mail> ' . $this->mailer->ErrorInfo);
502
+ // If the error is due to SMTP connection, the mailer cannot be reused since it does not clean up the connection
503
+ // on error.
504
+ $this->mailer = null;
505
+ return false;
506
+ }
507
+ return true;
508
  }
509
 
510
+ function mailer_init() {
511
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
512
+ require_once ABSPATH . WPINC . '/class-smtp.php';
513
+ $this->mailer = new PHPMailer();
514
+
515
+ if ($this->options['smtp_enabled'] == 1) {
516
+ $this->mailer->IsSMTP();
517
+ $this->mailer->Host = $this->options['smtp_host'];
518
+ if (!empty($this->options['smtp_port'])) $this->mailer->Port = (int) $this->options['smtp_port'];
519
+
520
+ if (!empty($this->options['smtp_user'])) {
521
+ $this->mailer->SMTPAuth = true;
522
+ $this->mailer->Username = $this->options['smtp_user'];
523
+ $this->mailer->Password = $this->options['smtp_pass'];
524
+ }
525
+ $this->mailer->SMTPKeepAlive = true;
526
+ $this->mailer->SMTPSecure = $this->options['smtp_secure'];
527
+ }
528
+ else $this->mailer->IsMail();
529
 
530
+ if (!empty($this->options['content_transfer_encoding']))
531
+ $this->mailer->Encoding = $this->options['content_transfer_encoding'];
 
 
 
532
 
533
+ $this->mailer->CharSet = 'UTF-8';
534
+ $this->mailer->From = $this->options['sender_email'];
535
+ if (!empty($this->options['return_path'])) $this->mailer->Sender = $this->options['return_path'];
536
+ if (!empty($this->options['reply_to'])) $this->mailer->AddReplyTo($this->options['reply_to']);
 
 
 
 
 
 
 
 
 
537
 
538
+ $this->mailer->FromName = $this->options['sender_name'];
 
 
539
  }
540
 
541
  function hook_deactivate() {
542
  wp_clear_scheduled_hook('newsletter');
543
+ wp_clear_scheduled_hook('newsletter_feed');
544
  }
545
 
546
  function hook_cron_schedules($schedules) {
551
  return $schedules;
552
  }
553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  function shortcode_newsletter_form($attrs, $content) {
555
  return $this->form($attrs['form']);
556
  }
557
 
558
+ function form($number = null) {
559
  if ($number == null) return $this->subscription_form();
560
  $options = get_option('newsletter_forms');
 
561
 
562
+ $form = $options['form_' . $number];
563
 
564
+ if (stripos($form, '<form') !== false) {
565
+ $form = str_replace('{newsletter_url}', NEWSLETTER_SUBSCRIBE_URL, $form);
566
+ } else {
567
+ $form = '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_URL . '" onsubmit="return newsletter_check(this)">' .
568
+ $form . '</form>';
569
  }
 
 
 
570
 
571
+ $form = $this->replace_lists($form);
 
572
 
573
+ return $form;
574
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
 
576
+ function find_file($file1, $file2) {
577
+ if (is_file($file1)) return $file1;
578
+ return $file2;
579
+ }
580
 
581
+ /**
582
+ * Return a user if there are request parameters or cookie with identification data otherwise null.
583
+ */
584
+ function check_user() {
585
+ global $wpdb, $current_user;
586
+
587
+ if (isset($_REQUEST['nk'])) {
588
+ list($id, $token) = @explode('-', $_REQUEST['nk'], 2);
589
+ } else if (isset($_REQUEST['ni'])) {
590
+ $id = (int) $_REQUEST['ni'];
591
+ $token = $_REQUEST['nt'];
592
+ } else if (isset($_COOKIE['newsletter'])) {
593
+ list ($id, $token) = @explode('-', $_COOKIE['newsletter'], 2);
594
  }
595
 
596
+ if (is_numeric($id) && !empty($token)) {
597
+ return $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix . "newsletter where id=%d and token=%s limit 1", $id, $token));
 
 
598
  }
599
 
600
+ if ($this->options_main['wp_integration'] != 1) {
601
+ return null;
 
 
 
602
  }
603
 
604
+ get_currentuserinfo();
605
+
606
+ // Retrieve the related newsletter user
607
+ $user = $wpdb->get_row("select * from " . NEWSLETTER_USERS_TABLE . " where wp_user_id=" . $current_user->ID . " limit 1");
608
+ // There is an email matching?
609
+ if (empty($user)) {
610
+ $user = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_USERS_TABLE . " where email=%s limit 1", strtolower($current_user->user_email)));
611
+ // If not found, create a new Newsletter user, else update the wp_user_id since this email must be linked
612
+ // to the WP user email.
613
+ if (empty($user)) {
614
+ return null;
615
+ //echo 'WP user not found';
616
+ $user = array();
617
+ $user['status'] = 'C';
618
+ $user['wp_user_id'] = $current_user->ID;
619
+ $user['token'] = $this->get_token();
620
+ $user['email'] = strtolower($current_user->user_email);
621
+
622
+ $id = $wpdb->insert(NEWSLETTER_USERS_TABLE, $user);
623
+ $user = NewsletterUsers::instance()->get_user($id);
624
+ } else {
625
+ //echo 'WP user found via email';
626
+ $wpdb->query($wpdb->prepare("update " . NEWSLETTER_USERS_TABLE . " set wp_user_id=" . $current_user->ID . ", email=%s", $current_user->user_email));
 
 
 
 
 
627
  }
628
+ } else {
629
+ //echo 'WP user found via id';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  }
 
631
 
632
+ return $user;
 
 
 
 
 
633
  }
634
 
635
+ function replace_date($text) {
636
+ // Date processing
637
+ $x = 0;
638
+ while (($x = strpos($text, '{date_', $x)) !== false) {
639
+ $y = strpos($text, '}', $x);
640
+ if ($y === false) continue;
641
+ $f = substr($text, $x + 6, $y - $x - 6);
642
+ $text = substr($text, 0, $x) . date($f) . substr($text, $y + 1);
643
  }
644
+ return $text;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  }
646
 
647
  /**
648
  * Replace any kind of newsletter placeholder in a text.
649
  */
650
+ function replace($text, $user = null, $email_id = null) {
651
  global $wpdb;
652
 
653
+ if (is_array($user)) $user = NewsletterUsers::instance()->get_user($user['id']);
654
  $text = str_replace('{home_url}', get_option('home'), $text);
655
  $text = str_replace('{blog_title}', get_option('blogname'), $text);
 
656
  $text = str_replace('{blog_description}', get_option('blogdescription'), $text);
657
+ $text = str_replace('{date}', date_i18n(get_option('date_format')), $text);
658
 
659
+ $text = $this->replace_date($text);
 
 
 
 
 
 
 
660
 
661
  if ($user != null) {
662
  $text = str_replace('{email}', $user->email, $text);
663
+ if (empty($user->name)) {
664
+ $text = str_replace(' {name}', '', $text);
665
+ $text = str_replace('{name}', '', $text);
666
+ } else {
667
+ $text = str_replace('{name}', $user->name, $text);
668
+ }
669
  $text = str_replace('{surname}', $user->surname, $text);
670
  $text = str_replace('{token}', $user->token, $text);
671
  $text = str_replace('%7Btoken%7D', $user->token, $text);
672
  $text = str_replace('{id}', $user->id, $text);
673
  $text = str_replace('%7Bid%7D', $user->id, $text);
674
  $text = str_replace('{ip}', $user->ip, $text);
675
+ $text = str_replace('{key}', $user->id . '-' . $user->token, $text);
676
+ $text = str_replace('%7Bkey%7D', $user->id . '-' . $user->token, $text);
677
 
678
+ if (strpos($text, '{profile_form}') !== false)
679
+ $text = str_replace('{profile_form}', NewsletterSubscription::instance()->get_profile_form($user), $text);
680
 
681
+ for ($i = 1; $i < NEWSLETTER_PROFILE_MAX; $i++) {
682
  $p = 'profile_' . $i;
683
  $text = str_replace('{profile_' . $i . '}', $user->$p, $text);
684
  }
690
 
691
  $text = preg_replace('/\\{np_.+\}/i', '', $text);
692
 
693
+ $base = (empty($this->options_main['url']) ? get_option('home') : $this->options_main['url']);
 
694
  $id_token = '&amp;ni=' . $user->id . '&amp;nt=' . $user->token;
695
+ $nk = $user->id . '-' . $user->token;
696
 
697
+ //$text = $this->replace_url($text, 'SUBSCRIPTION_CONFIRM_URL', self::add_qs(plugins_url('do.php', __FILE__), 'a=c' . $id_token));
698
+ $text = $this->replace_url($text, 'SUBSCRIPTION_CONFIRM_URL', NEWSLETTER_CONFIRM_URL . '?nk=' . $nk);
699
+ $text = $this->replace_url($text, 'UNSUBSCRIPTION_CONFIRM_URL', NEWSLETTER_UNSUBSCRIBE_URL . '?nk=' . $nk);
700
+ //$text = $this->replace_url($text, 'UNSUBSCRIPTION_CONFIRM_URL', NEWSLETTER_URL . '/do/unsubscribe.php?nk=' . $nk);
701
+ $text = $this->replace_url($text, 'UNSUBSCRIPTION_URL', NEWSLETTER_UNSUBSCRIPTION_URL . '?nk=' . $nk);
702
+ $text = $this->replace_url($text, 'CHANGE_URL', NEWSLETTER_CHANGE_URL);
703
 
704
+ // Obsolete.
705
+ $text = $this->replace_url($text, 'FOLLOWUP_SUBSCRIPTION_URL', self::add_qs($base, 'nm=fs' . $id_token));
706
+ $text = $this->replace_url($text, 'FOLLOWUP_UNSUBSCRIPTION_URL', self::add_qs($base, 'nm=fu' . $id_token));
707
+ $text = $this->replace_url($text, 'FEED_SUBSCRIPTION_URL', self::add_qs($base, 'nm=es' . $id_token));
708
+ $text = $this->replace_url($text, 'FEED_UNSUBSCRIPTION_URL', self::add_qs($base, 'nm=eu' . $id_token));
709
 
710
+ $options_profile = get_option('newsletter_profile');
711
+ if (empty($options_profile['profile_url']))
712
+ $text = $this->replace_url($text, 'PROFILE_URL', NEWSLETTER_PROFILE_URL . '?nk=' . $nk);
713
+ else
714
+ $text = $this->replace_url($text, 'PROFILE_URL', self::add_qs($options_profile['profile_url'], 'ni=' . $user->id . '&amp;nt=' . $user->token));
715
+
716
+ //$text = $this->replace_url($text, 'UNLOCK_URL', self::add_qs($this->options_main['lock_url'], 'nm=m' . $id_token));
717
+ $text = $this->replace_url($text, 'UNLOCK_URL', NEWSLETTER_UNLOCK_URL . '?nk=' . $nk);
718
+ if (!empty($email_id)) {
719
+ $text = $this->replace_url($text, 'EMAIL_URL', NEWSLETTER_EMAIL_URL . '?id=' . $email_id . '&amp;nk=' . $nk);
720
+ }
721
+
722
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
723
+ $text = $this->replace_url($text, 'LIST_' . $i . '_SUBSCRIPTION_URL', self::add_qs($base, 'nm=ls&amp;nl=' . $i . $id_token));
724
+ $text = $this->replace_url($text, 'LIST_' . $i . '_UNSUBSCRIPTION_URL', self::add_qs($base, 'nm=lu&amp;nl=' . $i . $id_token));
725
  }
726
  }
727
  return $text;
733
  $text = str_replace($home . '{' . $tag_lower . '}', $url, $text);
734
  $text = str_replace($home . '%7B' . $tag_lower . '%7D', $url, $text);
735
  $text = str_replace('{' . $tag_lower . '}', $url, $text);
736
+ $text = str_replace('%7B' . $tag_lower . '%7D', $url, $text);
737
 
738
  // for compatibility
739
  $text = str_replace($home . $tag, $url, $text);
741
  return $text;
742
  }
743
 
 
 
 
 
 
 
 
 
 
 
 
744
  function hook_shutdown() {
745
  if ($this->mailer != null) $this->mailer->SmtpClose();
746
  }
747
 
748
+ function shortcode_newsletter_lock($attrs, $content = null) {
749
+ global $hyper_cache_stop, $cache_stop;
750
 
751
  $hyper_cache_stop = true;
752
+ $cache_stop = true;
753
 
754
  $user = $this->check_user();
755
  if ($user != null && $user->status == 'C') {
760
  ob_start();
761
  eval('?>' . $buffer . "\n");
762
  $buffer = ob_get_clean();
763
+ // TODO: add the newsletter check on submit
764
+ $buffer = str_ireplace('<form', '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_URL . '"', $buffer);
765
  return do_shortcode($buffer);
766
  }
767
 
768
+ function shortcode_newsletter_profile($attrs, $content) {
769
+ global $wpdb, $current_user;
 
 
 
 
 
 
 
 
 
770
 
771
+ $user = $this->check_user();
 
 
772
 
773
+ if ($user == null) {
774
+ return 'No user found.';
775
+ }
 
 
 
776
 
777
+ return $this->profile_form($user);
 
 
 
 
778
  }
779
 
780
+ /**
781
+ * Exceutes a query and log it.
782
+ */
783
  function query($query) {
784
  global $wpdb;
785
 
788
  }
789
 
790
  function notify_admin($user, $subject) {
791
+ if ($this->options['notify'] != 1) return;
792
  $message = "Subscriber details:\n\n" .
793
+ "email: " . $user->email . "\n" .
794
+ "first name: " . $user->name . "\n" .
795
+ "last name: " . $user->surname . "\n" .
796
+ "gender: " . $user->sex . "\n";
797
 
798
  $options_profile = get_option('newsletter_profile');
799
 
800
+ for ($i = 0; $i < NEWSLETTER_PROFILE_MAX; $i++) {
801
  if ($options_profile['profile_' . $i] == '') continue;
802
  $field = 'profile_' . $i;
803
  $message .= $options_profile['profile_' . $i] . ': ' . $user->$field . "\n";
804
  }
805
 
806
+ for ($i = 0; $i < NEWSLETTER_LIST_MAX; $i++) {
807
+ if ($options_profile['list_' . $i] == '') continue;
808
+ $field = 'list_' . $i;
809
+ $message .= $options_profile['list_' . $i] . ': ' . $user->$field . "\n";
810
+ }
811
+
812
  $message .= "token: " . $user->token . "\n" .
813
+ "status: " . $user->status . "\n" .
814
+ "\nYours, Newsletter Pro.";
815
 
816
  wp_mail(get_option('admin_email'), '[' . get_option('blogname') . '] ' . $subject, $message, "Content-type: text/plain; charset=UTF-8\n");
817
  }
818
 
819
+ function get_user_from_request($required = false) {
820
+ if (isset($_REQUEST['nk'])) {
821
+ list($id, $token) = @explode('-', $_REQUEST['nk'], 2);
822
+ } else if (isset($_REQUEST['ni'])) {
823
+ $id = (int) $_REQUEST['ni'];
824
+ $token = $_REQUEST['nt'];
825
+ }
826
+ $user = NewsletterUsers::instance()->get_user($id);
827
 
828
+ if ($user == null || $token != $user->token) {
829
+ if ($required) die('No subscriber found.');
830
+ else return null;
831
+ }
832
+ return $user;
833
+ }
834
 
835
+ function add_menu_page($module, $page, $title) {
836
+ //var_dump($this);
837
+ //$this->menu_pages[] = array($module, $page, $title);
838
+ $file = WP_CONTENT_DIR . '/extensions/newsletter/' . $module . '/' . $page . '.php';
839
+ if (!is_file($file)) {
840
+ $file = NEWSLETTER_DIR . '/' . $module . '/' . $page . '.php';
841
+ }
842
+ $name = 'newsletter_' . $module . '_' . $page;
843
+ eval('function ' . $name . '(){global $newsletter;require "' . $file . '";}');
844
+ add_submenu_page('newsletter/welcome.php', $title, $title, 10, $name, $name);
845
+ }
846
 
847
+ function add_admin_page($module, $page, $title) {
848
+
849
+ $file = WP_CONTENT_DIR . '/extensions/newsletter/' . $module . '/' . $page . '.php';
850
+ if (!is_file($file)) {
851
+ $file = NEWSLETTER_DIR . '/' . $module . '/' . $page . '.php';
852
+ }
853
+
854
+ $name = 'newsletter_' . $module . '_' . $page;
855
+ eval('function ' . $name . '(){global $newsletter;require "' . $file . '";}');
856
+ add_submenu_page(null, $title, $title, 10, $name, $name);
857
+ }
858
+
859
+ function get_emails($type = null, $format = OBJECT) {
860
+ global $wpdb;
861
+ if ($type == null) {
862
+ $list = $wpdb->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " order by id desc", $format);
863
+ } else {
864
+ $list = $wpdb->get_results($wpdb->prepare("select * from " . NEWSLETTER_EMAILS_TABLE . " where type=%s order by id desc", $type), $format);
865
+ }
866
+ if ($wpdb->last_error) {
867
+ $this->logger->error($wpdb->last_error);
868
+ return false;
869
+ }
870
+ if (empty($list)) return array();
871
+ return $list;
872
+ }
873
 
874
+ function save_email($email) {
875
+ return $this->store->save(NEWSLETTER_EMAILS_TABLE, $email);
876
+ }
877
+
878
+ function delete_email($id) {
879
+ return $this->store->delete(NEWSLETTER_EMAILS_TABLE, $id);
880
+ }
881
+
882
+ function get_email($id, $format = OBJECT) {
883
+ return $this->store->get_single(NEWSLETTER_EMAILS_TABLE, $id, $format);
884
+ }
885
+
886
+ function get_email_field($id, $field_name) {
887
+ return $this->store->get_field(NEWSLETTER_EMAILS_TABLE, $id, $field_name);
888
+ }
889
 
890
+ /**
891
+ * Saves a new user on the database. Return false if the email (that must be unique) is already
892
+ * there. For a new users set the token and creation time if not passed.
893
+ *
894
+ * @param type $user
895
+ * @return type
896
+ */
897
+ function save_user($user, $return_format=OBJECT) {
898
+ if (is_object($user)) $user = (array) $user;
899
+ if (empty($user['id'])) {
900
+ if (empty($user['token'])) $user['token'] = NewsletterModule::get_token();
901
+ //if (empty($user['created'])) $user['created'] = time();
902
+ // Database default
903
+ //if (empty($user['status'])) $user['status'] = 'S';
904
+ }
905
+ // Due to the unique index on email field, this can fail.
906
+ return $this->store->save(NEWSLETTER_USERS_TABLE, $user, $return_format);
907
  }
908
 
909
+ /**
910
+ * Returns a list of users marked as "test user".
911
+ * @return array
912
+ */
913
+ function get_test_users() {
914
+ return $this->store->get_all(NEWSLETTER_USERS_TABLE, "where test=1");
915
  }
916
+
917
+ /** Returns the user identify by an id or an email. If $id_or_email is an object or an array, it is assumed it contains
918
+ * the "id" attribute or key and that is used to load the user.
919
+ *
920
+ * @global type $wpdb
921
+ * @param string|int|object|array $id_or_email
922
+ * @param type $format
923
+ * @return boolean
924
+ */
925
+ function get_user($id_or_email, $format=OBJECT) {
926
+ global $wpdb;
927
+
928
+ // To simplify the reaload of a user passing the user it self.
929
+ if (is_object($id_or_email)) $id_or_email = $id_or_email->id;
930
+ else if (is_array($id_or_email)) $id_or_email = $id_or_email['id'];
931
+
932
+ $id_or_email = strtolower(trim($id_or_email));
933
+
934
+ if (is_numeric($id_or_email)) {
935
+ $r = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_USERS_TABLE . " where id=%d limit 1", $id_or_email), $format);
936
+ } else {
937
+ $r = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_USERS_TABLE . " where email=%s limit 1", $id_or_email), $format);
938
+ }
939
+
940
+ if ($wpdb->last_error) {
941
+ $this->logger->error($wpdb->last_error);
942
+ return false;
943
+ }
944
+ return $r;
945
+ }
946
+
947
+ function delete_user($id) {
948
+ global $wpdb;
949
+ $r = $this->store->delete(NEWSLETTER_USERS_TABLE, $id);
950
+ if ($r !== false) {
951
+ $wpdb->delete(NEWSLETTER_STATS_TABLE, array('user_id'=>$id));
952
+ }
953
+ }
954
+
955
+ function set_user_status($id_or_email, $status) {
956
+ global $wpdb;
957
+
958
+ $id_or_email = strtolower(trim($id_or_email));
959
+ if (is_numeric($id_or_email)) {
960
+ $r = $wpdb->query($wpdb->prepare("update " . NEWSLETTER_USERS_TABLE . " set status=%s where id=%d limit 1", $status, $id_or_email));
961
+ } else {
962
+ $r = $wpdb->query($wpdb->prepare("update " . NEWSLETTER_USERS_TABLE . " set status=%s where email=%s limit 1", $status, $id_or_email));
963
+ }
964
+
965
+ if ($wpdb->last_error) {
966
+ $this->logger->error($wpdb->last_error);
967
+ return false;
968
+ }
969
+ return $r;
970
+ }
971
+
972
+
973
  }
974
 
975
+ // Newsletter will be always instantiated.
976
+ $newsletter = Newsletter::instance();
977
+
978
+ // Module loading
979
+ require_once NEWSLETTER_DIR . '/users/users.php';
980
+ require_once NEWSLETTER_DIR . '/subscription/subscription.php';
981
+ require_once NEWSLETTER_DIR . '/emails/emails.php';
982
+ require_once NEWSLETTER_DIR . '/statistics/statistics.php';
983
+ //require_once NEWSLETTER_DIR . '/bounce/bounce.php';
984
+ // Extended module loading
985
+ //if (is_file(WP_CONTENT_DIR . '/newsletter/updates/updates.php')) {
986
+ // require_once WP_CONTENT_DIR . '/newsletter/updates/updates.php';
987
+ //}
988
+ //if (is_file(WP_CONTENT_DIR . '/newsletter/followup/followup.php')) {
989
+ // require_once WP_CONTENT_DIR . '/newsletter/followup/followup.php';
990
+ //}
991
+ //
992
+ if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/feed/feed.php')) {
993
+ require_once WP_CONTENT_DIR . '/extensions/newsletter/feed/feed.php';
994
  }
995
 
996
+ require_once(dirname(__FILE__) . '/widget.php');
997
+
998
+ register_activation_hook(__FILE__, 'newsletter_activate');
999
+
1000
+ function newsletter_activate() {
1001
+ // TODO: May be it's better to declare an "activate" method?
1002
+ Newsletter::instance()->upgrade();
1003
+
1004
+ // Modules
1005
+ NewsletterUsers::instance()->upgrade();
1006
+ NewsletterEmails::instance()->upgrade();
1007
+ NewsletterSubscription::instance()->upgrade();
1008
+ NewsletterStatistics::instance()->upgrade();
1009
+
1010
+ // Extended modules
1011
+ //NewsletterUpdates::instance()->upgrade();
1012
+ //NewsletterFollowup::instance()->upgrade();
1013
+ // TODO: Scan for other modules or use the found modules above
1014
  }
1015
 
1016
+ register_activation_hook(__FILE__, 'newsletter_deactivate');
1017
+
1018
+ function newsletter_deactivate() {
1019
+ // Newsletter::instance()->deactivate();
1020
+ // NewsletterUsers::instance()->deactivate();
1021
+ // NewsletterEmails::instance()->deactivate();
1022
+ // NewsletterSubscription::instance()->deactivate();
1023
+ // NewsletterStatistics::instance()->deactivate();
1024
+ // NewsletterUpdates::instance()->deactivate();
1025
+ // TODO: Scan for other modules or use the found modules above
1026
  }
profile.php DELETED
@@ -1,202 +0,0 @@
1
- <?php
2
- @include_once 'commons.php';
3
-
4
- $nc = new NewsletterControls();
5
-
6
- if (!$nc->is_action()) {
7
- $nc->data = get_option('newsletter_profile');
8
- }
9
- else {
10
- if ($nc->is_action('save')) {
11
- update_option('newsletter_profile', $nc->data);
12
- }
13
- if ($nc->is_action('reset')) {
14
- include dirname(__FILE__) . '/languages/en_US.php';
15
- @include dirname(__FILE__) . '/languages/' . WPLANG . '.php';
16
- update_option('newsletter_profile', $defaults_profile);
17
- $nc->data = $defaults_profile;
18
- }
19
- }
20
-
21
- $nc->errors($errors);
22
- $nc->messages($messages);
23
-
24
- $status = array(0=>'Disabled', 1=>'Only on profile page', 2=>'Even on subscription page');
25
- ?>
26
- <script type="text/javascript" src="<?php echo get_option('siteurl'); ?>/wp-content/plugins/newsletter/tiny_mce/tiny_mce.js"></script>
27
- <script type="text/javascript">
28
- tinyMCE.init({
29
- mode : "specific_textareas",
30
- editor_selector : "visual",
31
- theme : "advanced",
32
- theme_advanced_disable : "styleselect",
33
- relative_urls : false,
34
- remove_script_host : false,
35
- theme_advanced_buttons3: "",
36
- theme_advanced_toolbar_location : "top",
37
- theme_advanced_resizing : true,
38
- theme_advanced_statusbar_location: "bottom",
39
- document_base_url : "<?php echo get_option('home'); ?>/",
40
- content_css : "<?php echo get_option('blogurl'); ?>/wp-content/plugins/newsletter/editor.css?" + new Date().getTime()
41
- });
42
- </script>
43
-
44
- <div class="wrap">
45
-
46
- <h2>Newsletter Profile</h2>
47
-
48
- <?php include dirname(__FILE__) . '/header.php'; ?>
49
-
50
- <p>
51
- User profile is the whole set of user data that he can edit accessing the profile page (usually via the {profile_url} link you
52
- should add in any newsletter or welcome message.<br />
53
- Some of this data (at least the email) is collected on subscription and you can decide here what to ask the user on sign up for your
54
- newsletter.<br />
55
- It's a good practice to let the subscriber to sign up with a small set of data (eg. only his email or email and name) and then let him to
56
- add more information on a profile page.<br />
57
- The form seems complex, but it's not! On first approach, skip profiles and lists.
58
- </p>
59
-
60
- <form action="" method="post">
61
- <?php $nc->init(); ?>
62
-
63
- <h3>Profile page</h3>
64
- <table class="form-table">
65
- <tr valign="top">
66
- <th>Profile page text</th>
67
- <td>
68
- <?php $nc->editor('profile_text'); ?>
69
- <div class="hints">
70
- This is the page content where the profile form is placed. Use the tag {profile_form} (required, don't forget it!) to let Newsletter
71
- Pro know how to insert the profile editing form. You can add text before and after the tag to give some kind of explanation to
72
- the subscriber.<br />
73
- You can use the tag {unsubscription_url} to create a link to let the user to cancel his subscription. Using the tag
74
- {unsubscription_confirm_url} the link leads to a direct cancellation without the confirm step.
75
- </div>
76
- </td>
77
- </tr>
78
- </table>
79
- <p class="submit"><?php $nc->button('save', 'Save'); ?></p>
80
-
81
-
82
- <h3>Main profile fields</h3>
83
- <table class="form-table">
84
- <tr>
85
- <th>User's data/fields</th>
86
- <td>
87
- <table class="widefat">
88
- <thead>
89
- <tr>
90
- <th>Field</th><th>When/Where</th><th>Configuration</th>
91
- </tr>
92
- </thead>
93
- <tr>
94
- <td>Email</td><td>&nbsp;</td>
95
- <td>
96
- label: <?php $nc->text('email'); ?><br/>
97
- wrong email message: <?php $nc->text('email_error', 50); ?>
98
- </td>
99
- </tr>
100
- <tr><td>First Name</td><td><?php $nc->select('name_status', $status); ?></td><td>label: <?php $nc->text('name'); ?></td></tr>
101
- <tr><td>Last Name</td><td><?php $nc->select('surname_status', $status); ?></td><td>label: <?php $nc->text('surname'); ?></td></tr>
102
- <tr>
103
- <td>Sex</td><td><?php $nc->select('sex_status', $status); ?></td>
104
- <td>
105
- label: <?php $nc->text('sex'); ?>
106
- "female": <?php $nc->text('sex_female'); ?>
107
- "male": <?php $nc->text('sex_male'); ?>
108
- </td>
109
- </tr>
110
- <tr><td>Privacy checkbox</td><td><?php $nc->yesno('privacy_status'); ?></td>
111
- <td>
112
- text: <?php $nc->text('privacy', 50); ?><br />
113
- unchecked message: <?php $nc->text('privacy_error', 50); ?>
114
- </td>
115
- </tr>
116
- </table>
117
- <div class="hints">
118
- If sex field is disabled subscribers will be stored with unspecified sex. Privacy is applied only on subscription and is
119
- a checkbox the use must check to proceed with subscription.
120
- </div>
121
- </td>
122
- </tr>
123
- <tr>
124
- <th>Buttons</th>
125
- <td>
126
- "subscribe": <?php $nc->text('subscribe'); ?> "profile save": <?php $nc->text('save'); ?>
127
- <div class="hints">
128
- For "subscribe" insert an URL to an image (http://...) to use it as a graphical button.
129
- </div>
130
- </td>
131
- </tr>
132
- </table>
133
- <p class="submit"><?php $nc->button('save', 'Save'); ?></p>
134
-
135
-
136
- <h3>Extra profile fields</h3>
137
-
138
- <table class="form-table">
139
- <tr>
140
- <th>Generic profile fields</th>
141
- <td>
142
- <div class="hints">Fields of type "list" must be configured with a set of options, comma separated
143
- like: "first option, second option, third option".
144
- </div>
145
- <table class="widefat">
146
- <thead>
147
- <tr>
148
- <th>Field</th><th>Label</th><th>When/Where</th><th>Type</th><th>Configuration</th>
149
- </tr>
150
- </thead>
151
- <?php for ($i=1; $i<=19; $i++) { ?>
152
- <tr>
153
- <td>Profile <?php echo $i; ?></td>
154
- <td><?php $nc->text('profile_' . $i); ?></td>
155
- <td><?php $nc->select('profile_' . $i . '_status', $status); ?></td>
156
- <td><?php $nc->select('profile_' . $i . '_type', array('text'=>'Text', 'select'=>'List')); ?></td>
157
- <td>
158
- <?php $nc->textarea_fixed('profile_' . $i . '_options', '300px', '50px'); ?>
159
- </td>
160
- </tr>
161
- <?php } ?>
162
- </table>
163
- <div class="hints">
164
- Those fields are collected as texts, Newsletter Pro does not give meaning to them, it just stores them.
165
- </div>
166
- </td>
167
- </tr>
168
- </table>
169
- <p class="submit"><?php $nc->button('save', 'Save'); ?></p>
170
-
171
-
172
- <h3>List/Options/Topics</h3>
173
- <p>
174
- Remember that lists are not separate lists of users, they are options chose by subscriber and usually they refer
175
- to topics of your emails.
176
- </p>
177
- <table class="form-table">
178
- <tr>
179
- <th>Lists/Options</th>
180
- <td>
181
- <table class="widefat">
182
- <thead>
183
- <tr>
184
- <th>Field</th><th>When/Where</th><th>Configuration</th>
185
- </tr>
186
- </thead>
187
- <?php for ($i=1; $i<=9; $i++) { ?>
188
- <tr><td>List <?php echo $i; ?></td><td><?php $nc->select('list_' . $i . '_status', $status); ?></td><td>label: <?php $nc->text('list_' . $i); ?></td></tr>
189
- <?php } ?>
190
- </table>
191
- <div class="hints">
192
- Disabled lists are not selectable by users but they can be assigned from admin panels, so they can be
193
- considered as private lists.
194
- </div>
195
- </td>
196
- </tr>
197
- </table>
198
- <p class="submit"><?php $nc->button('save', 'Save'); ?></p>
199
-
200
-
201
- </form>
202
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,57 +1,39 @@
1
-
2
  === Newsletter ===
3
- Tags: newsletter,email,subscription,mass mail
4
- Requires at least: 2.8
5
- Tested up to: 3.3.1
6
  Stable tag: trunk
7
- Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2545483
8
- Contributors: satollo
9
 
10
- Add a real newsletter service to your blog. In seconds. For free.
11
 
12
  == Description ==
13
 
14
- This plug-in lets you to collect subscribers on your blog with a single or double opt-in
15
- subscription process. Double opt-in is law compliant and it means the user has to confirm the subscription
16
- following simple standard instructions sent to him via email.
17
-
18
- Newsletter 2.5 works.
19
-
20
- Take the time to read the user guide, to configure
21
- it as if it would be a new installed plug-in, to enter the subscription form panel and
22
- configure it. Read the user guide about WordPress cron system and how it can affect
23
- the sending process. If you need to translate the subscription form, use the
24
- subscription form panel, please, do not hack the language files, they are
25
- used only on activation. On some WordPress installations the automatic update does not
26
- trigger the activation process. It's important, so try to deactivate and reactivate the
27
- plug-in if it does not saves e-mails. If you update manually uploading the plug-in
28
- with FTP, deactivate it first and the reactivate.
29
-
30
- Please, DO NOT hack the plug-in files and then, when things go wrong, try to solve
31
- the problem writing me... I have no time to answer to all. Reinstall if you're in doubt
32
- about the plug-in integrity.
33
 
34
- Thank you.
35
 
36
- Each step of subscribe and cancel process is fully configurable and translatable.
37
 
38
- Subscription form and profile form are easily configurable from administrative panels and you
39
- can translate every single label in your language.
 
 
 
 
 
 
 
 
 
40
 
41
- Create e-mails with a visual editor with the auto compose function which extract content
42
- for your blog. Auto composer themes can be customized.
43
 
44
- Use the widget to let users to subscribe from anywhere in your blog or use a short code
45
- to embed the subscription form on posts and pages.
46
 
47
- Use the locked content feature to fire up the subscription rate.
48
-
49
- Any option has a "hints" box with instruction to set it and the full user guide is
50
- inside the administrative panels.
51
-
52
- Version 2.5 is a major update and need to be reconfigured! Pay attention.
53
-
54
- More about Newsletter plug-in official page (http://www.satollo.net/plugins/newsletter).
55
 
56
  == Installation ==
57
 
@@ -61,7 +43,12 @@ More about Newsletter plug-in official page (http://www.satollo.net/plugins/news
61
 
62
  == Frequently Asked Questions ==
63
 
64
- None.
 
 
 
 
 
65
 
66
  == Screen shots ==
67
 
@@ -69,100 +56,136 @@ No screen shots are available at this time.
69
 
70
  == Changelog ==
71
 
72
- = 2.5.2.7 =
73
-
74
- * Fixed the profile save redirector on blogs without permalinks
75
-
76
- = 2.5.2.6 =
77
-
78
- * Fix the new test subscriber extraction
79
 
80
- = 2.5.2.5 =
81
 
82
- * Added the "test" flag on subscriber so a real subscriber can be used while sending test emails
83
- * Upgraded tinymce
84
- * Graphical button for submit
85
- * Emails like aaa@q.com are now accepted
86
 
87
- = 2.5.2.4 =
88
 
89
- * Import now consider 19 fields after the last name as extended profile data
90
- * A possible fix for better concurrency management while sending
91
 
92
- = 2.5.2.3 =
93
-
94
- * Fixed extra field of type "list" not showing up correctly (when more than one)
95
- * removed the collapsed sub panel on some configuration panel (people did not realized that a click would open them)
96
- * fixed the unconfirmed status display on users panel
97
- * fixed the status list on user edit panel
98
 
99
- = 2.5.2.2 =
100
 
101
- * removed the backtrace on log (some PHP installations have problems with it)
102
 
103
- = 2.5.2.1 =
104
 
105
- * fixed an error on subscriber panels claiming an unexisting table
 
 
 
106
 
107
- = 2.5.2 =
108
 
109
- * important change on subscription confirmation and unsubscription confirmation to avoid multiple emails
110
- * number of subscriber overview on subscriber panel
111
- * fix on profile form showing "no user"
 
 
 
 
 
 
 
 
 
 
112
 
113
- = 2.5.1.7 =
114
 
115
- * fixed the widget which was no showing the lists and extra fields
 
 
 
116
 
117
- = 2.5.1.6 =
118
 
119
- * fixed {unlock_url} tag
 
120
 
121
- = 2.5.1.5 =
122
 
123
- * fixed issues on multi email sending
124
- * main configuration panel all options open because people was missing to expand panels
125
- * subscriber panel does not more show up the full list on first open
126
  * fixed privacy check box on widget
127
 
128
- = 2.5.1.4 =
129
-
130
- * fixed a missing form element on subscriber list panel that caused some buttons to not work
131
-
132
- = 2.5.1.3 =
133
 
134
  * added compatibility with lite cache
135
  * fixed the list checkboxes on user edit panel
136
  * removed the 100 users limit on search panel
 
137
 
138
- = 2.5.1.2 =
139
 
140
- * fixed unsubscription administrator notifications
 
141
  * replaced sex with gender in notification emails
142
  * fixed the confirm/unconfirm button on user list
143
  * fixed some labels
144
- * subscription form html
145
 
146
-
147
- = 2.5.1.1 =
148
 
149
  * added {date} tag and {date_'format'} tag, where 'format' can be any of the PHP date formats
150
  * added {blog_description} tag
 
 
151
  * updated custom forms documentation
152
- * fixed extended subscriber profile collection
153
-
154
- = 2.5.1 =
155
-
156
- * Improved documentation about delivery engine, WordPress cron and multisite
157
- * New button to force a run of the delivery engine
158
- * Fixed images on theme 1
159
- * Fixed the widget field check
160
- * Renamed panel "user profile" in "subscription form" (since no one read the user guide.. may be due to my bad English... :-)
161
- * Updated theme documentation
162
- * Reintroduced theme CSS
163
- * Added CDATA on JavaScript
164
- * Added theme 3
165
-
166
- = 2.5.0 =
167
-
168
- * first major release after 1.5.9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  === Newsletter ===
2
+ Tags: newsletter,email,subscription,mass mail,list build,email marketing,direct mailing
3
+ Requires at least: 3.0.0
4
+ Tested up to: 3.4.2
5
  Stable tag: trunk
6
+ Donate link: http://www.satollo.net/donations
 
7
 
8
+ Add a real newsletter to your blog. In seconds. For free.
9
 
10
  == Description ==
11
 
12
+ This plug-in lets you collect subscribers on your blog with a single or double opt-in (law compliant)
13
+ subscription process. Perfect for list building, you can create cool emails with visual editor, send and
14
+ track them.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ Unlimited subscribers, unlimited emails.
17
 
18
+ Key features:
19
 
20
+ * unlimited subscribers (the database is your, why should I limit you?)
21
+ * unlimited emails
22
+ * single and double opt-in plus privacy acceptance checkbox (as per European laws)
23
+ * subscriber preferences to fine target your campaigns
24
+ * SMTP ready
25
+ * html and text version messages
26
+ * a real delivery engine to manage huge lists with configurable speed
27
+ * configurable themes
28
+ * easy to develop themes (for coders)
29
+ * every message fully translatable from administrative panels
30
+ * diagnostic panel
31
 
32
+ Visit the [Newsletter official page](http://www.satollo.net/plugins/newsletter).
 
33
 
34
+ Previous version is available [here](http://www.satollo.net/wp-content/uploads/newsletter-2.5.2.7.zip).
 
35
 
36
+ Thank you, Stefano Lissa (Satollo).
 
 
 
 
 
 
 
37
 
38
  == Installation ==
39
 
43
 
44
  == Frequently Asked Questions ==
45
 
46
+ See the [Newsletter FAQ](http://www.satollo.net/plugins/newsletter/newsletter-faq) or the
47
+ [Newsletter Forum](http://www.satollo.net/forums).
48
+
49
+ For documentation start from [Newsletter official page](http://www.satollo.net/plugins/newsletter).
50
+
51
+ Thank you, Stefano Lissa (Satollo).
52
 
53
  == Screen shots ==
54
 
56
 
57
  == Changelog ==
58
 
59
+ = 3.0.0 =
 
 
 
 
 
 
60
 
61
+ * Release
62
 
63
+ = 2.6.2 =
 
 
 
64
 
65
+ * Added the user massive management panel
66
 
67
+ = 2.5.3.3 =
 
68
 
69
+ * Updated to 20 lists instead of 9
70
+ * Max lists can be set on wp-config.php with define('NEWSLETTER_LIST_MAX', [number])
71
+ * Default preferences ocnfigurable on subscription panel
 
 
 
72
 
73
+ = 2.5.3.2 =
74
 
75
+ * fixed the profile fields generation on subscription form
76
 
77
+ = 2.5.3.1 =
78
 
79
+ * fixed javascript email check
80
+ * fixed rewrite of link that are anchors
81
+ * possible patch to increase concurrency detection while sending
82
+ * fixed warning message on email composer panel
83
 
84
+ = 2.5.3 =
85
 
86
+ * changed the confirmation and cancellation URLs to a direct call to Newsletter Pro to avoid double emails
87
+ * mail opening now tracked
88
+ * fixed the add api
89
+ * feed by mail settings added: categories and max posts
90
+ * feed by mail themes change to use the new settings
91
+ * unsubscribed users are marked as unsubscribed and not removed
92
+ * api now respect follow up and feed by mail subscription options
93
+ * fixed the profile form to add the user id and token
94
+ * subscribers' panel changed
95
+ * optimizations
96
+ * main url fixed everywhere
97
+ * small changes to the email composer
98
+ * small changes to the blank theme
99
 
100
+ = 2.5.2.3 =
101
 
102
+ * subscribers panel now show the profile data
103
+ * search can be ordered by profile data
104
+ * result limit on search can be specified
105
+ * {unlock_url} fixed (it was not pointing to the right configured url)
106
 
107
+ = 2.5.2.2 =
108
 
109
+ * fixed the concurrent email sending problem
110
+ * added WordPress media gallery integration inside email composer
111
 
112
+ = 2.5.2.1 =
113
 
114
+ * added the add_user method
115
+ * fixed the API (was not working) and added multilist on API (thankyou betting-tips-uk.com)
 
116
  * fixed privacy check box on widget
117
 
118
+ = 2.5.2 =
 
 
 
 
119
 
120
  * added compatibility with lite cache
121
  * fixed the list checkboxes on user edit panel
122
  * removed the 100 users limit on search panel
123
+ * category an max posts selection on email composer
124
 
125
+ = 2.5.1.5 =
126
 
127
+ * improved the url tag replacement for some particular blog installation
128
+ * fixed the unsubscription administrator notification
129
  * replaced sex with gender in notification emails
130
  * fixed the confirm/unconfirm button on user list
131
  * fixed some labels
132
+ * subscription form table HTML
133
 
134
+ = 2.5.1.4 =
 
135
 
136
  * added {date} tag and {date_'format'} tag, where 'format' can be any of the PHP date formats
137
  * added {blog_description} tag
138
+ * fixed the feed reset button
139
+ * added one day back button to the feed
140
  * updated custom forms documentation
141
+ * fixed the trigger button on emails panel
142
+ * changed both feed by mail themes (check them if you create your own theme)
143
+ * fixed the custom profile field generation (important!)
144
+ * fixed documentation about custom forms
145
+
146
+ Version 2.5.1.3
147
+ - fix the feed email test id (not important, it only generates PHP error logs)
148
+ - feed by mail send now now force the sending if in a non sending day
149
+ - changed the way feed by mail themes extract the posts: solves the sticky posts problem
150
+ - added the feed last check time reset button
151
+ - fixed the confirm and cancel buttons on user list
152
+ - fixed the welcome email when using a custom thank you page
153
+ - added images to theme 1
154
+ - added button to trigger the delivery engine
155
+ - fixed the widget mail check
156
+ - reintroduced style.css for themes
157
+ - updated theme documentation
158
+ - added CDATA on JavaScript
159
+ - fixed theme 1 which was not adding the images
160
+ - added theme 3
161
+
162
+ Version 2.5.1.2
163
+ - fixed the old profile fields saving
164
+
165
+ Version 2.5.1.1
166
+ - new fr_FR file
167
+ - fixed test of SMTP configuration which was sending to test address 2 instead of test address 1
168
+ - bounced voice remove on search filter
169
+ - added action "of" which return only the subscription form and fire a subcription of type "os"
170
+ - added action "os" that subscribe the user and show only the welcome/confirmation required message
171
+ - fixed issue with main page url configuration
172
+
173
+ Version 2.5.1
174
+ - Fixed the widget that was not using the extended fields
175
+ - Fixed the widget that was not using the lists
176
+ - Added the class "newsletter-profile" and "newsletter-profile-[number]" to the widget form
177
+ - Added the class "newsletter-profile" and "newsletter-profile-[number]" to the main subscription form
178
+ - Added the class "newsletter-profile" and "newsletter-profile-[number]" to the profile form
179
+ - Added the classes "newsletter-email", "newsletter-firstname", "newsletter-surname" to the respective fields on every form
180
+ - Removed email theme option on subscription panel (was not used)
181
+ - Fixed the welcome email on double opt in process
182
+ - Subscription notifications to admin only for confirmed subscription
183
+ - Fixed subscription process panel for double opt in (layout problems)
184
+ - Improved subscription process panel
185
+
186
+
187
+ Version 2.5.0.1
188
+ - Fix unsubscription process not working
189
+
190
+ Version 2.5.0
191
+ - Official first release
statistics/1x1.gif ADDED
Binary file
statistics/index.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $module = NewsletterStatistics::instance();
4
+ $controls = new NewsletterControls();
5
+ $emails = Newsletter::instance()->get_emails();
6
+
7
+ if ($controls->is_action('save')) {
8
+ $module->save_options($controls->data);
9
+ $controls->messages = 'Saved.';
10
+ }
11
+ ?>
12
+
13
+ <div class="wrap">
14
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/statistics-module'; ?>
15
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
16
+ <h2>Statistics Module</h2>
17
+ <p><em>This is a brief introduction waiting for an official page.</em></p>
18
+ <p>
19
+ The Newsletter Statistics Module adds to Newsletter the ability to collect messages opening and link clicks on
20
+ those messages.
21
+ </p>
22
+ <p>
23
+ Statistic data is collected per email, so on panels listing emals there should always be a "statistics" button
24
+ which leads to the analytics panel for that email.
25
+ </p>
26
+
27
+ <h3>Summary of collected data</h3>
28
+ <p><em>To do...</em></p>
29
+ <table class="widefat" style="width: auto">
30
+ <thead>
31
+ <tr>
32
+ <th>Parameter</th>
33
+ <th>Value</th>
34
+ </tr>
35
+ </thead>
36
+
37
+ <tbody>
38
+ <tr>
39
+ <td>Total email sent</td>
40
+ <td>-</td>
41
+ </tr>
42
+ <tr>
43
+ <td>Total clicks</td>
44
+ <td>-</td>
45
+ </tr>
46
+ <tr>
47
+ <td>Total unique users which read or clicked</td>
48
+ <td>-</td>
49
+ </tr>
50
+ </tbody>
51
+ </table>
52
+
53
+
54
+ </div>
statistics/link.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include '../../../../wp-load.php';
4
+
5
+ list($email_id, $user_id, $url, $anchor) = explode(';', base64_decode($_GET['r']), 4);
6
+ $wpdb->insert(NEWSLETTER_STATS_TABLE,
7
+ array(
8
+ 'email_id' => $email_id,
9
+ 'user_id' => $user_id,
10
+ 'url' => $url,
11
+ 'anchor' => $anchor
12
+ )
13
+ );
14
+
15
+ header('Location: ' . $url);
statistics/open.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once '../../../../wp-load.php';
4
+
5
+ list($email_id, $user_id) = explode(';', base64_decode($_GET['r']), 2);
6
+
7
+ // TODO: Create a service inside store o newsletter statistics
8
+ $wpdb->insert(NEWSLETTER_STATS_TABLE, array(
9
+ 'email_id' => $email_id,
10
+ 'user_id' => $user_id,
11
+ )
12
+ );
13
+
14
+ header('Content-Type: image/gif');
15
+ readfile(dirname(__FILE__) . '/1x1.gif');
16
+ die();
17
+
statistics/statistics.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
4
+
5
+ class NewsletterStatistics extends NewsletterModule {
6
+
7
+ const VERSION = '1.0.2';
8
+
9
+ static $instance;
10
+
11
+ /**
12
+ * @return NewsletterStatistics
13
+ */
14
+ static function instance() {
15
+ if (self::$instance == null) {
16
+ self::$instance = new NewsletterStatistics();
17
+ }
18
+ return self::$instance;
19
+ }
20
+
21
+ function __construct() {
22
+ parent::__construct('statistics', self::VERSION);
23
+ }
24
+
25
+ function upgrade() {
26
+ global $wpdb, $charset_collate;
27
+
28
+
29
+ // This before table creation or update for compatibility
30
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats change column newsletter_id user_id int not null default 0");
31
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats change column newsletter_id user_id int not null default 0");
32
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats change column date created timestamp not null default current_timestamp");
33
+
34
+ // Just for test since it will be part of statistics module
35
+ // This table stores clicks and email opens. An open is registered with a empty url.
36
+ $this->upgrade_query("create table if not exists {$wpdb->prefix}newsletter_stats (id int auto_increment, primary key (id)) $charset_collate");
37
+
38
+ // References
39
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column user_id int not null default 0");
40
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column email_id int not null default 0");
41
+ // Future... see the links table
42
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column link_id int not null default 0");
43
+
44
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column user_id int not null default 0");
45
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column created timestamp not null default current_timestamp");
46
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column url varchar(255) not null default ''");
47
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_stats add column anchor varchar(200) not null default ''");
48
+
49
+ // Stores the link of every email to create short links
50
+ $this->upgrade_query("create table if not exists {$wpdb->prefix}newsletter_links (id int auto_increment, primary key (id)) $charset_collate");
51
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_links add column email_id int not null default 0");
52
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_links add column token varchar(10) not null default ''");
53
+ $this->upgrade_query("alter table {$wpdb->prefix}newsletter_links add column text varchar(255) not null default ''");
54
+ }
55
+
56
+ function relink($text, $email_id, $user_id) {
57
+ $this->relink_email_id = $email_id;
58
+ $this->relink_user_id = $user_id;
59
+ $text = preg_replace_callback('/(<[aA][^>]+href=["\'])([^>"\']+)(["\'][^>]*>)(.*?)(<\/[Aa]>)/', array($this, 'relink_callback'), $text);
60
+
61
+ // TODO: use the WP rewriting
62
+ $text = str_replace('</body>', '<img src="' . NEWSLETTER_URL . '/statistics/open.php?r=' . urlencode(base64_encode($email_id . ';' . $user_id)) . '"/></body>', $text);
63
+ return $text;
64
+ }
65
+
66
+ function relink_callback($matches) {
67
+ // Do not replace the tracking or subscription/unsubscription links.
68
+ if (strpos($href, '/newsletter/') !== false) return $matches[0];
69
+ if (substr($href, 0, 1) == '#') return $matches[0];
70
+ $href = str_replace('&amp;', '&', $matches[2]);
71
+
72
+ $anchor = '';
73
+ if ($this->options['anchor'] == 1) {
74
+ $anchor = trim(str_replace(';', ' ', $matches[4]));
75
+ $anchor = strip_tags($anchor, '<img>');
76
+ if (stripos($anchor, '<img') === false && strlen($anchor) > 100) {
77
+ $anchor = substr($anchor, 0, 100);
78
+ }
79
+ }
80
+
81
+ $url = NEWSLETTER_URL . '/statistics/link.php?r=' .
82
+ urlencode(base64_encode($this->relink_email_id . ';' . $this->relink_user_id . ';' . $href . ';' . $anchor));
83
+
84
+ return $matches[1] . $url . $matches[3] . $matches[4] . $matches[5];
85
+ }
86
+
87
+ function get_statistics_url($email_id) {
88
+ return 'admin.php?page=newsletter_statistics_view&amp;id=' . $email_id;
89
+ }
90
+
91
+ function get_read_count($email_id) {
92
+ global $wpdb;
93
+ $email_id = (int) $email_id;
94
+ return (int) $wpdb->get_var("select count(distinct user_id) from " . NEWSLETTER_STATS_TABLE . " where email_id=" . $email_id);
95
+ }
96
+
97
+ }
98
+
99
+ add_action('newsletter_admin_menu', 'newsletter_statistics_admin_menu');
100
+
101
+ /**
102
+ * Add menu pages for this module.
103
+ * @global Newsletter $newsletter
104
+ */
105
+ function newsletter_statistics_admin_menu() {
106
+ global $newsletter;
107
+ $newsletter->add_menu_page('statistics', 'index', 'Statistics');
108
+ $newsletter->add_admin_page('statistics', 'view', 'Statistics');
109
+ }
110
+
statistics/view.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $module = NewsletterStatistics::instance();
3
+ $email = Newsletter::instance()->get_email($_GET['id']);
4
+ ?>
5
+ <div class="wrap">
6
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/statistics-module'; ?>
7
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
8
+
9
+ <h2>Statistics Module</h2>
10
+
11
+ <h3><?php echo esc_html($email->subject); ?></h3>
12
+
13
+ <table class="widefat" style="width: auto">
14
+ <thead>
15
+ <tr>
16
+ <td>Field</td>
17
+ <td>Value</td>
18
+ </tr>
19
+ </thead>
20
+
21
+ <tbody>
22
+ <tr>
23
+ <td>Total sent</td>
24
+ <td><?php echo $email->sent; ?></td>
25
+ </tr>
26
+ <tr>
27
+ <td>Email open</td>
28
+ <td><?php echo $module->get_read_count($email->id); ?></td>
29
+ </tr>
30
+ </tbody>
31
+ </table>
32
+ </div>
style.css DELETED
@@ -1,128 +0,0 @@
1
- .wrap h3
2
- {
3
- margin-bottom: 0px;
4
- margin-top: 40px;
5
- font-family: Georgia;
6
- font-size: 20px;
7
- font-style: italic;
8
- font-weight: normal;
9
- cursor: pointer;
10
- cursor: hand;
11
- }
12
- h4 {
13
- font-size: 1.1em;
14
- font-weight: bold;
15
- font-family: Georgia;
16
- font-style: italic;
17
- /* border-bottom: 1px solid #999;*/
18
- }
19
- .form-table {
20
- xborder: 1px solid #ccc;
21
- background-color: #fff;
22
- border: 3px solid #ddd;
23
- }
24
-
25
- .form-table th {
26
- text-align: right;
27
- font-weight: bold;
28
- border-right: 1px solid #ddd;
29
- }
30
- .form-table th small {
31
- font-weight: normal;
32
- }
33
-
34
- .widefat th {
35
- text-align: left;
36
- }
37
-
38
-
39
- p.submit {
40
- margin-top: 5px;
41
- padding: 5px;
42
- }
43
-
44
- .bordered-table {
45
- border-collapse: collapse;
46
- }
47
-
48
- .bordered-table td, .bordered-table th {
49
- border: 1px solid #ccc;
50
- padding: 3px;
51
- }
52
-
53
- .newsletter-button {
54
- font-size: 10px;
55
- }
56
- table.clicks td {
57
- border: 1px solid #666;
58
- padding: 2px;
59
- font-size: 10px;
60
- }
61
-
62
- table.clicks {
63
- border-collapse: collapse;
64
- }
65
-
66
- .grid {
67
- border-collapse: collapse;
68
- }
69
- .grid td, .grid th {
70
- padding: 10px;
71
- border: 1px solid #ddd;
72
- margin: 0;
73
- }
74
- .grid th {
75
- background-color: #aaa;
76
- }
77
-
78
- .form-table textarea {
79
- width: 100%;
80
- }
81
-
82
- .hints {
83
- border: 1px solid #aaf;
84
- background-color: #fafaff;
85
- padding: 5px;
86
- margin-top: 10px;
87
- border-radius: 4px 4px;
88
- -moz-border-radius: 4px;
89
- -webkit-border-radius: 4px;
90
- }
91
-
92
- .intro {
93
- font-size: 11px;
94
- margin: 6px 6px 8px;
95
- }
96
-
97
- .inside p, .inside li {
98
- font-size: 12px;
99
- margin: 10px;
100
- }
101
-
102
- .inside ul {
103
- list-style-type: circle;
104
- list-style-position: inside;
105
- }
106
-
107
- .nl-box {
108
- border-bottom-left-radius: 4px 4px;
109
- border-bottom-right-radius: 4px 4px;
110
- border-top-left-radius: 4px 4px;
111
- border-top-right-radius: 4px 4px;
112
- border: 1px solid #aaf;
113
- background-color: #fff;
114
- }
115
-
116
- .user-guide {
117
- background-color: #fff;
118
- border: 1px solid #000;
119
- padding: 20px;
120
- font-family: verdana;
121
- line-height: 20px;
122
- font-size: 12px;
123
- }
124
-
125
- .user-guide ul {
126
- list-style-type: disc;
127
- margin-left: 20px;
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
subscription/email-alternative.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // TODO: Explain how to customize.
4
+
5
+ ?>
6
+ <html>
7
+ <head>
8
+ <style type="text/css">
9
+ </style>
10
+ </head>
11
+
12
+ <body style="font-family: sans-serif; font-size: 12px">
13
+ <?php echo $message; ?>
14
+ </body>
15
+ </html>
subscription/email.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // TODO: Explain how to customize.
4
+
5
+ if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/subscription/email.php')) {
6
+ include WP_CONTENT_DIR . '/extensions/newsletter/subscription/email.php';
7
+ die();
8
+ }
9
+
10
+ ?>
11
+ <!DOCTYPE html>
12
+ <html>
13
+ <head>
14
+ <style type="text/css" media="all">
15
+ a {
16
+ text-decoration: none;
17
+ color: #0088cc;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body style="background-color: #ddd; font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 14px; color: #666; margin: 0 auto; padding: 0;">
22
+ <br>
23
+ <table align="center">
24
+ <tr>
25
+ <td style="font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 14px; color: #666;">
26
+ <div style="text-align: left; max-width: 500px; border-top: 10px solid #43A4D0; border-bottom: 3px solid #43A4D0;">
27
+ <div style="padding: 10px 20px; color: #000; font-size: 20px; background-color: #EFEFEF; border-bottom: 1px solid #ddd">
28
+ <?php echo get_option('blogname'); ?>
29
+ </div>
30
+ <div style="padding: 20px; background-color: #fff; line-height: 18px">
31
+
32
+ <?php echo $message; ?>
33
+
34
+ </div>
35
+
36
+ </div>
37
+ </td>
38
+ </tr>
39
+ </table>
40
+ </body>
41
+ </html>
subscription/forms.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $controls = new NewsletterControls();
4
+
5
+ if (!$controls->is_action()) {
6
+ $controls->data = get_option('newsletter_forms');
7
+ }
8
+
9
+ if ($controls->is_action('save')) {
10
+ update_option('newsletter_forms', $controls->data);
11
+ $controls->messages = 'Saved';
12
+ }
13
+ ?>
14
+
15
+ <div class="wrap">
16
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/newsletter-forms'; ?>
17
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
18
+
19
+ <?php include NEWSLETTER_DIR . '/subscription/menu.inc.php'; ?>
20
+
21
+ <?php $controls->show(); ?>
22
+
23
+ <div class="preamble">
24
+ <p>
25
+ Here you can store your hand coded forms to recall them from short codes.
26
+ <a href="http://www.satollo.net/plugins/newsletter/newsletter-forms" target="_blank">Read more about forms</a>.
27
+ </p>
28
+ </div>
29
+
30
+ <form method="post" action="">
31
+ <?php $controls->init(); ?>
32
+
33
+ <div id="tabs">
34
+
35
+ <ul>
36
+ <li><a href="#tabs-1">Forms</a></li>
37
+ </ul>
38
+
39
+ <div id="tabs-1">
40
+ <table class="form-table">
41
+ <?php for ($i = 1; $i <= 10; $i++) { ?>
42
+ <tr valign="top">
43
+ <th>Form <?php echo $i; ?></th>
44
+ <td>
45
+ <?php $controls->textarea('form_' . $i); ?>
46
+ <br />
47
+ <?php $controls->button('save', 'Save'); ?>
48
+ </td>
49
+ </tr>
50
+ <?php } ?>
51
+ </table>
52
+ </div>
53
+
54
+ </div>
55
+ </form>
56
+
57
+ </div>
{languages → subscription/languages}/de_DE.php RENAMED
@@ -1,28 +1,19 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'Falsche Email-Adresse.';
5
- $defaults_profile['name_error'] = 'Das Feld für Ihren namen darf nicht leer sein.';
6
 
7
-
8
- $defaults = array();
9
- // Subscription page introductory text (befor the subscription form)
10
- $defaults['subscription_text'] =
11
- "<p>Um unseren Newsletter zu erhalten f&uuml;llen Sie das folgende Formular aus.</p>
12
- <p>Sie erhalten eine Best&auml;tigungs-Email an Ihre Email-Adresse:
13
- bitte folgen Sie den Anweisungen um Ihre Anmeldung zu vollenden.</p>";
14
 
15
  // Message show after a subbscription request has made.
16
- $defaults['subscribed_text'] =
17
  "<p>Sie haben sich in unseren Newsletter eingetragen.
18
  In wenigen Minuten erhalten Sie eine Best&auml;tigungs-Email. Folgen Sie dem Link um die Anmeldung zu best&auml;tigen. Sollte die Email nicht innerhalb der n&auml;chsten 15 Minuten in Ihrem Posteingang erscheinen, &uuml;berpr&uuml;fen Sie Ihren Spam-Ordner.</p>";
19
 
20
  // Confirmation email subject (double opt-in)
21
- $defaults['confirmation_subject'] =
22
  "{name},{blog_title} Newsletter - hier Anmeldebest&auml;tigung";
23
 
24
  // Confirmation email body (double opt-in)
25
- $defaults['confirmation_message'] =
26
  "<p>Hallo {name},</p>
27
  <p>Für diese Email-Adresse haben wir eine Anmeldung zu unserem Newsletter erhalten. Sie k&ouml;nnen diese Anmeldung best&auml;tigen, in dem Sie <a href=\"{subscription_confirm_url}\"><strong>hier klicken</strong></a>.
28
  Wenn Sie nicht klicken k&ouml;nnen, nutzen Sie die folgenden URL in Ihren Browser ein:</p>
@@ -33,14 +24,14 @@ Wenn Sie nicht klicken k&ouml;nnen, nutzen Sie die folgenden URL in Ihren Browse
33
 
34
  // Subscription confirmed text (after a user clicked the confirmation link
35
  // on the email he received
36
- $defaults['confirmed_text'] =
37
  "<p>Ihre Anmeldung zu unserem Newsletter wurde best&auml;tigt!
38
  Herzlichen Dank!</p>";
39
 
40
- $defaults['confirmed_subject'] =
41
  "{blog_title} Newsletter - Willkommen";
42
 
43
- $defaults['confirmed_message'] =
44
  "<p>
45
  Hallo {name},
46
  Willkommen zu unserem {blog_title} Newsletter.</p>
@@ -51,11 +42,10 @@ Wenn Sie unseren newsletter nicht mehr erhalten m&ouml;chten, tragen Sie sich bi
51
  <p>Besten Dank!</p>";
52
 
53
  // Unsubscription request introductory text
54
- $defaults['unsubscription_text'] =
55
  "<p>Bitte best&auml;tigen Sie, dass Sie unseren Newsletter abbestellen, indem Sie
56
  <a href=\"{unsubscription_confirm_url}\">hier klicken</a>.";
57
 
58
  // When you finally loosed your subscriber
59
- $defaults['unsubscribed_text'] =
60
  "<p>Herzlichen Dank, Sie wurden aus dem Verteiler entfernt...</p>";
61
- ?>
1
  <?php
2
 
 
 
 
3
 
4
+ $options = array();
 
 
 
 
 
 
5
 
6
  // Message show after a subbscription request has made.
7
+ $options['subscribed_text'] =
8
  "<p>Sie haben sich in unseren Newsletter eingetragen.
9
  In wenigen Minuten erhalten Sie eine Best&auml;tigungs-Email. Folgen Sie dem Link um die Anmeldung zu best&auml;tigen. Sollte die Email nicht innerhalb der n&auml;chsten 15 Minuten in Ihrem Posteingang erscheinen, &uuml;berpr&uuml;fen Sie Ihren Spam-Ordner.</p>";
10
 
11
  // Confirmation email subject (double opt-in)
12
+ $options['confirmation_subject'] =
13
  "{name},{blog_title} Newsletter - hier Anmeldebest&auml;tigung";
14
 
15
  // Confirmation email body (double opt-in)
16
+ $options['confirmation_message'] =
17
  "<p>Hallo {name},</p>
18
  <p>Für diese Email-Adresse haben wir eine Anmeldung zu unserem Newsletter erhalten. Sie k&ouml;nnen diese Anmeldung best&auml;tigen, in dem Sie <a href=\"{subscription_confirm_url}\"><strong>hier klicken</strong></a>.
19
  Wenn Sie nicht klicken k&ouml;nnen, nutzen Sie die folgenden URL in Ihren Browser ein:</p>
24
 
25
  // Subscription confirmed text (after a user clicked the confirmation link
26
  // on the email he received
27
+ $options['confirmed_text'] =
28
  "<p>Ihre Anmeldung zu unserem Newsletter wurde best&auml;tigt!
29
  Herzlichen Dank!</p>";
30
 
31
+ $options['confirmed_subject'] =
32
  "{blog_title} Newsletter - Willkommen";
33
 
34
+ $options['confirmed_message'] =
35
  "<p>
36
  Hallo {name},
37
  Willkommen zu unserem {blog_title} Newsletter.</p>
42
  <p>Besten Dank!</p>";
43
 
44
  // Unsubscription request introductory text
45
+ $options['unsubscription_text'] =
46
  "<p>Bitte best&auml;tigen Sie, dass Sie unseren Newsletter abbestellen, indem Sie
47
  <a href=\"{unsubscription_confirm_url}\">hier klicken</a>.";
48
 
49
  // When you finally loosed your subscriber
50
+ $options['unsubscribed_text'] =
51
  "<p>Herzlichen Dank, Sie wurden aus dem Verteiler entfernt...</p>";
 
subscription/languages/en_US.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Those default options are used ONLY on FIRST setup and on plugin updates but limited to
3
+ // new options that may have been added between your and new version.
4
+ //
5
+ // This is the main language file, too, which is always loaded by Newsletter. Other language
6
+ // files are loaded according the WPLANG constant defined in wp-config.php file. Those language
7
+ // specific files are "merged" with this one and the language specific configuration
8
+ // keys override the ones in this file.
9
+ //
10
+ // Language specific files only need to override configurations containing texts
11
+ // langiage dependant.
12
+
13
+ $options = array();
14
+ $options['profile_text'] = '{profile_form}<p>If you want to cancel your subscription, <a href="{unsubscription_confirm_url}">click here</a></p>';
15
+
16
+ // Subscription page introductory text (befor the subscription form)
17
+ $options['subscription_text'] =
18
+ "{subscription_form}";
19
+
20
+ // Message show after a subbscription request has made.
21
+ $options['subscribed_text'] =
22
+ "<p>You successfully subscribed to my newsletter.
23
+ You'll receive in few minutes a confirmation email. Follow the link
24
+ in it to confirm the subscription. If the email takes more than 15
25
+ minutes to appear in your mailbox, check the spam folder.</p>";
26
+
27
+ // Confirmation email subject (double opt-in)
28
+ $options['confirmation_subject'] =
29
+ "Confirm now your subscription to {blog_title}";
30
+
31
+ // Confirmation email body (double opt-in)
32
+ $options['confirmation_message'] =
33
+ "<p>Hi {name},</p>
34
+ <p>I received a subscription request for this email address. You can confirm it
35
+ <a href=\"{subscription_confirm_url}\"><strong>clicking here</strong></a>.
36
+ If you cannot click the link, use the following link:</p>
37
+ <p>{subscription_confirm_url}</p>
38
+ <p>If this subscription request has not been made from you, just ignore this message.</p>
39
+ <p>Thank you.</p>";
40
+
41
+
42
+ // Subscription confirmed text (after a user clicked the confirmation link
43
+ // on the email he received
44
+ $options['confirmed_text'] =
45
+ "<p>Your subscription has been confirmed!
46
+ Thank you {name}!</p>";
47
+
48
+ $options['confirmed_subject'] =
49
+ "Welcome aboard, {name}";
50
+
51
+ $options['confirmed_message'] =
52
+ "<p>The message confirm your subscription to {blog_title} newsletter.</p>
53
+ <p>Thank you!</p>
54
+ <p>If you want to cancel your unsubscription, <a href=\"{unsubscription_url}\">click here</a>, if you want to change your
55
+ subscription data, <a href=\"{profile_url}\">click here</a>.</p>";
56
+
57
+ // Unsubscription request introductory text
58
+ $options['unsubscription_text'] =
59
+ "<p>Please confirm you want to unsubscribe my newsletter
60
+ <a href=\"{unsubscription_confirm_url}\">clicking here</a>.";
61
+
62
+ // When you finally loosed your subscriber
63
+ $options['unsubscribed_text'] =
64
+ "<p>That make me cry, but I have removed your subscription...</p>";
65
+
66
+ $options['unsubscribed_subject'] =
67
+ "Goodbye, {name}";
68
+
69
+ $options['unsubscribed_message'] =
70
+ "<p>The message confirm your unsubscription to {blog_title} newsletter.</p>
71
+ <p>Good bye!</p>";
{languages → subscription/languages}/es_ES.php RENAMED
@@ -1,30 +1,21 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'Direccion de correo electronico incorrecta.';
5
- $defaults_profile['name_error'] = 'El nombre no puede estar vacio.';
6
-
7
- $defaults = array();
8
- // Suscripcion pagina de introduccion de texto (formulario de suscripcion)
9
- $defaults['subscription_text'] =
10
- "<p>Suscribirse a mi boletín llenando el formulario a continuacion.
11
- Voy a tratar de hacerte feliz.</p>
12
- <p>Un correo de confirmacion será enviado a su buzon de correo:
13
- por favor, lea las instrucciones en su interior para completar la suscripcion.</p>";
14
 
15
  // Mostrar mensaje despues de una solicitud de suscripcion hecha.
16
- $defaults['subscribed_text'] =
17
  "<p>Con exito suscrito a mi boletín informativo.
18
  Usted recibirá en pocos minutos un email de confirmacion. Siga el enlace
19
  en el para confirmar la suscripcion. Si el correo tarda mas de 15
20
  minutos en aparecer en su buzon de correo, revise la carpeta de spam.</p>";
21
 
22
  // Tema de correo electronico de confirmacion (double opt-in)
23
- $defaults['confirmation_subject'] =
24
  "{name}, confirmar su suscripcion a {blog_title}";
25
 
26
  // Cuerpo confirmacion por correo electronico (double opt-in)
27
- $defaults['confirmation_message'] =
28
  "<p>Hola {name},</p>
29
  <p>He recibido una solicitud de suscripcion para esta direccion de correo electronico. Usted puede confirmar:
30
  <a href=\"{subscription_confirm_url}\"><strong>click aquí</strong></a>.
@@ -36,30 +27,30 @@ Si usted no puede hacer click en el enlace, utilice el siguiente enlace:</p>
36
 
37
  // Suscripcion confirmacion texto (despues de que un usuario hace clic en el enlace de confirmacion
38
  // en el correo electronico que recibira
39
- $defaults['confirmed_text'] =
40
  "<p>Su suscripcion se ha confirmado!
41
  Gracias {name}!</p>";
42
 
43
- $defaults['confirmed_subject'] =
44
  "Bienvenido a bordo, {name}";
45
 
46
- $defaults['confirmed_message'] =
47
  "<p>El mensaje de confirmar su suscripcion a {blog_title} newsletter.</p>
48
  <p>Gracias!</p>";
49
 
50
  // Darse de baja de la solicitud introduccion de texto
51
- $defaults['unsubscription_text'] =
52
  "<p>Por favor, confirme que desea darse de baja mi boletín de noticias
53
  <a href=\"{unsubscription_confirm_url}\">click aquí</a>.";
54
 
55
 
56
- $defaults['unsubscribed_text'] =
57
  "<p>Me hace llorar, pero he quitado su suscripcion ...</p>";
58
 
59
- $defaults['unsubscribed_subject'] =
60
  "Adios, {name}";
61
 
62
- $defaults['unsubscribed_message'] =
63
  "<p>Mensaje de confirmacion de su baja en {blog_title} Boletín de noticias.</p>
64
  <p>Adios!</p>";
65
 
1
  <?php
2
 
3
+
4
+ $options = array();
 
 
 
 
 
 
 
 
 
5
 
6
  // Mostrar mensaje despues de una solicitud de suscripcion hecha.
7
+ $options['subscribed_text'] =
8
  "<p>Con exito suscrito a mi boletín informativo.
9
  Usted recibirá en pocos minutos un email de confirmacion. Siga el enlace
10
  en el para confirmar la suscripcion. Si el correo tarda mas de 15
11
  minutos en aparecer en su buzon de correo, revise la carpeta de spam.</p>";
12
 
13
  // Tema de correo electronico de confirmacion (double opt-in)
14
+ $options['confirmation_subject'] =
15
  "{name}, confirmar su suscripcion a {blog_title}";
16
 
17
  // Cuerpo confirmacion por correo electronico (double opt-in)
18
+ $options['confirmation_message'] =
19
  "<p>Hola {name},</p>
20
  <p>He recibido una solicitud de suscripcion para esta direccion de correo electronico. Usted puede confirmar:
21
  <a href=\"{subscription_confirm_url}\"><strong>click aquí</strong></a>.
27
 
28
  // Suscripcion confirmacion texto (despues de que un usuario hace clic en el enlace de confirmacion
29
  // en el correo electronico que recibira
30
+ $options['confirmed_text'] =
31
  "<p>Su suscripcion se ha confirmado!
32
  Gracias {name}!</p>";
33
 
34
+ $options['confirmed_subject'] =
35
  "Bienvenido a bordo, {name}";
36
 
37
+ $options['confirmed_message'] =
38
  "<p>El mensaje de confirmar su suscripcion a {blog_title} newsletter.</p>
39
  <p>Gracias!</p>";
40
 
41
  // Darse de baja de la solicitud introduccion de texto
42
+ $options['unsubscription_text'] =
43
  "<p>Por favor, confirme que desea darse de baja mi boletín de noticias
44
  <a href=\"{unsubscription_confirm_url}\">click aquí</a>.";
45
 
46
 
47
+ $options['unsubscribed_text'] =
48
  "<p>Me hace llorar, pero he quitado su suscripcion ...</p>";
49
 
50
+ $options['unsubscribed_subject'] =
51
  "Adios, {name}";
52
 
53
+ $options['unsubscribed_message'] =
54
  "<p>Mensaje de confirmacion de su baja en {blog_title} Boletín de noticias.</p>
55
  <p>Adios!</p>";
56
 
{languages → subscription/languages}/fr_FR.php RENAMED
@@ -1,27 +1,19 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'E-mail incorrect.';
5
- $defaults_profile['name_error'] = 'Merci d&prime;indiquer votre nom.';
6
-
7
- $defaults = array();
8
- // Subscription page introductory text (befor the subscription form)
9
- $defaults['subscription_text'] =
10
- "<p>Abonnez-vous &agrave; la lettre d&prime;information {blog_title} en remplissants le formulaire ci-dessous.</p>
11
- <p>Un e-mail de confirmation vous sera envoyé.</p>";
12
 
13
  // Message show after a subbscription request has made.
14
- $defaults['subscribed_text'] =
15
  "<p>Votre demande d'inscription est enregistr&eacute;e. Merci ! Un e-mail de confirmation vous a été envoyé. V&eacute;rifier &eacute;galement votre dossier spam.</p>";
16
 
17
  // Confirmation email subject (double opt-in)
18
- $defaults['confirmation_subject'] =
19
- "Inscription &agrave; la lettre d&prime;information {blog_title}";
20
 
21
  // Confirmation email body (double opt-in)
22
- $defaults['confirmation_message'] =
23
  "<p>Bonjour {name}!</p>
24
- <p>Vous recevez cet e-mail car nous avons enregistr&eacute; une demande d&prime;inscription &agrave; la lettre d&prime;infrmation {blog_title}.
25
  Merci de confirmer votre inscription en cliquant sur le lien suivant : <a href=\"{subscription_confirm_url}\"><strong>je confirme mon inscription.</strong></a>.
26
  Si le lien ne fonctionne pas, merci d'utiliser cette adresse :</p>
27
  <p>{subscription_confirm_url}</p>
@@ -31,22 +23,22 @@ Si le lien ne fonctionne pas, merci d'utiliser cette adresse :</p>
31
 
32
  // Subscription confirmed text (after a user clicked the confirmation link
33
  // on the email he received
34
- $defaults['confirmed_text'] =
35
- "<p>Votre inscription est confirm&eacute;. Merci !</p>";
36
 
37
- $defaults['confirmed_subject'] =
38
  "Bienvenue, {name}";
39
 
40
- $defaults['confirmed_message'] =
41
- "<p>Votre inscription est confirm&eacute;. Merci !</p>";
42
 
43
  // Unsubscription request introductory text
44
- $defaults['unsubscription_text'] =
45
- "<p>&Ecirc;tes-vous certain de vouloir vous d&eacute;sinscrire de la lettre d&prime;information {blog_title} ? <a href=\"{unsubscription_confirm_url}\">Oui</a>.";
46
 
47
  // When you finally loosed your subscriber
48
- $defaults['unsubscribed_text'] =
49
- "<p>Vous n&prime;&ecirc;tes plus abonn&eacute; &agrave; la lettre d'information {blog_title}. Merci de nous avoir suivi et &agrave; bient&ocirc;t !</p>";
50
 
51
 
52
 
1
  <?php
2
 
3
+ $options = array();
 
 
 
 
 
 
 
 
4
 
5
  // Message show after a subbscription request has made.
6
+ $options['subscribed_text'] =
7
  "<p>Votre demande d'inscription est enregistr&eacute;e. Merci ! Un e-mail de confirmation vous a été envoyé. V&eacute;rifier &eacute;galement votre dossier spam.</p>";
8
 
9
  // Confirmation email subject (double opt-in)
10
+ $options['confirmation_subject'] =
11
+ "Inscription &agrave; la lettre d&prime;information de {blog_title}";
12
 
13
  // Confirmation email body (double opt-in)
14
+ $options['confirmation_message'] =
15
  "<p>Bonjour {name}!</p>
16
+ <p>Vous recevez cet e-mail car nous avons enregistr&eacute; une demande d&prime;inscription &agrave; la lettre d&prime;infrmation de {blog_title}.
17
  Merci de confirmer votre inscription en cliquant sur le lien suivant : <a href=\"{subscription_confirm_url}\"><strong>je confirme mon inscription.</strong></a>.
18
  Si le lien ne fonctionne pas, merci d'utiliser cette adresse :</p>
19
  <p>{subscription_confirm_url}</p>
23
 
24
  // Subscription confirmed text (after a user clicked the confirmation link
25
  // on the email he received
26
+ $options['confirmed_text'] =
27
+ "<p>Votre inscription est confirm&eacute;e. Merci !</p>";
28
 
29
+ $options['confirmed_subject'] =
30
  "Bienvenue, {name}";
31
 
32
+ $options['confirmed_message'] =
33
+ "<p>Votre inscription est confirm&eacute;e. Merci !</p>";
34
 
35
  // Unsubscription request introductory text
36
+ $options['unsubscription_text'] =
37
+ "<p>&Ecirc;tes-vous certain de vouloir vous d&eacute;sinscrire de la lettre d&prime;information de {blog_title} ? <a href=\"{unsubscription_confirm_url}\">Oui</a>.";
38
 
39
  // When you finally loosed your subscriber
40
+ $options['unsubscribed_text'] =
41
+ "<p>Vous n&prime;&ecirc;tes plus abonn&eacute; &agrave; la lettre d'information de {blog_title}. Merci de nous avoir suivi et &agrave; bient&ocirc;t !</p>";
42
 
43
 
44
 
subscription/languages/it_IT.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ $options = array();
5
+
6
+ // Subscription registration message
7
+ $options['subscribed_text'] =
8
+ "<p>L'iscrizione è quasi completa: controlla la tua
9
+ casella di posta, c'è un messaggio per te con il quale confermare l'iscrizione.</p>";
10
+
11
+ // Confirmation email (double opt-in)
12
+ $options['confirmation_subject'] =
13
+ "{name}, conferma l'iscrizione alle newsletter di {blog_title}";
14
+
15
+ $options['confirmation_message'] =
16
+ "<p>Ciao {name},</p>
17
+ <p>hai richiesto l'iscrizione alla newsletter di {blog_title}.
18
+ Conferma l'iscrizione <a href=\"{subscription_confirm_url}\"><strong>cliccando qui</strong></a>
19
+ oppure copia il link qui sotto nel tu programma di navigazione:</p>
20
+ <p>{subscription_confirm_url}</p>
21
+ <p>Grazie!</p>";
22
+
23
+ $options['confirmed_subject'] =
24
+ "Benvenuto {name}!";
25
+
26
+ $options['confirmed_message'] =
27
+ "<p>Con questo messaggio ti confermo l'iscrizione alla newsletter.</p>
28
+ <p>Grazie!</p>";
29
+
30
+ // Subscription confirmed text
31
+ $options['confirmed_text'] =
32
+ "<p>{name}, la tua iscrizione è stata confermata.
33
+ Buona lettura!</p>";
34
+
35
+
36
+ $options['unsubscription_text'] =
37
+ "<p>{name}, vuoi eliminare la tua iscrizione?
38
+ Se sì... mi dispace, ma non ti trattengo oltre:</p>
39
+ <p><a href=\"{unsubscription_confirm_url}\">Sì, voglio eliminare la mia iscrizione per sempre</a>.</p>";
40
+
41
+ $options['unsubscribed_text'] =
42
+ "<p>La tua iscrizione è stata definitivamente eliminata.</p>";
{languages → subscription/languages}/nl_NL.php RENAMED
@@ -1,26 +1,18 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'Foutief email-adres.';
5
- $defaults_profile['name_error'] = 'Gelieve jouw naam in te vullen.';
6
-
7
- $defaults = array();
8
- // Subscription page introductory text (befor the subscription form)
9
- $defaults['subscription_text'] =
10
- "<p>Via onderstaand formuliertje kan je je inschrijven voor onze nieuwsbrief. Via deze nieuwsbrief houden we je op de hoogte van komende activiteiten.</p>
11
- <p>Nadat je het formuliertje verstuurd hebt, zal je een bevestigingsmail ontvangen. Lees deze mail aandachtig om jouw inschrijving te bevestigen.</p>";
12
 
13
  // Message show after a subbscription request has made.
14
- $defaults['subscribed_text'] =
15
  "<p>Je hebt je ingeschreven op de nieuwsbrief.</p>
16
  <p>Binnen enkele minuten zal je een bevestigingsmail ontvangen. Volg de link in die mail om jouw inschrijving te bevestigen. Indien je problemen hebt met het ontvangen van de bevestigingsmail kan je ons via het contactformulier bereiken.</p>";
17
 
18
  // Confirmation email subject (double opt-in)
19
- $defaults['confirmation_subject'] =
20
  "{name}, Bevestig jouw inschrijving op de nieuwsbrief van {blog_title}";
21
 
22
  // Confirmation email body (double opt-in)
23
- $defaults['confirmation_message'] =
24
  "<p>Hallo {name},</p>
25
  <p>We ontvingen jouw inschrijving op onze nieuwsbrief. Gelieve de inschrijving te bevestigen door <a href=\"{subscription_confirm_url}\"><strong>hier</strong></a> te klikken. Als het klikken op de link voor jou niet werkt, kan je de volgende link in jouw browser copieren.</p>
26
  <p>{subscription_confirm_url}</p>
@@ -29,28 +21,28 @@ $defaults['confirmation_message'] =
29
 
30
  // Subscription confirmed text (after a user clicked the confirmation link
31
  // on the email he received
32
- $defaults['confirmed_text'] =
33
  "<p>Je hebt zonet jouw inschrijving bevestigd.</p><p>bedankt {name} !</p>";
34
 
35
- $defaults['confirmed_subject'] =
36
  "Welkom, {name}";
37
 
38
- $defaults['confirmed_message'] =
39
  "<p>Uw inschrijving op de niewsbrief van {blog_title} is bevestigd.</p>
40
  <p>Bedankt !</p>";
41
 
42
  // Unsubscription request introductory text
43
- $defaults['unsubscription_text'] =
44
  "<p>Gelieve uw uitschrijving te bevestigen door <a href=\"{unsubscription_confirm_url}\">hier</a> te klikken.";
45
 
46
  // When you finally loosed your subscriber
47
- $defaults['unsubscribed_text'] =
48
  "<p>U bent uit onze lijst verwijderd.</p>";
49
 
50
- $defaults['unsubscribed_subject'] =
51
  "Tot ziens, {name}";
52
 
53
- $defaults['unsubscribed_message'] =
54
  "<p>Uw uitschrijving op de nieuwsbrief van {blog_title} is bevestigd.</p>
55
  <p>Tot ziens.</p>";
56
 
1
  <?php
2
 
3
+ $options = array();
 
 
 
 
 
 
 
 
4
 
5
  // Message show after a subbscription request has made.
6
+ $options['subscribed_text'] =
7
  "<p>Je hebt je ingeschreven op de nieuwsbrief.</p>
8
  <p>Binnen enkele minuten zal je een bevestigingsmail ontvangen. Volg de link in die mail om jouw inschrijving te bevestigen. Indien je problemen hebt met het ontvangen van de bevestigingsmail kan je ons via het contactformulier bereiken.</p>";
9
 
10
  // Confirmation email subject (double opt-in)
11
+ $options['confirmation_subject'] =
12
  "{name}, Bevestig jouw inschrijving op de nieuwsbrief van {blog_title}";
13
 
14
  // Confirmation email body (double opt-in)
15
+ $options['confirmation_message'] =
16
  "<p>Hallo {name},</p>
17
  <p>We ontvingen jouw inschrijving op onze nieuwsbrief. Gelieve de inschrijving te bevestigen door <a href=\"{subscription_confirm_url}\"><strong>hier</strong></a> te klikken. Als het klikken op de link voor jou niet werkt, kan je de volgende link in jouw browser copieren.</p>
18
  <p>{subscription_confirm_url}</p>
21
 
22
  // Subscription confirmed text (after a user clicked the confirmation link
23
  // on the email he received
24
+ $options['confirmed_text'] =
25
  "<p>Je hebt zonet jouw inschrijving bevestigd.</p><p>bedankt {name} !</p>";
26
 
27
+ $options['confirmed_subject'] =
28
  "Welkom, {name}";
29
 
30
+ $options['confirmed_message'] =
31
  "<p>Uw inschrijving op de niewsbrief van {blog_title} is bevestigd.</p>
32
  <p>Bedankt !</p>";
33
 
34
  // Unsubscription request introductory text
35
+ $options['unsubscription_text'] =
36
  "<p>Gelieve uw uitschrijving te bevestigen door <a href=\"{unsubscription_confirm_url}\">hier</a> te klikken.";
37
 
38
  // When you finally loosed your subscriber
39
+ $options['unsubscribed_text'] =
40
  "<p>U bent uit onze lijst verwijderd.</p>";
41
 
42
+ $options['unsubscribed_subject'] =
43
  "Tot ziens, {name}";
44
 
45
+ $options['unsubscribed_message'] =
46
  "<p>Uw uitschrijving op de nieuwsbrief van {blog_title} is bevestigd.</p>
47
  <p>Tot ziens.</p>";
48
 
{languages → subscription/languages}/pl_PL.php RENAMED
@@ -1,29 +1,19 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'Nieprawidłowy adres e-mail.';
5
- $defaults_profile['name_error'] = 'Imię nie może być puste.';
6
-
7
- $defaults = array();
8
- // Subscription page introductory text (befor the subscription form)
9
- $defaults['subscription_text'] =
10
- "<p>Zapisz się do newslettera wypełniając pola poniżej.
11
- Postaramy się Cię uszczęśliwić.</p>
12
- <p>Zostanie wysłany do Ciebie e-mail potwierdzający:
13
- przeczytaj instrukcje w nim zawarte, aby potwierdzić subskrypcję.</p>";
14
 
15
  // Message show after a subbscription request has made.
16
- $defaults['subscribed_text'] =
17
  "<p>Zostałeś zapisany do subskrypcji.
18
  W ciągu kilku minut otrzymasz e-mail potwierdzający.
19
  Kliknij w odnośnik w nim zawarty aby potwierdzić subskrypcję. Jeśli e-mail nie pojawi się w Twojej skrzynce przez 15 minut - sprawdź folder spam.</p>";
20
 
21
  // Confirmation email subject (double opt-in)
22
- $defaults['confirmation_subject'] =
23
  "{name}, potwierdź swoją subskrypcję w {blog_title}";
24
 
25
  // Confirmation email body (double opt-in)
26
- $defaults['confirmation_message'] =
27
  "<p>Witaj {name},</p>
28
  <p>Otrzymaliśmy prośbę o wpis do subskrypcji dla tego adresu e-mail. Możesz potwierdzić ją
29
  <a href=\"{subscription_confirm_url}\"><strong>klikając tutaj</strong></a>.
@@ -35,24 +25,24 @@ Jeśli nie możesz kliknąć odnośnika, użyj poniższego linku:</p>
35
 
36
  // Subscription confirmed text (after a user clicked the confirmation link
37
  // on the email he received
38
- $defaults['confirmed_text'] =
39
  "<p>Twoja subskrypcja została potwierdzona!
40
  Dziękujemy {name}!</p>";
41
 
42
- $defaults['confirmed_subject'] =
43
  "Witaj, {name}";
44
 
45
- $defaults['confirmed_message'] =
46
  "<p>Wiadomość potwierdzająca subskyrpcję {blog_title}.</p>
47
  <p>Dziękujemy!</p>";
48
 
49
  // Unsubscription request introductory text
50
- $defaults['unsubscription_text'] =
51
  "<p>Proszę potwierdzić rezygnację z subskrypcji
52
  <a href=\"{unsubscription_confirm_url}\">klikając tutaj</a>.";
53
 
54
  // When you finally loosed your subscriber
55
- $defaults['unsubscribed_text'] =
56
  "<p>To smutne, ale usunęliśmy Twój e-mail z subskrypcji...</p>";
57
 
58
 
1
  <?php
2
 
3
+ $options = array();
 
 
 
 
 
 
 
 
 
 
4
 
5
  // Message show after a subbscription request has made.
6
+ $options['subscribed_text'] =
7
  "<p>Zostałeś zapisany do subskrypcji.
8
  W ciągu kilku minut otrzymasz e-mail potwierdzający.
9
  Kliknij w odnośnik w nim zawarty aby potwierdzić subskrypcję. Jeśli e-mail nie pojawi się w Twojej skrzynce przez 15 minut - sprawdź folder spam.</p>";
10
 
11
  // Confirmation email subject (double opt-in)
12
+ $options['confirmation_subject'] =
13
  "{name}, potwierdź swoją subskrypcję w {blog_title}";
14
 
15
  // Confirmation email body (double opt-in)
16
+ $options['confirmation_message'] =
17
  "<p>Witaj {name},</p>
18
  <p>Otrzymaliśmy prośbę o wpis do subskrypcji dla tego adresu e-mail. Możesz potwierdzić ją
19
  <a href=\"{subscription_confirm_url}\"><strong>klikając tutaj</strong></a>.
25
 
26
  // Subscription confirmed text (after a user clicked the confirmation link
27
  // on the email he received
28
+ $options['confirmed_text'] =
29
  "<p>Twoja subskrypcja została potwierdzona!
30
  Dziękujemy {name}!</p>";
31
 
32
+ $options['confirmed_subject'] =
33
  "Witaj, {name}";
34
 
35
+ $options['confirmed_message'] =
36
  "<p>Wiadomość potwierdzająca subskyrpcję {blog_title}.</p>
37
  <p>Dziękujemy!</p>";
38
 
39
  // Unsubscription request introductory text
40
+ $options['unsubscription_text'] =
41
  "<p>Proszę potwierdzić rezygnację z subskrypcji
42
  <a href=\"{unsubscription_confirm_url}\">klikając tutaj</a>.";
43
 
44
  // When you finally loosed your subscriber
45
+ $options['unsubscribed_text'] =
46
  "<p>To smutne, ale usunęliśmy Twój e-mail z subskrypcji...</p>";
47
 
48
 
{languages → subscription/languages}/pt_BR.php RENAMED
@@ -1,26 +1,19 @@
1
  <?php
2
- $defaults_profile['email_error'] = 'Endereço de email incorreto.';
3
- $defaults_profile['name_error'] = 'O nome não pode estar vazio.';
4
 
5
- // Subscription page introductory text (befor the subscription form)
6
- $defaults['subscription_text'] =
7
- "<p>Inscreva-se na minha newsletter preenchendo os campos abaixo.
8
- Tentarei lhe fazer feliz.</p>
9
- <p>Um email de confirmação será enviado a sua caixa de entrada:
10
- por favor leia as instruções e complete seu registro.</p>";
11
 
12
  // Message show after a subbscription request has made.
13
- $defaults['subscribed_text'] =
14
  "<p>Você foi inscrito corretamente na newsletter.
15
  Em alguns minutos você receberá um email de confirmação. Siga o link para confirmar a inscrição.
16
  Se o email demorar mais do que 15 minutos para chegar, cheque sua caixa de SPAM.</p>";
17
 
18
  // Confirmation email subject (double opt-in)
19
- $defaults['confirmation_subject'] =
20
  "{name}, confirme sua inscrição no site {blog_title}";
21
 
22
  // Confirmation email body (double opt-in)
23
- $defaults['confirmation_message'] =
24
  "<p>Oi {name},</p>
25
  <p>Recebemos um pedido de inscrição nos nossos informativos deste email. Você pode confirmar
26
  <a href=\"{subscription_confirm_url}\"><strong>clicando aqui</strong></a>.
@@ -32,24 +25,24 @@ Se você não puder seguir o link, acesse este endereço:</p>
32
 
33
  // Subscription confirmed text (after a user clicked the confirmation link
34
  // on the email he received
35
- $defaults['confirmed_text'] =
36
  "<p>Sua inscrição foi confirmada!
37
  Obrigado {name}.</p>";
38
 
39
- $defaults['confirmed_subject'] =
40
  "Bem vindo(a) a bordo, {name}";
41
 
42
- $defaults['confirmed_message'] =
43
  "<p>A mensagem confirma a sua inscrição nos nossos informativos.</p>
44
  <p>Obrigado.</p>";
45
 
46
  // Unsubscription request introductory text
47
- $defaults['unsubscription_text'] =
48
  "<p>Cancele a sua inscrição nos informativos
49
  <a href=\"{unsubscription_confirm_url}\">clicando aqui</a>.";
50
 
51
  // When you finally loosed your subscriber
52
- $defaults['unsubscribed_text'] =
53
  "<p>Sua inscrição foi cancelada. Inscreva-se novamente quando quiser.</p>";
54
 
55
 
1
  <?php
 
 
2
 
3
+ $options = array();
 
 
 
 
 
4
 
5
  // Message show after a subbscription request has made.
6
+ $options['subscribed_text'] =
7
  "<p>Você foi inscrito corretamente na newsletter.
8
  Em alguns minutos você receberá um email de confirmação. Siga o link para confirmar a inscrição.
9
  Se o email demorar mais do que 15 minutos para chegar, cheque sua caixa de SPAM.</p>";
10
 
11
  // Confirmation email subject (double opt-in)
12
+ $options['confirmation_subject'] =
13
  "{name}, confirme sua inscrição no site {blog_title}";
14
 
15
  // Confirmation email body (double opt-in)
16
+ $options['confirmation_message'] =
17
  "<p>Oi {name},</p>
18
  <p>Recebemos um pedido de inscrição nos nossos informativos deste email. Você pode confirmar
19
  <a href=\"{subscription_confirm_url}\"><strong>clicando aqui</strong></a>.
25
 
26
  // Subscription confirmed text (after a user clicked the confirmation link
27
  // on the email he received
28
+ $options['confirmed_text'] =
29
  "<p>Sua inscrição foi confirmada!
30
  Obrigado {name}.</p>";
31
 
32
+ $options['confirmed_subject'] =
33
  "Bem vindo(a) a bordo, {name}";
34
 
35
+ $options['confirmed_message'] =
36
  "<p>A mensagem confirma a sua inscrição nos nossos informativos.</p>
37
  <p>Obrigado.</p>";
38
 
39
  // Unsubscription request introductory text
40
+ $options['unsubscription_text'] =
41
  "<p>Cancele a sua inscrição nos informativos
42
  <a href=\"{unsubscription_confirm_url}\">clicando aqui</a>.";
43
 
44
  // When you finally loosed your subscriber
45
+ $options['unsubscribed_text'] =
46
  "<p>Sua inscrição foi cancelada. Inscreva-se novamente quando quiser.</p>";
47
 
48
 
{languages → subscription/languages}/ru_RU.php RENAMED
@@ -1,25 +1,17 @@
1
  <?php
2
 
3
- $defaults_profile = array();
4
- $defaults_profile['email_error'] = 'Неверный e-mail.';
5
- $defaults_profile['name_error'] = 'Имя должно быть указано.';
6
-
7
- $defaults = array();
8
- // Subscription page introductory text (befor the subscription form)
9
- $defaults['subscription_text'] =
10
- "<p>Вы можете подписаться на получение новостей сайта, используя форму ниже.</p>
11
- <p>На ваш почтовый ящик будет выслано письмо для подтверждения. Пожалуйста, ознакомьтесь с инструкциями в письме, для завершения процедуры.</p>";
12
 
13
  // Message show after a subbscription request has made.
14
- $defaults['subscribed_text'] =
15
  "<p>Вы успешно подписаны на рассылку. Вы получите письмо с подтверждением через несколько минут. Перейдите по ссылке в письме для подтверждения. Если в течении 15 минут письмо все-таки не пришло, проверьте папку со спамом на вашем ящике, на случай если почтовая служба сочла письмо спамом. Если же письма нигде нет, свяжитесь с администратором сайта</a>.</p>";
16
 
17
  // Confirmation email subject (double opt-in)
18
- $defaults['confirmation_subject'] =
19
  "{name}, Подвердите вашу подписку на новостную ленту {blog_title}";
20
 
21
  // Confirmation email body (double opt-in)
22
- $defaults['confirmation_message'] =
23
  "<p>Здравствуйте, {name},</p>
24
  <p>От Вас поступил запрос на получение новостной рассылки. Вы можете подтвердить его, кликнув на эту <a href=\"{subscription_confirm_url}\"><strong>ссылку</strong></a>. Если ссылка по каким-то причинам не нажимается, вставьте вручную в браузер, ссылку:</p>
25
  <p>{subscription_confirm_url}</p>
@@ -29,24 +21,24 @@ $defaults['confirmation_message'] =
29
 
30
  // Subscription confirmed text (after a user clicked the confirmation link
31
  // on the email he received
32
- $defaults['confirmed_text'] =
33
  "<p>Ваша подписка подтверждена! Спасибо, {name}!</p>";
34
 
35
- $defaults['confirmed_subject'] =
36
  "Добро пожаловать, {name}";
37
 
38
- $defaults['confirmed_message'] =
39
  "<p>Вы были успешно подписаны на новостную ленту {blog_title}.</p>
40
  <p>Спасибо!</p>";
41
 
42
  // Unsubscription request introductory text
43
- $defaults['unsubscription_text'] =
44
  "<p>Пожалуйста, подведите свой отказ от подписки, кликнув <a href=\"{unsubscription_confirm_url}\">здесь</a>.</p>";
45
 
46
  // When you finally loosed your subscriber
47
- $defaults['unsubscribed_text'] =
48
  "<p>Это сделает нам немножечко больно, но мы отписали Вас от получения новостей...</p>";
49
 
50
- $defaults['unsubscribed_subject'] =
51
  "До свидания, {name}";
52
 
1
  <?php
2
 
3
+ $options = array();
 
 
 
 
 
 
 
 
4
 
5
  // Message show after a subbscription request has made.
6
+ $options['subscribed_text'] =
7
  "<p>Вы успешно подписаны на рассылку. Вы получите письмо с подтверждением через несколько минут. Перейдите по ссылке в письме для подтверждения. Если в течении 15 минут письмо все-таки не пришло, проверьте папку со спамом на вашем ящике, на случай если почтовая служба сочла письмо спамом. Если же письма нигде нет, свяжитесь с администратором сайта</a>.</p>";
8
 
9
  // Confirmation email subject (double opt-in)
10
+ $options['confirmation_subject'] =
11
  "{name}, Подвердите вашу подписку на новостную ленту {blog_title}";
12
 
13
  // Confirmation email body (double opt-in)
14
+ $options['confirmation_message'] =
15
  "<p>Здравствуйте, {name},</p>
16
  <p>От Вас поступил запрос на получение новостной рассылки. Вы можете подтвердить его, кликнув на эту <a href=\"{subscription_confirm_url}\"><strong>ссылку</strong></a>. Если ссылка по каким-то причинам не нажимается, вставьте вручную в браузер, ссылку:</p>
17
  <p>{subscription_confirm_url}</p>
21
 
22
  // Subscription confirmed text (after a user clicked the confirmation link
23
  // on the email he received
24
+ $options['confirmed_text'] =
25
  "<p>Ваша подписка подтверждена! Спасибо, {name}!</p>";
26
 
27
+ $options['confirmed_subject'] =
28
  "Добро пожаловать, {name}";
29
 
30
+ $options['confirmed_message'] =
31
  "<p>Вы были успешно подписаны на новостную ленту {blog_title}.</p>
32
  <p>Спасибо!</p>";
33
 
34
  // Unsubscription request introductory text
35
+ $options['unsubscription_text'] =
36
  "<p>Пожалуйста, подведите свой отказ от подписки, кликнув <a href=\"{unsubscription_confirm_url}\">здесь</a>.</p>";
37
 
38
  // When you finally loosed your subscriber
39
+ $options['unsubscribed_text'] =
40
  "<p>Это сделает нам немножечко больно, но мы отписали Вас от получения новостей...</p>";
41
 
42
+ $options['unsubscribed_subject'] =
43
  "До свидания, {name}";
44
 
subscription/menu.inc.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <h2>Subscription</h2>
2
+ <div id="newsletter-nav">
3
+ <a class="button" href="?page=newsletter/subscription/options.php">Subscription and unsubscription</a>
4
+ <a class="button" href="?page=newsletter/subscription/profile.php">Form fields and layout</a>
5
+ <!--<a class="button" href="?page=newsletter/subscription/form-code.php">The form code</a>-->
6
+ <a class="button" href="?page=newsletter/subscription/forms.php">Other forms</a>
7
+ </div>
subscription/options.php ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $controls = new NewsletterControls();
4
+ $module = NewsletterSubscription::instance();
5
+
6
+ // TODO: Remove and use the $module->options.
7
+ $options = get_option('newsletter', array());
8
+
9
+ if ($controls->is_action()) {
10
+ if ($controls->is_action('save')) {
11
+
12
+ if (empty($controls->data['profile_text'])) {
13
+ $defaults = $module->get_default_options();
14
+ $controls->data['profile_text'] = $defaults['profile_text'];
15
+ }
16
+
17
+ // Without the last curly bracket since there can be a form number apended
18
+ if (empty($controls->data['subscription_text'])) {
19
+ $defaults = $module->get_default_options();
20
+ $controls->data['subscription_text'] = $defaults['subscription_text'];
21
+ }
22
+
23
+ $controls->data['confirmed_url'] = trim($controls->data['confirmed_url']);
24
+ $controls->data['confirmation_url'] = trim($controls->data['confirmation_url']);
25
+ update_option('newsletter', $controls->data);
26
+ $controls->messages = 'Saved.';
27
+ }
28
+
29
+ if ($action == 'reset') {
30
+ $controls->data = $module->get_default_options();
31
+ $module->save_options($controls->data);
32
+ }
33
+
34
+ if ($controls->is_action('align_wp_users')) {
35
+
36
+ NewsletterUsers::instance();
37
+
38
+ // TODO: check if the user is already there
39
+ $wp_users = $wpdb->get_results("select * from $wpdb->users");
40
+ foreach ($wp_users as &$wp_user) {
41
+ $module->logger->info('Adding a registered WordPress user (' . $wp_user->ID . ')');
42
+ $nl_user = array();
43
+ $nl_user['email'] = $module->normalize_email($wp_user->user_email);
44
+ $nl_user['name'] = $wp_user->user_login;
45
+ $nl_user['status'] = 'C';
46
+ $nl_user['wp_user_id'] = $wp_user->ID;
47
+
48
+ if (is_array($module->options['preferences'])) {
49
+ foreach ($module->options['preferences'] as $p) {
50
+ $nl_user['list_' . $p] = 1;
51
+ }
52
+ }
53
+
54
+ NewsletterUsers::instance()->save_user($nl_user);
55
+ }
56
+ $controls->messages = 'Done.';
57
+ }
58
+ } else {
59
+ $controls->data = get_option('newsletter', array());
60
+ }
61
+ ?>
62
+
63
+ <?php if ($controls->data['novisual'] != 1) { ?>
64
+ <script type="text/javascript" src="<?php echo NEWSLETTER_URL; ?>/tiny_mce/tiny_mce.js"></script>
65
+
66
+ <script type="text/javascript">
67
+ tinyMCE.init({
68
+ inline_styles : false,
69
+ mode : "specific_textareas",
70
+ editor_selector : "visual",
71
+ theme : "advanced",
72
+ theme_advanced_disable : "styleselect",
73
+ relative_urls : false,
74
+ remove_script_host : false,
75
+ theme_advanced_buttons3: "",
76
+ theme_advanced_toolbar_location : "top",
77
+ theme_advanced_resizing : true,
78
+ theme_advanced_statusbar_location: "bottom",
79
+ document_base_url : "<?php echo get_option('home'); ?>/",
80
+ content_css : "<?php echo NEWSLETTER_URL; ?>/editor.css?" + new Date().getTime()
81
+ });
82
+ </script>
83
+ <?php } ?>
84
+
85
+ <div class="wrap">
86
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/subscription-module'; ?>
87
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
88
+
89
+ <?php include NEWSLETTER_DIR . '/subscription/menu.inc.php'; ?>
90
+
91
+
92
+ <?php $controls->show(); ?>
93
+
94
+ <p>
95
+ In this panel you can configure the subscription and cancellation process, setting every message, the single or double opt in and
96
+ even a customized subscription form.<br />
97
+ All tags that can be used on texts below are listed under <a href="#documentation">documentation</a> paragraph.
98
+ </p>
99
+
100
+
101
+ <form method="post" action="">
102
+ <?php $controls->init(); ?>
103
+ <div id="tabs">
104
+ <ul>
105
+ <li><a href="#tabs-1">General</a></li>
106
+ <li><a href="#tabs-2">Subscription</a></li>
107
+ <li><a href="#tabs-3">Confirmation</a></li>
108
+ <li><a href="#tabs-4">Welcome</a></li>
109
+ <li><a href="#tabs-9">Profile</a></li>
110
+ <li><a href="#tabs-5">Unsubscription</a></li>
111
+ <!--<li><a href="#tabs-8">Popup</a></li>-->
112
+ <li><a href="#tabs-7">Docs</a></li>
113
+ </ul>
114
+
115
+ <div id="tabs-1">
116
+ <p>Choose how the subscription process to your newsletter works.</p>
117
+ <table class="form-table">
118
+ <tr valign="top">
119
+ <th>Opt In</th>
120
+ <td>
121
+ <?php $controls->select('noconfirmation', array(0 => 'Double Opt In', 1 => 'Single Opt In')); ?>
122
+ <div class="hints">
123
+ <strong>Double Opt In</strong> means subscribers need to confirm their email address by an activation link sent them on a activation email message.<br />
124
+ <strong>Single Opt In</strong> means subscribers do not need to confirm their email address.<br />
125
+ </div>
126
+ </td>
127
+ </tr>
128
+ <tr valign="top">
129
+ <th>WordPress page URL for messages</th>
130
+ <td>
131
+ <?php $controls->text('url', 70); ?> (eg. <?php echo get_option('home') . '/newsletter'; ?>, optional)
132
+
133
+ <div class="hints">
134
+ Newsletter Pro needs to interact with subscribers: subscription form, welcome messages, cancellation messages,
135
+ profile editing form. If you want all those interactions within you blog theme, create a WordPress page and put
136
+ in its body <strong>only</strong> the short code [newsletter] (as is). Then open that page in your browser and copy the
137
+ page address (URL) in this field.<br />
138
+ </div>
139
+ </td>
140
+ </tr>
141
+ <tr valign="top">
142
+ <th>Disable visual editors?</th>
143
+ <td>
144
+ <?php $controls->yesno('novisual'); ?>
145
+ </td>
146
+ <tr valign="top">
147
+ <th>Automatically subscribe WordPress users</th>
148
+ <td>
149
+ <?php $controls->yesno('subscribe_wp_users'); ?>
150
+ <div class="hints">
151
+ It works only on new registration. To align old registration, press the alignment button.
152
+ <?php $controls->button_confirm('align_wp_users', 'Align WP Users', 'Proceed?'); ?>
153
+ </div>
154
+ </td>
155
+ </tr>
156
+ <tr valign="top">
157
+ <th>Notifications</th>
158
+ <td>
159
+ <?php $controls->yesno('notify'); ?>
160
+ to: <?php $controls->text_email('notify_email'); ?> (email address, leave empty for the WordPress administration email <?php echo get_option('admin_email'); ?>)
161
+ <div class="hints">
162
+ Notifies when a user confirm his subscription or unsubscribe.
163
+ </div>
164
+ </td>
165
+ </tr>
166
+ </table>
167
+ </div>
168
+
169
+
170
+ <div id="tabs-2">
171
+
172
+ <table class="form-table">
173
+ <tr valign="top">
174
+ <th>Subscription page</th>
175
+ <td>
176
+ <?php $controls->editor('subscription_text'); ?>
177
+ <div class="hints">
178
+ User <strong>{subscription_form}</strong> to insert the subscription form where you prefere in the text or
179
+ <strong>{subscription_form_N}</strong> (with N from 1 to 10) to insert one of the custom forms.
180
+ </div>
181
+ </td>
182
+ </tr>
183
+ <tr valign="top">
184
+ <th>Preferences</th>
185
+ <td>
186
+ <?php $controls->preferences(); ?>
187
+ <div class="hints">
188
+ Add to new subscribers these preferences by default.
189
+ </div>
190
+ </td>
191
+ </tr>
192
+ </table>
193
+ </div>
194
+
195
+
196
+ <div id="tabs-3">
197
+ <p>Only for double opt-in mode</p>
198
+ <table class="form-table">
199
+ <tr valign="top">
200
+ <th>Confirmation required message</th>
201
+ <td>
202
+ <?php $controls->editor('confirmation_text'); ?>
203
+ <div class="hints">
204
+ This is the text showed to a user who has pressed "subscribe me" on the previous
205
+ step informing that an email to confirm subscription has just been sent. Remember
206
+ the user to check the spam folder and to follow the email instructions.
207
+ </div>
208
+ </td>
209
+ </tr>
210
+
211
+ <tr valign="top">
212
+ <th>Alternative custom confirmation required page</th>
213
+ <td>
214
+ <?php $controls->text('confirmation_url', 70); ?>
215
+ <div class="hints">
216
+ A full page address (http://yourblog.com/confirm) to be used instead of message above. If empty the message is
217
+ used.
218
+ </div>
219
+ </td>
220
+ </tr>
221
+
222
+
223
+ <!-- CONFIRMATION EMAIL -->
224
+ <tr valign="top">
225
+ <th>Confirmation email</th>
226
+ <td>
227
+ <?php $controls->email('confirmation'); ?>
228
+ <div class="hints">
229
+ Message sent by email to new subscribers with instructions to confirm their subscription
230
+ (for double opt-in process). Do not forget to add the <strong>{subscription_confirm_url}</strong>
231
+ that users must click to activate their subscription.<br />
232
+ Sometime can be useful to add a <strong>{unsubscription_url}</strong> to let users to
233
+ cancel if they wrongly subscribed your service.
234
+ </div>
235
+ </td>
236
+ </tr>
237
+ </table>
238
+ </div>
239
+
240
+
241
+ <div id="tabs-4">
242
+ <table class="form-table">
243
+ <tr valign="top">
244
+ <th>Welcome message</th>
245
+ <td>
246
+ <?php $controls->editor('confirmed_text'); ?>
247
+ <div class="hints">
248
+ Showed when the user follow the confirmation URL sent to him with previous email
249
+ settings or if signed up directly with no double opt-in process. You can use the <strong>{profile_form}</strong> tag to let the user to
250
+ complete it's profile.
251
+ </div>
252
+ </td>
253
+ </tr>
254
+
255
+ <tr valign="top">
256
+ <th>Alternative custom welcome page</th>
257
+ <td>
258
+ <?php $controls->text('confirmed_url', 70); ?>
259
+ <div class="hints">
260
+ A full page address (http://yourblog.com/welcome) to be used instead of message above. If empty the message is
261
+ used.
262
+ </div>
263
+ </td>
264
+ </tr>
265
+
266
+ <tr valign="top">
267
+ <th>Conversion tracking code<br/><small>ADVANCED</small></th>
268
+ <td>
269
+ <?php $controls->textarea('confirmed_tracking'); ?>
270
+ <div class="hints">
271
+ The code is injected AS-IS in welcome page and can be used to track conversion
272
+ (you can use PHP if needed). Conversion code is usually supply by tracking services,
273
+ like Google AdWords, Google Analytics and so on.</div>
274
+ </td>
275
+ </tr>
276
+
277
+ <!-- WELCOME/CONFIRMED EMAIL -->
278
+ <tr valign="top">
279
+ <th>
280
+ Welcome email<br /><small>The right place where to put bonus content link</small>
281
+ </th>
282
+ <td>
283
+ <?php $controls->email('confirmed'); ?>
284
+ <div class="hints">
285
+ Email sent to the user to confirm his subscription, the successful confirmation
286
+ page, the welcome email. This is the right message where to put a <strong>{unlock_url}</strong> link to remember to the
287
+ user where is the premium content (if any, main configuration panel).<br />
288
+ It's a good idea to add the <strong>{unsubscription_url}</strong> too and the <strong>{profile_url}</strong>
289
+ letting users to cancel or manage/complete their profile.
290
+ </div>
291
+ </td>
292
+ </tr>
293
+
294
+ </table>
295
+ </div>
296
+
297
+ <!-- PROFILE -->
298
+ <div id="tabs-9">
299
+
300
+ <table class="form-table">
301
+ <tr valign="top">
302
+ <th>Profile page</th>
303
+ <td>
304
+ <?php $controls->editor('profile_text'); ?>
305
+ <div class="hints">
306
+ This is the page where subscribers edit their data. Must contain at least the {profile_form} tag. Empty the field
307
+ and save to reset it to its default.
308
+ </div>
309
+ </td>
310
+ </tr>
311
+ <tr>
312
+ <th>Other messages</th>
313
+ <td>
314
+ confirmation after profile save: <?php $controls->text('profile_saved'); ?>
315
+ </td>
316
+ </tr>
317
+ </table>
318
+ </div>
319
+
320
+
321
+ <div id="tabs-5">
322
+ <p class="intro">
323
+ A user starts the cancellation process clicking the unsubscription link in
324
+ a newsletter. This link contains the email to unsubscribe and some unique information
325
+ to avoid hacking. The user are required to confirm the unsubscription: this is the last
326
+ step where YOU can communicate with your almost missed user.
327
+ <br />
328
+ To create immediate cancellation, you can use the <strong>{unsubscription_confirm_url}</strong>
329
+ in your newsletters and upon click on that link goodbye message and email are used directly
330
+ skipping the confirm request.
331
+ </p>
332
+
333
+ <table class="form-table">
334
+ <tr valign="top">
335
+ <th>Cancellation message</th>
336
+ <td>
337
+ <?php $controls->editor('unsubscription_text'); ?>
338
+ <div class="hints">
339
+ This text is show to users who click on a "unsubscription link" in a newsletter
340
+ email. You <strong>must</strong> insert a link in the text that user can follow to confirm the
341
+ unsubscription request using the tag <strong>{unsubscription_confirm_url}</strong>.
342
+ </div>
343
+ </td>
344
+ </tr>
345
+
346
+ <!-- Text showed to the user on successful unsubscription -->
347
+ <tr valign="top">
348
+ <th>Goodbye message</th>
349
+ <td>
350
+ <?php $controls->editor('unsubscribed_text'); ?>
351
+ <div class="hints">
352
+ Shown to users after the cancellation has been completed.
353
+ </div>
354
+ </td>
355
+ </tr>
356
+
357
+ <!-- GOODBYE EMAIL -->
358
+ <tr valign="top">
359
+ <th>Goodbye email</th>
360
+ <td>
361
+ <?php $controls->email('unsubscribed'); ?>
362
+ <div class="hints">
363
+ Sent after a cancellation, is the last message you send to the user before his removal
364
+ from your newsletter subscribers. Leave the subject empty to disable this message.
365
+ </div>
366
+ </td>
367
+ </tr>
368
+ </table>
369
+ </div>
370
+
371
+
372
+ <!-- POPUP -->
373
+ <!--
374
+ <div id="tabs-8">
375
+ <p>
376
+ Newsletter plugin does not provide a popup, but if you use a popup system (like ...) you can configure it to
377
+ open the url <code><?php echo NEWSLETTER_SUBSCRIPTION_POPUP_URL; ?></code>. The message shown is the one below or,
378
+ if left empty, the standard subscription text (just try, it's easy).
379
+ </p>
380
+ <p>
381
+ The message shown after the subscription is the standard confirmation or welcome message (it depends on opt in setting).
382
+ </p>
383
+
384
+ <table class="form-table">
385
+ <tr valign="top">
386
+ <th>Popup subscription page</th>
387
+ <td>
388
+ <?php $controls->editor('subscription_popup_text'); ?>
389
+ <div class="hints">
390
+ Leave empty to use the standard subscription page text.
391
+ </div>
392
+ </td>
393
+ </tr>
394
+ </table>
395
+ </div>
396
+ -->
397
+
398
+ <div id="tabs-7">
399
+
400
+ <h4>User's data</h4>
401
+ <p>
402
+ <strong>{name}</strong>
403
+ The user name<br />
404
+ <strong>{surname}</strong>
405
+ The user surname<br />
406
+ <strong>{email}</strong>
407
+ The user email<br />
408
+ <strong>{ip}</strong>
409
+ The IP address from where the subscription started<br />
410
+ <strong>{id}</strong>
411
+ The user id<br />
412
+ <strong>{token}</strong>
413
+ The user secret token<br />
414
+ <strong>{profile_N}</strong>
415
+ The user profile field number N (from 1 to 19)<br />
416
+ </p>
417
+
418
+ <h4>Action URLs and forms</h4>
419
+ <p>
420
+ <strong>{subscription_confirm_url}</strong>
421
+ URL to build a link to confirmation of subscription when double opt-in is used. To be used on confirmation email.<br />
422
+ <strong>{unsubscription_url}</strong>
423
+ URL to build a link to start the cancellation process. To be used on every newsletter to let the user to cancel.<br />
424
+ <strong>{unsubscription_confirm_url}</strong>
425
+ URL to build a link to an immediate cancellation action. Can be used on newsletters if you want an immediate cancellation or
426
+ on cancellation page (displayed on {unsubscription_url}) to ask a cancellation confirmation.<br />
427
+ <strong>{profile_url}</strong>
428
+ URL to build a link to user's profile page (see the User Profile panel)<br />
429
+ <strong>{unlock_url}</strong>
430
+ Special URL to build a link that on click unlocks protected contents. See Main Configuration panel.<br />
431
+ <strong>{profile_form}</strong>
432
+ Insert the profile form with user's data. Usually it make sense only on welcome page.<br />
433
+ </p>
434
+ </div>
435
+ </div>
436
+
437
+ <p class="submit">
438
+ <?php $controls->button('save', 'Save'); ?>
439
+ <?php $controls->button_confirm('reset', 'Reset all', 'Are you sure you want to reset all?'); ?>
440
+ </p>
441
+
442
+ </form>
443
+ </div>
subscription/page-alternative.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // This is an alternative subscription message showing page. Variables are already initialized
3
+ // on the original page which includes this one.
4
+ ?>
5
+ <html>
6
+ <head>
7
+ <style type="text/css">
8
+ body {
9
+ font-family: verdana;
10
+ background-color: #ddd;
11
+ font-size: 12px;
12
+ }
13
+ #container {
14
+ border: 1px solid #aaa;
15
+ border-radius: 5px;
16
+ background-color: #fff;
17
+ margin: 40px auto;
18
+ width: 600px;
19
+ padding: 20px
20
+ }
21
+ h1 {
22
+ font-size: 24px;
23
+ font-weight: normal;
24
+ border-bottom: 1px solid #aaa;
25
+ margin-top: 0;
26
+ }
27
+ h2 {
28
+ font-size: 20px;
29
+ }
30
+ th, td {
31
+ font-size: 12px;
32
+ }
33
+ th {
34
+ padding-right: 10px;
35
+ text-align: right;
36
+ vertical-align: middle;
37
+ font-weight: normal;
38
+ }
39
+ </style>
40
+ </head>
41
+
42
+ <body>
43
+ <?php if (!empty($alert)) { ?>
44
+ <script>
45
+ alert("<?php echo addslashes($alert); ?>");
46
+ </script>
47
+ <?php } ?>
48
+
49
+ <div id="container">
50
+ <h1><?php echo get_option('blogname'); ?></h1>
51
+ <?php echo $message; ?>
52
+ </div>
53
+ </body>
54
+ </html>
subscription/page-popup.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // This page is used to show subscription message on a popup.
4
+ //
5
+ // The message to be shown is contained on externally prepared variable $message.
6
+ //
7
+ // To create an alternative to this file, just copy it inside
8
+ //
9
+ // wp-content/newsletter/popup.php
10
+ //
11
+ // and modify that copy.
12
+ //
13
+ // REMEBER TO REMOVE THE LINES OF CODE BELOW IN YOUR COPY!!!
14
+
15
+ // To be removed on your customzed copy
16
+ if (strpos(__FILE__, 'wp-content/newsletter') === false && is_file(WP_CONTENT_DIR . '/newsletter/popup.php')) {
17
+ include WP_CONTENT_DIR . '/newsletter/popup.php';
18
+ die();
19
+ }
20
+ // End of the code to be removed
21
+
22
+ ?>
23
+ <html>
24
+ <head>
25
+ <style type="text/css">
26
+ body {
27
+ font-family: verdana;
28
+ font-size: 12px;
29
+ background-color: #fff;
30
+ margin: 0;
31
+ padding: 0;
32
+ }
33
+ #container {
34
+ background-image: url("<?php echo NEWSLETTER_URL; ?>/images/popup/bg.png");
35
+ background-repeat: repeat-x;
36
+ padding: 10px 15px;
37
+ }
38
+ #title {
39
+ font-size: 24px;
40
+ color: #fff;
41
+ }
42
+ th, td {
43
+ font-size: 12px;
44
+ }
45
+ th {
46
+ padding-right: 10px;
47
+ text-align: right;
48
+ vertical-align: middle;
49
+ font-weight: normal;
50
+ }
51
+
52
+ .newsletter-td-privacy {
53
+ text-align: center;
54
+ }
55
+
56
+ .newsletter-td-submit {
57
+ text-align: right;
58
+ }
59
+
60
+ input[type=submit] {
61
+ background-image: url("<?php echo NEWSLETTER_URL; ?>/images/popup/button.png");
62
+ color: #fff;
63
+ border: 1px solid #333;
64
+ padding: 5px;
65
+ }
66
+ </style>
67
+ </head>
68
+
69
+ <body>
70
+ <div id="container">
71
+ <div id="title"><?php echo get_option('blogname'); ?></div>
72
+ <div id="message">
73
+ <?php echo $message; ?>
74
+ </div>
75
+ </div>
76
+ </body>
77
+ </html>
subscription/page.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // This page is used to show subscription messages to users along the various
3
+ // subscription and unsubscription steps.
4
+ //
5
+ // This page is used ONLY IF, on main configutation, you have NOT set a specific
6
+ // WordPress page to be used to show messages and when there are no alternative
7
+ // URLs specified on single messages.
8
+ //
9
+ // To create an alternative to this file, just copy the subscription-page-alternative.php on
10
+ //
11
+ // wp-content/newsletter/subscription/page.php
12
+ //
13
+ // and modify that copy.
14
+
15
+ include '../../../../wp-load.php';
16
+
17
+ $module = NewsletterSubscription::instance();
18
+ $user = $module->get_user_from_request();
19
+ $message_key = $module->get_message_key_from_request();
20
+ $message = $newsletter->replace($module->options[$message_key . '_text'], $user);
21
+ $alert = stripslashes($_REQUEST['alert']);
22
+
23
+
24
+ if (is_file(WP_CONTENT_DIR . '/extensions/newsletter/subscription/page.php')) {
25
+ include WP_CONTENT_DIR . '/extensions/newsletter/subscription/page.php';
26
+ die();
27
+ }
28
+ ?>
29
+ <html>
30
+ <head>
31
+ <style type="text/css">
32
+ body {
33
+ font-family: verdana;
34
+ background-color: #ddd;
35
+ font-size: 12px;
36
+ }
37
+ #container {
38
+ border: 1px solid #aaa;
39
+ border-radius: 5px;
40
+ background-color: #fff;
41
+ margin: 40px auto;
42
+ width: 600px;
43
+ padding: 20px
44
+ }
45
+ h1 {
46
+ font-size: 24px;
47
+ font-weight: normal;
48
+ border-bottom: 1px solid #aaa;
49
+ margin-top: 0;
50
+ }
51
+ h2 {
52
+ font-size: 20px;
53
+ }
54
+ th, td {
55
+ font-size: 12px;
56
+ }
57
+ th {
58
+ padding-right: 10px;
59
+ text-align: right;
60
+ vertical-align: middle;
61
+ font-weight: normal;
62
+ }
63
+ </style>
64
+ </head>
65
+
66
+ <body>
67
+ <?php if (!empty($alert)) { ?>
68
+ <script>
69
+ alert("<?php echo addslashes($alert); ?>");
70
+ </script>
71
+ <?php } ?>
72
+ <div id="container">
73
+ <h1><?php echo get_option('blogname'); ?></h1>
74
+ <?php echo $message; ?>
75
+ </div>
76
+ </body>
77
+ </html>
subscription/profile.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
3
+ $controls = new NewsletterControls();
4
+ $module = NewsletterSubscription::instance();
5
+
6
+ if (!$controls->is_action()) {
7
+ $controls->data = get_option('newsletter_profile');
8
+ }
9
+ else {
10
+ if ($controls->is_action('save')) {
11
+ update_option('newsletter_profile', $controls->data);
12
+ }
13
+ if ($controls->is_action('reset')) {
14
+ @include NEWSLETTER_DIR . '/languages/en_US.php';
15
+ if (defined(WPLANG) && WPLANG != '')
16
+ @include NEWSLETTER_DIR . '/languages/' . WPLANG . '.php';
17
+ update_option('newsletter_profile', $defaults_profile);
18
+ $controls->data = $defaults_profile;
19
+ }
20
+ }
21
+
22
+ $status = array(0=>'Disabled/Private', 1=>'Only on profile page', 2=>'Even on subscription page');
23
+ $rules = array(0=>'Optional', 1=>'Required');
24
+ ?>
25
+ <script type="text/javascript" src="<?php echo get_option('siteurl'); ?>/wp-content/plugins/newsletter/tiny_mce/tiny_mce.js"></script>
26
+ <script type="text/javascript">
27
+ tinyMCE.init({
28
+ mode : "specific_textareas",
29
+ editor_selector : "visual",
30
+ theme : "advanced",
31
+ theme_advanced_disable : "styleselect",
32
+ relative_urls : false,
33
+ remove_script_host : false,
34
+ theme_advanced_buttons3: "",
35
+ theme_advanced_toolbar_location : "top",
36
+ theme_advanced_resizing : true,
37
+ theme_advanced_statusbar_location: "bottom",
38
+ document_base_url : "<?php echo get_option('home'); ?>/",
39
+ content_css : "<?php echo get_option('blogurl'); ?>/wp-content/plugins/newsletter/editor.css?" + new Date().getTime()
40
+ });
41
+ </script>
42
+
43
+ <div class="wrap">
44
+ <?php $help_url = 'http://www.satollo.net/plugins/newsletter/subscription-module'; ?>
45
+ <?php include NEWSLETTER_DIR . '/header.php'; ?>
46
+
47
+ <?php include NEWSLETTER_DIR . '/subscription/menu.inc.php'; ?>
48
+
49
+ <div class="preamble">
50
+ <p>
51
+ User profile is the whole set of user data that he can edit accessing the profile page (usually via the {profile_url} link you
52
+ should add in any newsletter or welcome message.<br />
53
+ Some of this data (at least the email) is collected on subscription and you can decide here what to ask the user on sign up for your
54
+ newsletter.<br />
55
+ It's a good practice to let the subscriber to sign up with a small set of data (eg. only his email or email and name) and then let him to
56
+ add more information on a profile page.<br />
57
+ The form seems complex, but it's not! On first approach, skip profiles and preferences.
58
+ </p>
59
+ </div>
60
+
61
+ <?php $controls->show(); ?>
62
+
63
+ <form action="" method="post">
64
+ <?php $controls->init(); ?>
65
+
66
+ <div id="tabs">
67
+
68
+ <ul>
69
+ <li><a href="#tabs-2">Main profile fields</a></li>
70
+ <li><a href="#tabs-3">Extra profile fields</a></li>
71
+ <li><a href="#tabs-4">Preferences</a></li>
72
+ <li><a href="#tabs-5">Form code</a></li>
73
+ <li><a href="#tabs-6">Form style</a></li>
74
+ </ul>
75
+
76
+ <div id="tabs-2">
77
+ <table class="form-table">
78
+ <tr>
79
+ <th>User's data/fields</th>
80
+ <td>
81
+ <table class="widefat">
82
+ <thead>
83
+ <tr>
84
+ <th width="150">Field</th>
85
+ <th>Where to ask</th>
86
+ <th>Rules</th>
87
+ <th>Configuration</th>
88
+ </tr>
89
+ </thead>
90
+ <tr>
91
+ <td>Email</td>
92
+ <td>&nbsp;</td>
93
+ <td>&nbsp;</td>
94
+ <td>
95
+ <label>label</label> <?php $controls->text('email', 50); ?><br/>
96
+ <label>if wrong</label> <?php $controls->text('email_error', 50); ?>
97
+ </td>
98
+ </tr>
99
+ <tr>
100
+ <td>First Name</td>
101
+ <td><?php $controls->select('name_status', $status); ?></td>
102
+ <td><?php $controls->select('name_rules', $rules); ?></td>
103
+ <td>
104
+ <label>label</label> <?php $controls->text('name', 50); ?>
105
+ <label>if missing</label> <?php $controls->text('name_error', 50); ?>
106
+ </td>
107
+ </tr>
108
+ <tr>
109
+ <td>Last Name</td>
110
+ <td><?php $controls->select('surname_status', $status); ?></td>
111
+ <td><?php $controls->select('surname_rules', $rules); ?></td>
112
+ <td>
113
+ <label>label</label> <?php $controls->text('surname', 50); ?><br />
114
+ <label>if missing</label> <?php $controls->text('surname_error', 50); ?>
115
+ </td>
116
+ </tr>
117
+ <tr>
118
+ <td>Sex</td>
119
+ <td><?php $controls->select('sex_status', $status); ?></td>
120
+ <td>
121
+ label: <?php $controls->text('sex'); ?>
122
+ "female": <?php $controls->text('sex_female'); ?>
123
+ "male": <?php $controls->text('sex_male'); ?>
124
+ "not specified": <?php $controls->text('sex_none'); ?>
125
+ </td>
126
+ </tr>
127
+ <tr><td>Privacy checkbox</td><td><?php $controls->yesno('privacy_status'); ?></td>
128
+ <td>
129
+ <label>text</label> <?php $controls->text('privacy', 50); ?><br />
130
+ <label>unchecked warning</label> <?php $controls->text('privacy_error', 50); ?>
131
+ <label>privacy link</label> <?php $controls->text('privacy_url', 50); ?>
132
+ </td>
133
+ </tr>
134
+ </table>
135
+ <div class="hints">
136
+ If sex field is disabled subscribers will be stored with unspecified sex. Privacy is applied only on subscription and is
137
+ a checkbox the use must check to proceed with subscription.
138
+ </div>
139
+ </td>
140
+ </tr>
141
+ <tr>
142
+ <th>Buttons</th>
143
+ <td>
144
+ "subscribe": <?php $controls->text('subscribe'); ?> "profile save": <?php $controls->text('save'); ?>
145
+ <div class="hints">
146
+ For "subscribe" insert an URL to an image (http://...) to use it as a graphical button.
147
+ </div>
148
+ </td>
149
+ </tr>
150
+
151
+ </table>
152
+ </div>
153
+
154
+
155
+ <div id="tabs-3">
156
+ <table class="form-table">
157
+ <tr>
158
+ <th>Generic profile fields</th>
159
+ <td>
160
+ <div class="hints">Fields of type "list" must be configured with a set of options, comma separated
161
+ like: "first option, second option, third option".
162
+ </div>
163
+ <table class="widefat">
164
+ <thead>
165
+ <tr>
166
+ <th>Field</th><th>Label</th><th>When/Where</th><th>Type</th><th>Configuration</th>
167
+ </tr>
168
+ </thead>
169
+ <?php for ($i=1; $i<=NEWSLETTER_PROFILE_MAX; $i++) { ?>
170
+ <tr>
171
+ <td>Profile <?php echo $i; ?></td>
172
+ <td><?php $controls->text('profile_' . $i); ?></td>
173
+ <td><?php $controls->select('profile_' . $i . '_status', $status); ?></td>
174
+ <td><?php $controls->select('profile_' . $i . '_type', array('text'=>'Text', 'select'=>'List')); ?></td>
175
+ <td>
176
+ <?php $controls->textarea_fixed('profile_' . $i . '_options', '300px', '50px'); ?>
177
+ </td>
178
+ </tr>
179
+ <?php } ?>
180
+ </table>
181
+ <div class="hints">
182
+ Those fields are collected as texts, Newsletter Pro does not give meaning to them, it just stores them.
183
+ </div>
184
+ </td>
185
+ </tr>
186
+ </table>
187
+ </div>
188
+
189
+
190
+ <div id="tabs-4">
191
+ <p>
192
+ Preferences are on/off choices users can change on their profile. Those preferences are then
193
+ used by you to target emails you create.
194
+ </p>
195
+ <table class="form-table">
196
+ <tr>
197
+ <th>Preferences</th>
198
+ <td>
199
+ <table class="widefat">
200
+ <thead>
201
+ <tr>
202
+ <th>Field</th><th>When/Where</th><th>Configuration</th>
203
+ </tr>
204
+ </thead>
205
+ <?php for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) { ?>
206
+ <tr><td>Preference <?php echo $i; ?></td><td><?php $controls->select('list_' . $i . '_status', $status); ?></td><td>label: <?php $controls->text('list_' . $i); ?></td></tr>
207
+ <?php } ?>
208
+ </table>
209
+ <div class="hints">
210
+ Disabled preferences are not selectable by users but they can be assigned from admin panels, so they can be
211
+ considered as private user preferences.
212
+ </div>
213
+ </td>
214
+ </tr>
215
+ </table>
216
+ </div>
217
+
218
+
219
+ <div id="tabs-5">
220
+ <div class="tab-preamble">
221
+ <p>This panel shows the form HTML code generated by Newsletter if you want to copy it as starting point for a custom form.</p>
222
+ </div>
223
+
224
+ <textarea readonly style="width: 100%; height: 500px; font-family: monospace"><?php echo htmlspecialchars(NewsletterSubscription::instance()->get_subscription_form()); ?></textarea>
225
+ </div>
226
+
227
+ <div id="tabs-6">
228
+ <div class="tab-preamble">
229
+ <p></p>
230
+ </div>
231
+ <?php $controls->select('style', $module->get_styles()); ?>
232
+ </div>
233
+
234
+ </div>
235
+
236
+ <p class="submit"><?php $controls->button('save', 'Save'); ?></p>
237
+
238
+ </form>
239
+ </div>
subscription/styles/gray.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .newsletter {
2
+ text-align: center;
3
+ }
4
+
5
+ .newsletter table {
6
+ margin-left: auto;
7
+ margin-right: auto;
8
+ text-align: left;
9
+ border: 1px solid #eee;
10
+ background-color: #f9f9f9;
11
+ box-shadow: 0px 0px 10px #999;
12
+ padding: 10px;
13
+ width: auto;
14
+ }
15
+
16
+ .newsletter th, .newsletter td {
17
+ padding: 10px;
18
+ border: 0;
19
+ }
20
+
21
+ .newsletter th {
22
+ text-align: right;
23
+ }
24
+
25
+ .newsletter-td-submit {
26
+ text-align: center;
27
+ }
28
+
29
+ .newsletter-submit {
30
+ font-size: 18px;
31
+ background-color: #eee;
32
+ padding: 10px;
33
+ border: 1px solid #ddd;
34
+ }
subscription/styles/white.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .newsletter {
2
+ text-align: center;
3
+ }
4
+
5
+ .newsletter table {
6
+ margin-left: auto;
7
+ margin-right: auto;
8
+ text-align: left;
9
+ border: 1px solid #eee;
10
+ background-color: #fff;
11
+ box-shadow: 0px 0px 10px #999;
12
+ padding: 10px;
13
+ width: auto;
14
+ }
15
+
16
+ .newsletter th, .newsletter td {
17
+ padding: 10px;
18
+ border: 0;
19
+ }
20
+
21
+ .newsletter th {
22
+ text-align: right;
23
+ }
24
+
25
+ .newsletter-td-submit {
26
+ text-align: center;
27
+ }
28
+
29
+ .newsletter-submit {
30
+ font-size: 18px;
31
+ background-color: #eee;
32
+ padding: 10px;
33
+ border: 1px solid #ddd;
34
+ }
subscription/subscription.php ADDED
@@ -0,0 +1,848 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
4
+
5
+ class NewsletterSubscription extends NewsletterModule {
6
+
7
+ const VERSION = '1.0.0';
8
+ const MESSAGE_CONFIRMED = 'confirmed';
9
+
10
+ static $instance;
11
+
12
+ /**
13
+ * @return NewsletterSubscription
14
+ */
15
+ static function instance() {
16
+ if (self::$instance == null) {
17
+ self::$instance = new NewsletterSubscription();
18
+ }
19
+ return self::$instance;
20
+ }
21
+
22
+ function __construct() {
23
+ parent::__construct('subscription', self::VERSION);
24
+ }
25
+
26
+ function upgrade() {
27
+ global $wpdb, $charset_collate;
28
+
29
+ parent::upgrade();
30
+
31
+ // Migrate the profile_text from profile to subscription options
32
+ $options_profile = get_option('newsletter_profile');
33
+ $options = get_option('newsletter');
34
+ if (isset($options_profile['profile_text'])) {
35
+ $options['profile_text'] = $options_profile['profile_text'];
36
+ update_option('newsletter', $options);
37
+ unset($options_profile['profile_text']);
38
+ update_option('newsletter_profile', $options_profile);
39
+ }
40
+
41
+ if (isset($options_profile['profile_saved'])) {
42
+ $options['profile_saved'] = $options_profile['profile_saved'];
43
+ update_option('newsletter', $options);
44
+ unset($options_profile['profile_saved']);
45
+ update_option('newsletter_profile', $options_profile);
46
+ }
47
+
48
+ // TODO: Remove since it's only useful for first time migration
49
+ if (empty($options['profile_text'])) {
50
+ $options['profile_text'] = '{profile_form}<p><a href="{unsubscription_url}">I want unsubscribe?</a>';
51
+ }
52
+
53
+ if (!isset($options['url']) && !empty(Newsletter::instance()->options['url'])) {
54
+ $options['url'] = Newsletter::instance()->options['url'];
55
+ update_option('newsletter', $options);
56
+ }
57
+ return true;
58
+ }
59
+
60
+ function get_options($sub = '') {
61
+ if ($sub == '') {
62
+ // For compatibility the options are wrongly named
63
+ return get_option('newsletter', array());
64
+ }
65
+ parent::get_options($sub);
66
+ }
67
+
68
+ /**
69
+ * Return the subscribed user.
70
+ *
71
+ * @global type $newsletter
72
+ */
73
+ function subscribe() {
74
+ global $newsletter;
75
+
76
+ $options = get_option('newsletter', array());
77
+ $options_profile = get_option('newsletter_profile', array());
78
+
79
+ // Can be set externally
80
+ if (!isset($opt_in)) {
81
+ $opt_in = (int) $this->options['noconfirmation']; // 0 - double, 1 - single
82
+ }
83
+
84
+ $email = $newsletter->normalize_email(stripslashes($_REQUEST['ne']));
85
+ if ($email == null) die('Wrong email');
86
+
87
+ $user = NewsletterUsers::instance()->get_user($email);
88
+
89
+ // This address is new?
90
+ if ($user == null || $user->status == 'S') {
91
+
92
+ if ($user->status == 'S') {
93
+ $this->logger->info("Email address subscribed but not confirmed");
94
+ $user = array('id' => $user->id);
95
+ } else {
96
+ $this->logger->info("New email address");
97
+ $user = array('email' => $email);
98
+ }
99
+
100
+ $user['name'] = $newsletter->normalize_name(stripslashes($_REQUEST['nn']));
101
+ // TODO: required checking
102
+
103
+ $user['surname'] = $newsletter->normalize_name(stripslashes($_REQUEST['ns']));
104
+ // TODO: required checking
105
+
106
+ if (!empty($_REQUEST['nx'])) $user['sex'] = $_REQUEST['nx'][0];
107
+ // TODO: valid values check
108
+
109
+ $user['referrer'] = $_REQUEST['nr'];
110
+ $user['http_referer'] = $_SERVER['HTTP_REFERER'];
111
+
112
+ // New profiles
113
+ for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
114
+ // If the profile cannot be set by subscriber, skiyp it.
115
+ if ($options_profile['profile_' . $i . '_status'] == 0) continue;
116
+
117
+ $user['profile_' . $i] = trim(stripslashes($_REQUEST['np' . $i]));
118
+ }
119
+
120
+ // Preferences (field names are nl[] and values the list number so special forms with radio button can work)
121
+ if (is_array($_REQUEST['nl'])) {
122
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
123
+ // If not zero it is selectable by user (on subscription or on profile)
124
+ if ($options_profile['list_' . $i . '_status'] == 0) continue;
125
+ if (in_array($i, $_REQUEST['nl'])) $user['list_' . $i] = 1;
126
+ }
127
+ }
128
+
129
+ // Forced preferences as set on subscription configuration
130
+ if (is_array($options['preferences'])) {
131
+ foreach ($options['preferences'] as $p) {
132
+ $user['list_' . $p] = 1;
133
+ }
134
+ }
135
+
136
+ $user['token'] = $newsletter->get_token();
137
+ $user['ip'] = $_SERVER['REMOTE_ADDR'];
138
+ $user['status'] = $opt_in == 1 ? 'C' : 'S';
139
+
140
+ // TODO: add the flow integration?
141
+
142
+ if (isset($flow)) {
143
+ $user['flow'] = $flow;
144
+ }
145
+
146
+ // TODO: use a filter
147
+ if (class_exists('NewsletterFollowup')) {
148
+ if (NewsletterFollowup::instance()->options['add_new'] == 1) {
149
+ $user['followup'] = 1;
150
+ $user['followup_time'] = time() + NewsletterFollowup::instance()->options['interval'] * 3600;
151
+ }
152
+ }
153
+
154
+ $user = apply_filters('newsletter_user_subscribe', $user);
155
+
156
+ if (defined('NEWSLETTER_FEED_VERSION')) {
157
+ $options_feed = get_option('newsletter_feed', array());
158
+ if ($options_feed['add_new'] == 1) $user['feed'] = 1;
159
+ }
160
+
161
+ $user = NewsletterUsers::instance()->save_user($user);
162
+
163
+ // Notification to admin (only for new confirmed subscriptions)
164
+ if ($user->status == 'C') {
165
+ $this->notify_admin($user, 'Newsletter subscription');
166
+ }
167
+ } else {
168
+ // If the subscriber already exists, update it
169
+ // TODO: as second option, only a welcome/confirmation email should be sent with invitation to edit
170
+ // the profile
171
+ // $delta = array();
172
+ // if (is_array($_REQUEST['nl'])) {
173
+ // for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
174
+ // if ($options_profile['list_' . $i . '_status'] == 0) continue;
175
+ // if (in_array($i, $_REQUEST['nl'])) $delta['list_' . $i] = 1;
176
+ // }
177
+ // }
178
+ // $delta['id'] = $user->id;
179
+ // $user = $this->store->save_user($delta);
180
+ }
181
+
182
+
183
+ $prefix = ($user->status == 'C') ? 'confirmed_' : 'confirmation_';
184
+ $message = $options[$prefix . 'message'];
185
+
186
+ // TODO: This is always empty!
187
+ $message_text = $options[$prefix . 'message_text'];
188
+ $subject = $options[$prefix . 'subject'];
189
+
190
+ if ($user->status == 'C') {
191
+ setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
192
+ }
193
+
194
+ $this->mail($user->email, $newsletter->replace($subject, $user), $newsletter->replace($message, $user));
195
+
196
+ return $user;
197
+ }
198
+
199
+ /**
200
+ * Send emails during the subscription process. Emails are themes with email.php file.
201
+ * @global type $newsletter
202
+ * @return type
203
+ */
204
+ function mail($to, $subject, $message) {
205
+
206
+ ob_start();
207
+ include NEWSLETTER_DIR . '/subscription/email.php';
208
+ $message = ob_get_clean();
209
+ ob_end_clean();
210
+
211
+ Newsletter::instance()->mail($to, $subject, $message);
212
+ }
213
+
214
+ function confirm() {
215
+ global $newsletter;
216
+ $user = $this->get_user_from_request();
217
+ if ($user == null) die('No subscriber found.');
218
+ setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
219
+ NewsletterUsers::instance()->set_user_status($user->id, 'C');
220
+
221
+ $message = $this->options['confirmed_message'];
222
+
223
+ // TODO: This is always empty!
224
+ $message_text = $this->options['confirmed_message_text'];
225
+ $subject = $this->options['confirmed_subject'];
226
+
227
+ $this->mail($user->email, $newsletter->replace($subject, $user), $newsletter->replace($message, $user));
228
+
229
+ $this->notify_admin($user, 'Newsletter subscription');
230
+
231
+ $user->status = 'C';
232
+ return $user;
233
+ }
234
+
235
+ /**
236
+ * Returns the unsubscribed user.
237
+ *
238
+ * @global type $newsletter
239
+ * @return type
240
+ */
241
+ function unsubscribe() {
242
+ global $newsletter;
243
+ $user = $this->get_user_from_request();
244
+ if ($user == null) die('No subscriber found.');
245
+
246
+ setcookie('newsletter', '', time() - 3600);
247
+ NewsletterUsers::instance()->set_user_status($user->id, 'U');
248
+
249
+ $options = get_option('newsletter', array());
250
+ $options_main = get_option('newsletter_main', array());
251
+
252
+ $newsletter->mail($user->email, $newsletter->replace($options['unsubscribed_subject'], $user), $newsletter->replace($options['unsubscribed_message'], $user));
253
+ $this->notify_admin($user, 'Newsletter unsubscription');
254
+
255
+ return $user;
256
+ }
257
+
258
+ function save_profile() {
259
+ global $newsletter;
260
+
261
+ $user = $this->get_user_from_request();
262
+ if ($user == null) die('No subscriber found.');
263
+
264
+
265
+ $options_profile = get_option('newsletter_profile', array());
266
+ $options_main = get_option('newsletter_main', array());
267
+
268
+ if (!$newsletter->is_email($_REQUEST['ne'])) die('Wrong email address.');
269
+
270
+ // General data
271
+ $data['email'] = $newsletter->normalize_email(stripslashes($_REQUEST['ne']));
272
+ $data['name'] = $newsletter->normalize_name(stripslashes($_REQUEST['nn']));
273
+ $data['surname'] = $newsletter->normalize_name(stripslashes($_REQUEST['ns']));
274
+ if ($options_profile['sex_status'] >= 1) {
275
+ $data['sex'] = $_REQUEST['nx'][0];
276
+ // Wrong data injection check
277
+ if ($data['sex'] != 'm' && $data['sex'] != 'f' && $data['sex'] != 'n') die('Wrong sex field');
278
+ }
279
+
280
+ // Lists
281
+ if (is_array($_REQUEST['nl'])) {
282
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
283
+ if ($options_profile['list_' . $i . '_status'] == 0) continue;
284
+ $data['list_' . $i] = in_array($i, $_REQUEST['nl']) ? 1 : 0;
285
+ }
286
+ }
287
+
288
+ // Profile
289
+ for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
290
+ if ($options_profile['profile_' . $i . '_status'] == 0) continue;
291
+ $data['profile_' . $i] = stripslashes($_REQUEST['np' . $i]);
292
+ }
293
+
294
+ // Follow up
295
+ $options_followup = get_option('newsletter_followup');
296
+ if ($options_followup['enabled'] == 1 && $options_profile['followup_status'] > 0) {
297
+ if (isset($_POST['followup'])) $data['followup'] = 1;
298
+ else $data['followup'] = 0;
299
+ }
300
+ $data['id'] = $user->id;
301
+
302
+ // Feed by Mail service is saved here
303
+ $data = apply_filters('newsletter_profile_save', $data);
304
+
305
+ $user = NewsletterUsers::instance()->save_user($data);
306
+ return $user;
307
+ }
308
+
309
+ /**
310
+ * Finds the right way to show the message identified by $key (welcome, unsubscription, ...) redirecting the user to the
311
+ * WordPress page or loading the configured url or activating the standard page.
312
+ */
313
+ function show_message($key, $user, $alert = '') {
314
+ if (!is_object($user)) {
315
+ if (is_array($user)) $user = (object) $user;
316
+ else $user = NewsletterUsers::instance()->get_user($user);
317
+ }
318
+
319
+ if (!empty($alert)) $params = '&alert=' . urlencode($alert);
320
+
321
+ // Add exceptions for "profile" key.
322
+ // Is there a custom url?
323
+ if (!empty($this->options[$key . '_url'])) {
324
+ header('Location: ' . self::add_qs($this->options[$key . '_url'], 'nk=' . $user->id . '-' . $user->token) . $params);
325
+ die();
326
+ }
327
+
328
+ // Is there a dedicated page?
329
+ if (!empty($this->options['url'])) {
330
+ header('Location: ' . self::add_qs($this->options['url'], 'nm=' . $key . '&nk=' . $user->id . '-' . $user->token) . $params);
331
+ die();
332
+ }
333
+
334
+ // Use the standard page.
335
+ header('Location: ' . NEWSLETTER_URL . '/subscription/page.php?nm=' . $key . '&nk=' . $user->id . '-' . $user->token . $params);
336
+ die();
337
+ }
338
+
339
+ /**
340
+ * Loads the user using the request parameters (nk or nt and ni).
341
+ *
342
+ * @return null
343
+ */
344
+ function get_user_from_request() {
345
+ if (isset($_REQUEST['nk'])) {
346
+ list($id, $token) = @explode('-', $_REQUEST['nk'], 2);
347
+ } else if (isset($_REQUEST['ni'])) {
348
+ $id = (int) $_REQUEST['ni'];
349
+ $token = $_REQUEST['nt'];
350
+ }
351
+ $user = NewsletterUsers::instance()->get_user($id);
352
+
353
+ if ($user == null || $token != $user->token) return null;
354
+ return $user;
355
+ }
356
+
357
+ function get_message_key_from_request() {
358
+ if (empty($_GET['nm'])) return 'subscription';
359
+ $key = $_GET['nm'];
360
+ switch ($key) {
361
+ case 's': return 'confirmation';
362
+ case 'c': return 'confirmed';
363
+ case 'u': return 'unsubscription';
364
+ case 'uc': return 'unsubscribed';
365
+ case 'p':
366
+ case 'pe':
367
+ return 'profile';
368
+ default: return $key;
369
+ }
370
+ }
371
+
372
+ /** Searches for a user using the nk parameter or the ni and nt parameters. Tries even with the newsletter cookie.
373
+ * If found, the user object is returned or null.
374
+ * The user is returned without regards to his status that should be checked by caller.
375
+ *
376
+ * @global wpdb $wpdb
377
+ * @global type $current_user
378
+ * @return null
379
+ */
380
+ function check_user() {
381
+ global $wpdb, $current_user;
382
+
383
+ if (isset($_REQUEST['nk'])) {
384
+ list($id, $token) = @explode('-', $_REQUEST['nk'], 2);
385
+ } else if (isset($_REQUEST['ni'])) {
386
+ $id = (int) $_REQUEST['ni'];
387
+ $token = $_REQUEST['nt'];
388
+ } else if (isset($_COOKIE['newsletter'])) {
389
+ list ($id, $token) = @explode('-', $_COOKIE['newsletter'], 2);
390
+ }
391
+
392
+ if (is_numeric($id) && !empty($token)) {
393
+ return $wpdb->get_row($wpdb->prepare("select * from " . $wpdb->prefix . "newsletter where id=%d and token=%s limit 1", $id, $token));
394
+ }
395
+
396
+ if ($this->options_main['wp_integration'] != 1) {
397
+ return null;
398
+ }
399
+
400
+ get_currentuserinfo();
401
+
402
+ // Retrieve the related newsletter user
403
+ $user = $wpdb->get_row("select * from " . NEWSLETTER_USERS_TABLE . " where wp_user_id=" . $current_user->ID . " limit 1");
404
+ // There is an email matching?
405
+ if (empty($user)) {
406
+ $user = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_USERS_TABLE . " where email=%s limit 1", strtolower($current_user->user_email)));
407
+ // If not found, create a new Newsletter user, else update the wp_user_id since this email must be linked
408
+ // to the WP user email.
409
+ if (empty($user)) {
410
+ return null;
411
+ //echo 'WP user not found';
412
+ $user = array();
413
+ $user['status'] = 'C';
414
+ $user['wp_user_id'] = $current_user->ID;
415
+ $user['token'] = $this->get_token();
416
+ $user['email'] = strtolower($current_user->user_email);
417
+
418
+ $id = $wpdb->insert(NEWSLETTER_USERS_TABLE, $user);
419
+ $user = NewsletterUsers::instance()->get_user($id);
420
+ } else {
421
+ //echo 'WP user found via email';
422
+ $wpdb->query($wpdb->prepare("update " . NEWSLETTER_USERS_TABLE . " set wp_user_id=" . $current_user->ID . ", email=%s", $current_user->user_email));
423
+ }
424
+ } else {
425
+ //echo 'WP user found via id';
426
+ }
427
+
428
+ return $user;
429
+ }
430
+
431
+ function get_form_javascript() {
432
+ $options_profile = get_option('newsletter_profile');
433
+ $buffer .= "\n\n";
434
+ $buffer .= '<script type="text/javascript">' . "\n";
435
+ $buffer .= '//<![CDATA[' . "\n";
436
+ $buffer .= 'if (typeof newsletter_check !== "function") {' . "\n";
437
+ ;
438
+ $buffer .= 'window.newsletter_check = function (f) {' . "\n";
439
+ $buffer .= ' var re = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-]{1,})+\.)+([a-zA-Z0-9]{2,})+$/;' . "\n";
440
+ $buffer .= ' if (!re.test(f.elements["ne"].value)) {' . "\n";
441
+ $buffer .= ' alert("' . addslashes($options_profile['email_error']) . '");' . "\n";
442
+ $buffer .= ' return false;' . "\n";
443
+ $buffer .= ' }' . "\n";
444
+ if ($options_profile['name_status'] == 2 && $options_profile['name_rules'] == 1) {
445
+ $buffer .= ' if (f.elements["nn"] && (f.elements["nn"].value == "" || f.elements["nn"].value == f.elements["nn"].defaultValue)) {' . "\n";
446
+ $buffer .= ' alert("' . addslashes($options_profile['name_error']) . '");' . "\n";
447
+ $buffer .= ' return false;' . "\n";
448
+ $buffer .= ' }' . "\n";
449
+ }
450
+ $buffer .= ' if (f.elements["ny"] && !f.elements["ny"].checked) {' . "\n";
451
+ $buffer .= ' alert("' . addslashes($options_profile['privacy_error']) . '");' . "\n";
452
+ $buffer .= ' return false;' . "\n";
453
+ $buffer .= ' }' . "\n";
454
+ $buffer .= ' return true;' . "\n";
455
+ $buffer .= '}' . "\n";
456
+ $buffer .= '}' . "\n";
457
+ $buffer .= '//]]>' . "\n";
458
+ $buffer .= '</script>' . "\n\n";
459
+ return $buffer;
460
+ }
461
+
462
+ /**
463
+ * Returns the form html code for subscription.
464
+ *
465
+ * @return string The html code of the subscription form
466
+ */
467
+ function get_subscription_form() {
468
+ $options_profile = get_option('newsletter_profile');
469
+ $options = get_option('newsletter');
470
+
471
+ $buffer = $this->get_form_javascript();
472
+
473
+
474
+ $buffer .= '<div class="newsletter newsletter-subscription">' . "\n";
475
+ if (empty($action)) {
476
+ $buffer .= '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_URL . '" onsubmit="return newsletter_check(this)">' . "\n\n";
477
+ } else {
478
+ $buffer .= '<form method="post" action="' . $action . '" onsubmit="return newsletter_check(this)">' . "\n\n";
479
+ }
480
+ $buffer .= '<table cellspacing="0" cellpadding="3" border="0">' . "\n\n";
481
+ if ($options_profile['name_status'] == 2) {
482
+ $buffer .= "<!-- first name -->\n";
483
+ $buffer .= "<tr>\n\t" . '<th>' . $options_profile['name'] . '</th>' . "\n\t" . '<td><input class="newsletter-firstname" type="text" name="nn" size="30"/></td>' . "\n" . '</tr>' . "\n\n";
484
+ }
485
+ if ($options_profile['surname_status'] == 2) {
486
+ $buffer .= "<!-- last name -->\n";
487
+ $buffer .= "<tr>\n\t" . '<th>' . $options_profile['surname'] . '</th>' . "\n\t" . '<td><input class="newsletter-lastname" type="text" name="ns" size="30"/></td>' . "\n" . '</tr>' . "\n\n";
488
+ }
489
+
490
+ $buffer .= "<!-- email -->\n";
491
+ $buffer .= "<tr>\n\t" . '<th>' . $options_profile['email'] . '</th>' . "\n\t" . '<td align="left"><input class="newsletter-email" type="text" name="ne" size="30"/></td>' . "\n" . '</tr>' . "\n\n";
492
+
493
+ if ($options_profile['sex_status'] == 2) {
494
+ $buffer .= "<!-- sex -->\n";
495
+ $buffer .= "<tr>\n\t" . '<th>' . $options_profile['sex'] . "</th>\n\t<td>\n\t" . '<select name="nx" class="newsletter-sex">' . "\n";
496
+ $buffer .= "\t\t" . '<option value="m">' . $options_profile['sex_male'] . '</option>' . "\n";
497
+ $buffer .= "\t\t" . '<option value="f">' . $options_profile['sex_female'] . '</option>' . "\n";
498
+ $buffer .= "\t</select>\n\t</td></tr>\n";
499
+ }
500
+
501
+ $lists = '';
502
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
503
+ if ($options_profile['list_' . $i . '_status'] != 2) continue;
504
+ $lists .= "\t\t" . '<input type="checkbox" name="nl[]" value="' . $i . '"/>&nbsp;' . $options_profile['list_' . $i] . '<br />' . "\n";
505
+ }
506
+ if (!empty($lists))
507
+ $buffer .= "<!-- preferences -->\n<tr>\n\t<th>&nbsp;</th>\n\t<td>\n" . $lists . "\t</td>\n</tr>\n\n";
508
+
509
+ // Extra profile fields
510
+ for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
511
+ // Not for subscription form
512
+ if ($options_profile['profile_' . $i . '_status'] != 2) continue;
513
+
514
+ // Text field
515
+ if ($options_profile['profile_' . $i . '_type'] == 'text') {
516
+ $buffer .= "<tr>\n\t<th>" . $options_profile['profile_' . $i] . "</th>\n\t<td>\n\t\t" . '<input class="newsletter-profile newsletter-profile-' . $i . '" type="text" size="30" name="np' . $i . '"/>' . "\n\t</td>\n</tr>\n\n";
517
+ }
518
+
519
+ // Select field
520
+ if ($options_profile['profile_' . $i . '_type'] == 'select') {
521
+ $buffer .= "<tr>\n\t<th>" . $options_profile['profile_' . $i] . "</th>\n\t<td>\n\t\t" . '<select class="newsletter-profile newsletter-profile-' . $i . '" name="np' . $i . '">' . "\n";
522
+ $opts = explode(',', $options_profile['profile_' . $i . '_options']);
523
+ for ($j = 0; $j < count($opts); $j++) {
524
+ $buffer .= "\t\t\t<option>" . trim($opts[$j]) . "</option>\n";
525
+ }
526
+ $buffer .= "\t\t</select>\n\t</td>\n</tr>\n\n";
527
+ }
528
+ }
529
+
530
+ $extra = apply_filters('newsletter_subscription_extra', array());
531
+ foreach ($extra as &$x) {
532
+ $buffer .= "<tr>\n\t<th>" . $x['label'] . "</th>\n\t<td>\n\t\t";
533
+ $buffer .= $x['field'] . "\n\t</td>\n</tr>\n\n";
534
+ }
535
+
536
+ if ($options_profile['privacy_status'] == 1) {
537
+ $buffer .= "<tr>\n\t" . '<td colspan="2" class="newsletter-td-privacy">' . "\n";
538
+ $buffer .= "\t\t" . '<input type="checkbox" name="ny"/>&nbsp;';
539
+ if (!empty($options_profile['privacy_url'])) {
540
+ $buffer .= '<a target="_blank" href="' . $options_profile['privacy_url'] . '">';
541
+ $buffer .= $options_profile['privacy'] . '</a>';
542
+ } else {
543
+ $buffer .= $options_profile['privacy'];
544
+ }
545
+ $buffer .= "\n\t</td>\n</tr>\n\n";
546
+ }
547
+
548
+ $buffer .= "<tr>\n\t" . '<td colspan="2" class="newsletter-td-submit">' . "\n";
549
+
550
+ if (strpos($options_profile['subscribe'], 'http://') !== false) {
551
+ $buffer .= "\t\t" . '<input class="newsletter-submit" type="image" src="' . $options_profile['subscribe'] . '"/>' . "\n\t</td>\n</tr>\n\n";
552
+ } else {
553
+ $buffer .= "\t\t" . '<input class="newsletter-submit" type="submit" value="' . $options_profile['subscribe'] . '"/>' . "\n\t</td>\n</tr>\n\n";
554
+ }
555
+
556
+ $buffer .= "</table>\n</form>\n</div>";
557
+ return $buffer;
558
+ }
559
+
560
+ /**
561
+ * Generate the profile editing form.
562
+ */
563
+ function get_profile_form($user) {
564
+ $options = get_option('newsletter_profile');
565
+
566
+ $buffer .= '<div class="newsletter newsletter-profile">';
567
+ $buffer .= '<form action="' . NEWSLETTER_SAVE_URL . '" method="post">';
568
+ // TODO: use nk
569
+ $buffer .= '<input type="hidden" name="nk" value="' . $user->id . '-' . $user->token . '"/>';
570
+ $buffer .= '<table cellspacing="0" cellpadding="3" border="0">';
571
+ $buffer .= '<tr><th align="right">' . $options['email'] . '</th><td><input class="newsletter-email" type="text" size="30" name="ne" value="' . htmlspecialchars($user->email) . '"/></td></tr>';
572
+ if ($options['name_status'] >= 1) {
573
+ $buffer .= '<tr><th align="right">' . $options['name'] . '</th><td><input class="newsletter-firstname" type="text" size="30" name="nn" value="' . htmlspecialchars($user->name) . '"/></td></tr>';
574
+ }
575
+ if ($options['surname_status'] >= 1) {
576
+ $buffer .= '<tr><th align="right">' . $options['surname'] . '</th><td><input class="newsletter-lastname" type="text" size="30" name="ns" value="' . htmlspecialchars($user->surname) . '"/></td></tr>';
577
+ }
578
+ if ($options['sex_status'] >= 1) {
579
+ $buffer .= '<tr><th align="right">' . $options['sex'] . '</th><td><select name="nx" class="newsletter-sex">';
580
+ // if (!empty($options['sex_none'])) {
581
+ // $buffer .= '<option value="n"' . ($user->sex == 'n' ? ' selected' : '') . '>' . $options['sex_none'] . '</option>';
582
+ // }
583
+ $buffer .= '<option value="f"' . ($user->sex == 'f' ? ' selected' : '') . '>' . $options['sex_female'] . '</option>';
584
+ $buffer .= '<option value="m"' . ($user->sex == 'm' ? ' selected' : '') . '>' . $options['sex_male'] . '</option>';
585
+ $buffer .= '<option value="n"' . ($user->sex == 'n' ? ' selected' : '') . '>' . $options['sex_none'] . '</option>';
586
+ $buffer .= '</select></td></tr>';
587
+ }
588
+
589
+ // Profile
590
+ for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
591
+ if ($options['profile_' . $i . '_status'] == 0) continue;
592
+
593
+ $buffer .= '<tr><th align="right">' . $options['profile_' . $i] . '</th><td>';
594
+ //if ($options['list_type_' . $i] != 'public') continue;
595
+ $field = 'profile_' . $i;
596
+
597
+ if ($options['profile_' . $i . '_type'] == 'text') {
598
+ $buffer .= '<input class="newsletter-profile newsletter-profile-' . $i . '" type="text" size="50" name="np' . $i . '" value="' . htmlspecialchars($user->$field) . '"/>';
599
+ }
600
+
601
+ if ($options['profile_' . $i . '_type'] == 'select') {
602
+ $buffer .= '<select class="newsletter-profile newsletter-profile-' . $i . '" name="np' . $i . '">';
603
+ $opts = explode(',', $options['profile_' . $i . '_options']);
604
+ for ($j = 0; $j < count($opts); $j++) {
605
+ $opts[$j] = trim($opts[$j]);
606
+ $buffer .= '<option';
607
+ if ($opts[$j] == $user->$field) $buffer .= ' selected';
608
+ $buffer .= '>' . $opts[$j] . '</option>';
609
+ }
610
+ $buffer .= '</select>';
611
+ }
612
+
613
+ $buffer .= '</td></tr>';
614
+ }
615
+
616
+ // Lists
617
+ $buffer .= '<tr><th>&nbsp;</th><td>';
618
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
619
+ if ($options['list_' . $i . '_status'] == 0) continue;
620
+ $buffer .= '<input type="checkbox" name="nl[]" value="' . $i . '"';
621
+ $list = 'list_' . $i;
622
+ if ($user->$list == 1) $buffer .= ' checked';
623
+ $buffer .= '/> ' . htmlspecialchars($options['list_' . $i]) . '<br />';
624
+ }
625
+ $buffer .= '</td></tr>';
626
+
627
+ // Follow up
628
+ if (defined('NEWSLETTER_FOLLOWUP_VERSION')) {
629
+ $options_followup = get_option('newsletter_followup');
630
+ if ($options_followup['enabled'] == 1 && $options['followup_status'] >= 1) {
631
+ $buffer .= '<tr><th align="right">' . $options['followup'] . '</th><td>';
632
+ $buffer .= '<input type="checkbox" name="followup"';
633
+ if ($user->followup == 1) $buffer .= ' checked';
634
+ $buffer .= '/></td></tr>';
635
+ }
636
+ }
637
+
638
+ $extra = apply_filters('newsletter_profile_extra', array(), $user);
639
+ foreach ($extra as &$x) {
640
+ $buffer .= "<tr>\n\t<th>" . $x['label'] . "</th>\n\t<td>\n\t\t";
641
+ $buffer .= $x['field'] . "\n\t</td>\n</tr>\n\n";
642
+ }
643
+
644
+ $buffer .= '<tr><td colspan="2" class="newsletter-td-submit"><input type="submit" class="newsletter-submit" value="' . $options['save'] . '"/></td></tr>';
645
+ $buffer .= '</table></form></div>';
646
+
647
+ return $buffer;
648
+ }
649
+
650
+ function get_form($number) {
651
+ $options = get_option('newsletter_forms');
652
+
653
+ $form = $options['form_' . $number];
654
+
655
+ if (stripos($form, '<form') === false) {
656
+ $form = '<form method="post" action="' . NEWSLETTER_SUBSCRIBE_URL . '">' .
657
+ $form . '</form>';
658
+ }
659
+
660
+ // For compatibility
661
+ $form = str_replace('{newsletter_url}', NEWSLETTER_SUBSCRIBE_URL, $form);
662
+
663
+ $form = $this->replace_lists($form);
664
+
665
+ return $form;
666
+ }
667
+
668
+ /** Replaces on passed text the special tag {lists} that can be used to show the preferences as a list of checkbox.
669
+ * They are called lists but on configuration panel they are named preferences!
670
+ *
671
+ * @param string $buffer
672
+ * @return string
673
+ */
674
+ function replace_lists($buffer) {
675
+ $options_profile = get_option('newsletter_profile');
676
+ $lists = '';
677
+ for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
678
+ if ($options_profile['list_' . $i . '_status'] != 2) continue;
679
+ $lists .= '<input type="checkbox" name="nl[]" value="' . $i . '"/>&nbsp;' . $options_profile['list_' . $i] . '<br />';
680
+ }
681
+ $buffer = str_replace('{lists}', $lists, $buffer);
682
+ $buffer = str_replace('{preferences}', $lists, $buffer);
683
+ return $buffer;
684
+ }
685
+
686
+ function notify_admin($user, $subject) {
687
+
688
+ if ($this->options['notify'] != 1) return;
689
+
690
+ $message = "Subscriber details:\n\n" .
691
+ "email: " . $user->email . "\n" .
692
+ "first name: " . $user->name . "\n" .
693
+ "last name: " . $user->surname . "\n" .
694
+ "gender: " . $user->sex . "\n";
695
+
696
+ $options_profile = get_option('newsletter_profile');
697
+
698
+ for ($i = 0; $i < NEWSLETTER_PROFILE_MAX; $i++) {
699
+ if ($options_profile['profile_' . $i] == '') continue;
700
+ $field = 'profile_' . $i;
701
+ $message .= $options_profile['profile_' . $i] . ': ' . $user->$field . "\n";
702
+ }
703
+
704
+ for ($i = 0; $i < NEWSLETTER_LIST_MAX; $i++) {
705
+ if ($options_profile['list_' . $i] == '') continue;
706
+ $field = 'list_' . $i;
707
+ $message .= $options_profile['list_' . $i] . ': ' . $user->$field . "\n";
708
+ }
709
+
710
+ $message .= "token: " . $user->token . "\n" .
711
+ "status: " . $user->status . "\n" .
712
+ "\nYours, Newsletter Pro.";
713
+ $email = trim($this->options['notify_email']);
714
+ if (empty($email)) $email = get_option('admin_email');
715
+ wp_mail($email, '[' . get_option('blogname') . '] ' . $subject, $message, "Content-type: text/plain; charset=UTF-8\n");
716
+ }
717
+
718
+ }
719
+
720
+ // TODO: Remove in version 3.5. For compatibility.
721
+ add_shortcode('newsletter_embed', 'newsletter_shortcode_form');
722
+
723
+ add_shortcode('newsletter_form', 'newsletter_shortcode_form');
724
+
725
+ function newsletter_shortcode_form($attrs, $content) {
726
+ global $cache_stop;
727
+ $cache_stop = true;
728
+ if (isset($attrs['form'])) {
729
+ return NewsletterSubscription::instance()->get_form($attrs['form']);
730
+ } else {
731
+ return NewsletterSubscription::instance()->get_subscription_form();
732
+ }
733
+ }
734
+
735
+ add_shortcode('newsletter', 'newsletter_shortcode');
736
+
737
+ function newsletter_shortcode($attrs, $content) {
738
+ global $wpdb, $cache_stop, $newsletter;
739
+
740
+ $cache_stop = true;
741
+
742
+ $module = NewsletterSubscription::instance();
743
+ $user = $module->get_user_from_request();
744
+ $message_key = $module->get_message_key_from_request();
745
+ $alert = stripslashes($_REQUEST['alert']);
746
+
747
+ $message = $newsletter->replace($module->options[$message_key . '_text'], $user);
748
+
749
+ // Now check what form must be added
750
+ if ($message_key == 'subscription') {
751
+
752
+ if (strpos($message, '{subscription_form') === false) {
753
+ $message .= '{subscription_form}';
754
+ }
755
+
756
+ if (strpos($message, '{subscription_form}') !== false) {
757
+ // TODO: Remove on version 3.1. For compatibility.
758
+ if (isset($attrs['form'])) {
759
+ $message = str_replace('{subscription_form}', $module->get_form($attrs['form']), $message);
760
+ } else {
761
+ $message = str_replace('{subscription_form}', $module->get_subscription_form(), $message);
762
+ }
763
+ } else {
764
+ for ($i = 1; $i <= 10; $i++) {
765
+ if (strpos($message, "{subscription_form_$i}") !== false) {
766
+ $message = str_replace("{subscription_form_$i}", $module->get_form($i), $message);
767
+ break;
768
+ }
769
+ }
770
+ }
771
+ }
772
+
773
+ if (!empty($alert)) {
774
+ $message .= '<script>alert("' . addslashes($alert) . '");</script>';
775
+ }
776
+
777
+ return $message;
778
+ }
779
+
780
+ // The hook is always active so the module can be activated only on registration (otherwise we should check that
781
+ // option on every page load. The registration code should be moved inside the module...
782
+ add_action('user_register', 'newsletter_subscription_user_register');
783
+
784
+ function newsletter_subscription_user_register($user_id) {
785
+ global $wpdb;
786
+
787
+ $module = NewsletterSubscription::instance();
788
+
789
+ if ($module->options['subscribe_wp_users'] != 1) return;
790
+
791
+ $module->logger->info('Adding a registered WordPress user (' . $user_id . ')');
792
+ $wp_user = $wpdb->get_row($wpdb->prepare("select * from $wpdb->users where id=%d limit 1", $user_id));
793
+ if (empty($wp_user)) {
794
+ $module->logger->error('User not found?!');
795
+ return;
796
+ }
797
+ $user = array();
798
+ $user['email'] = $module->normalize_email($wp_user['user_email']);
799
+ $user['name'] = $wp_user['user_login'];
800
+ $user['status'] = 'C';
801
+ $user['wp_user_id'] = $wp_user->ID;
802
+
803
+ if (is_array($module->options['preferences'])) {
804
+ foreach ($module->options['preferences'] as $p) {
805
+ $user['list_' . $p] = 1;
806
+ }
807
+ }
808
+
809
+ NewsletterUsers::instance()->save_user($user);
810
+ }
811
+
812
+ // Compatibility code
813
+
814
+ function newsletter_form($number = null) {
815
+ if ($number != null) {
816
+ echo NewsletterSubscription::instance()->get_form($attrs[$number]);
817
+ } else {
818
+ echo NewsletterSubscription::instance()->get_subscription_form();
819
+ }
820
+ }
821
+
822
+ if ($_REQUEST['na'] == 's') {
823
+ $user = NewsletterSubscription::instance()->subscribe();
824
+ if ($user->status == 'C') NewsletterSubscription::instance()->show_message('confirmation', $user->id);
825
+ if ($user->status == 'S') NewsletterSubscription::instance()->show_message('confirmed', $user->id);
826
+ }
827
+
828
+ if ($_REQUEST['na'] == 'c') {
829
+ $user = NewsletterSubscription::instance()->confirm();
830
+ NewsletterSubscription::instance()->show_message('confirmed', $user);
831
+ }
832
+
833
+ if ($_REQUEST['na'] == 'u') {
834
+ $user = NewsletterSubscription::instance()->get_user_from_request();
835
+ if ($user == null) die('No subscriber found.');
836
+ NewsletterSubscription::instance()->show_message('unsubscription', $user->id);
837
+ }
838
+
839
+ if ($_REQUEST['na'] == 'uc') {
840
+ $user = NewsletterSubscription::instance()->unsubscribe();
841
+ NewsletterSubscription::instance()->show_message('unsubscribed', $user);
842
+ }
843
+
844
+ if ($_REQUEST['na'] == 'p' || $_REQUEST['na'] == 'pe') {
845
+ $user = NewsletterSubscription::instance()->get_user_from_request();
846
+ if ($user == null) die('No subscriber found.');
847
+ NewsletterSubscription::instance()->show_message('profile', $user);
848
+ }
themes-page/page-1/theme.php DELETED
@@ -1,27 +0,0 @@
1
- <?php
2
- // This theme is used to show subscription messages to users along the various
3
- // subscription and unsubscription steps.
4
- // This theme is used to show feed by mail and follow up unsubscription messages too.
5
- //
6
- // The theme is used ONLY IF, on main configutation, you have NOT set a specific
7
- // WordPress page to be used to show messages.
8
- //
9
- // The theme MUST contain the {message} place holder.
10
-
11
- ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html40/strict.dtd">
12
- <html>
13
- <head>
14
- <style type="text/css">
15
- body {
16
- font-family: sans-serif;
17
- }
18
- </style>
19
- </head>
20
-
21
- <body style="background-color: #ddd">
22
- <div style="margin: 40px auto 0 auto; width: 600px; border: 3px solid #666; background-color: #fff; padding: 20px">
23
- <h2><?php echo get_option('blogname'); ?></h2>
24
- {message}
25
- </div>
26
- </body>
27
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
themes/blank/theme.php DELETED
@@ -1 +0,0 @@
1
- <p>Blank newsletter!</p>
 
themes/empty.css DELETED
@@ -1 +0,0 @@
1
- /* Empty css for theme that does not need it */
 
themes/theme-1/theme.php DELETED
@@ -1,56 +0,0 @@
1
- <?php
2
- // If you want to translate or customize this theme, just copy the file inside the folder
3
- // wp-content/plugins/newsletter-pro-custom/themes
4
- // (create it if it does not exist) and the a new theme called "theme-1" will appear
5
- // on autocompose menu. You can rename the file if you want.
6
-
7
- $posts = new WP_Query();
8
- $posts->query(array('showposts'=>10, 'post_status'=>'publish'));
9
- ?>
10
- <table bgcolor="#c0c0c0" width="100%" cellpadding="20" cellspacing="0" border="0">
11
- <tr>
12
- <td align="center">
13
- <table width="500" bgcolor="#ffffff" align="center" cellspacing="10" cellpadding="0" style="border: 1px solid #666;">
14
- <tr>
15
- <td style="font-size: 30px">
16
- <i><?php echo get_option('blogname'); ?></i>
17
- </td>
18
- </tr>
19
- <tr>
20
- <td style="border-top: 1px solid #eee; border-bottom: 1px solid #eee; font-size: 12px; color: #999">
21
- <br />NEWSLETTER<br /><br />
22
- </td>
23
- </tr>
24
- <tr>
25
- <td style="font-size: 14px; color: #666">
26
- <p>Dear {name}, here an update from <?php echo get_option('blogname'); ?>.</p>
27
- </td>
28
- </tr>
29
- <?php
30
- while ($posts->have_posts())
31
- {
32
- $posts->the_post();
33
- $image = nt_post_image(get_the_ID());
34
- ?>
35
- <tr>
36
- <td style="font-size: 14px; color: #666">
37
- <?php if ($image != null) { ?>
38
- <img src="<?php echo $image; ?>" alt="picture" align="left"/>
39
- <?php } ?>
40
- <p><a href="<?php echo get_permalink(); ?>" style="font-size: 16px; color: #000; text-decoration: none"><?php the_title(); ?></a></p>
41
-
42
- <?php the_excerpt(); ?>
43
- </td>
44
- </tr>
45
- <?php
46
- }
47
- ?>
48
- <tr>
49
- <td style="border-top: 1px solid #eee; border-bottom: 1px solid #eee; font-size: 12px; color: #999">
50
- You received this email because you subscribed for it as {email}. If you'd like, you can <a href="{unsubscription_url}">unsubscribe</a>.
51
- </td>
52
- </tr>
53
- </table>
54
- </td>
55
- </tr>
56
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
themes/theme-2/theme-2.php DELETED
@@ -1,120 +0,0 @@
1
- <?php
2
-
3
- query_posts('showposts=' . nt_option('posts', 10) . '&post_status=publish');
4
-
5
- $text_css = 'font-family: Lucida Sans Unicode, Lucida Grande, sans-serif; font-size: 11px;';
6
- $title_css = 'font-family: Trebuchet MS, Helvetica, sans-serif; font-size: 20px; text-transform: uppercase;';
7
-
8
- ?>
9
-
10
- <table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF">
11
- <tr>
12
- <td align="left"><table width="600" align="center" cellpadding="0" cellspacing="0" style="border-width:1px;border-style:solid;border-color:#cccccc;" >
13
- <tr>
14
- <td bgcolor="#ffffff" height="10"></td>
15
- </tr>
16
- <tr>
17
- <td bgcolor="#ffffff" style="padding-top:0;padding-bottom:0;padding-right:15px;padding-left:15px;"><font size="1" face="Lucida Sans Unicode, Lucida Grande, sans-serif" color="#999999">
18
- <span style="font-size:11px;">You have received this email because you are subscribed to <?php echo get_option('blogname'); ?></span></font>
19
- </td>
20
- </tr>
21
- <tr>
22
- <td bgcolor="#ffffff" height="10"></td>
23
- </tr>
24
- <tr>
25
- <td height="3" bgcolor="#75af2d"></td>
26
- </tr>
27
- <tr>
28
- <td height="30" bgcolor="#ffffff"></td>
29
- </tr>
30
- <tr>
31
- <td bgcolor="#ffffff"><table width="100%" border="0" cellspacing="0" cellpadding="0">
32
- <tr>
33
- <td width="25" valign="top"></td>
34
- <td valign="top" width="262" height="48"><span style="font-size: 38px; color:silver"><?php echo get_option('blogname'); ?></span></td>
35
- <td width="25" valign="top"></td>
36
- </tr>
37
- <tr>
38
- <td width="25" height="20" valign="top"></td>
39
- <td height="20" valign="top"></td>
40
- <td width="25" height="20" valign="top"></td>
41
- </tr>
42
- <tr>
43
- <td width="25" height="1" valign="top"></td>
44
- <td height="1" valign="top" bgcolor="#e1e1e1"></td>
45
- <td width="25" height="1" valign="top"></td>
46
- </tr>
47
- <tr>
48
- <td width="25" height="20" valign="top"></td>
49
- <td height="20" valign="top"></td>
50
- <td width="25" height="20" valign="top"></td>
51
- </tr>
52
- <tr>
53
- <td width="25" valign="top"></td>
54
- <td valign="top">
55
- <p><strong>Hi {name},</strong></p>
56
- <p>Here a little bit of intgroduction text...</p>
57
- <p>A second line...</p>
58
- <p>Cheers, YOUR NAME</p>
59
- </td>
60
- <td width="25" valign="top"></td>
61
- </tr>
62
-
63
- <?php while (have_posts()) { the_post(); ?>
64
-
65
- <tr>
66
- <td width="25" height="20" valign="top"></td>
67
- <td height="20" valign="top" style="border-bottom: 1px solid #e1e1e1"></td>
68
- <td width="25" height="20" valign="top"></td>
69
- </tr>
70
- <!--
71
- <tr>
72
- <td width="25" height="1" valign="top"></td>
73
- <td height="1" valign="top" bgcolor="#e1e1e1"></td>
74
- <td width="25" height="1" valign="top"></td>
75
- </tr>
76
- -->
77
- <tr>
78
- <td width="25" height="20" valign="top"></td>
79
- <td height="20" valign="top"></td>
80
- <td width="25" height="20" valign="top"></td>
81
- </tr>
82
- <tr>
83
- <td width="25" valign="top"></td>
84
- <td valign="top" style="<?php echo $text_css; ?>">
85
- <h2 style="<?php echo $title_css; ?>"><?php the_title(); ?></h2>
86
- <?php $img = nt_post_image($post->ID, 'thumbnail'); ?>
87
- <?php if ($img != null) { ?>
88
- <p><img src="<?php echo $img; ?>" alt=""/></p>
89
- <?php } ?>
90
- <?php echo the_excerpt(); ?>
91
- <p><a href="<?php echo get_permalink(); ?>">Read more...</a></p>
92
- </td>
93
- <td width="25" valign="top"></td>
94
- </tr>
95
- <?php } ?>
96
-
97
- </table></td>
98
- </tr>
99
- <tr>
100
- <td height="25"></td>
101
- </tr>
102
-
103
- <tr>
104
- <td height="40" bgcolor="#e9eee8" style="padding-top:10px;padding-bottom:10px;padding-right:15px;padding-left:15px;">
105
- <font size="1" face="Lucida Sans Unicode, Lucida Grande, sans-serif" color="#403f41">
106
- <span style="font-size:10px;" >
107
- If you do not wish to receive further
108
- email notifications like this one, please
109
- <a href="{unsubscription_url}" style="text-decoration:none; color:#959595">unsubscribe</a>
110
- <br />
111
- &copy; 2009, <?php echo get_option('blogname'); ?>
112
- </span>
113
- </font>
114
- </td>
115
- </tr>
116
- </table></td>
117
- </tr>
118
- </table>
119
-
120
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/langs/en.js CHANGED
@@ -1 +1 @@
1
- tinyMCE.addI18n({en:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode_stick":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"}}});
1
+ tinyMCE.addI18n({en:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode_stick":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"},visualblocks:{desc:'Show/hide block elements'}}});
tiny_mce/plugins/fullscreen/editor_plugin.js CHANGED
@@ -1 +1 @@
1
- (function(){var a=tinymce.DOM;tinymce.create("tinymce.plugins.FullScreenPlugin",{init:function(d,e){var f=this,g={},c,b;f.editor=d;d.addCommand("mceFullScreen",function(){var i,j=a.doc.documentElement;if(d.getParam("fullscreen_is_enabled")){if(d.getParam("fullscreen_new_window")){closeFullscreen()}else{a.win.setTimeout(function(){tinymce.dom.Event.remove(a.win,"resize",f.resizeFunc);tinyMCE.get(d.getParam("fullscreen_editor_id")).setContent(d.getContent());tinyMCE.remove(d);a.remove("mce_fullscreen_container");j.style.overflow=d.getParam("fullscreen_html_overflow");a.setStyle(a.doc.body,"overflow",d.getParam("fullscreen_overflow"));a.win.scrollTo(d.getParam("fullscreen_scrollx"),d.getParam("fullscreen_scrolly"));tinyMCE.settings=tinyMCE.oldSettings},10)}return}if(d.getParam("fullscreen_new_window")){i=a.win.open(e+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{i.resizeTo(screen.availWidth,screen.availHeight)}catch(h){}}else{tinyMCE.oldSettings=tinyMCE.settings;g.fullscreen_overflow=a.getStyle(a.doc.body,"overflow",1)||"auto";g.fullscreen_html_overflow=a.getStyle(j,"overflow",1);c=a.getViewPort();g.fullscreen_scrollx=c.x;g.fullscreen_scrolly=c.y;if(tinymce.isOpera&&g.fullscreen_overflow=="visible"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&g.fullscreen_overflow=="scroll"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&(g.fullscreen_html_overflow=="visible"||g.fullscreen_html_overflow=="scroll")){g.fullscreen_html_overflow="auto"}if(g.fullscreen_overflow=="0px"){g.fullscreen_overflow=""}a.setStyle(a.doc.body,"overflow","hidden");j.style.overflow="hidden";c=a.getViewPort();a.win.scrollTo(0,0);if(tinymce.isIE){c.h-=1}if(tinymce.isIE6){b="absolute;top:"+c.y}else{b="fixed;top:0"}n=a.add(a.doc.body,"div",{id:"mce_fullscreen_container",style:"position:"+b+";left:0;width:"+c.w+"px;height:"+c.h+"px;z-index:200000;"});a.add(n,"div",{id:"mce_fullscreen"});tinymce.each(d.settings,function(k,l){g[l]=k});g.id="mce_fullscreen";g.width=n.clientWidth;g.height=n.clientHeight-15;g.fullscreen_is_enabled=true;g.fullscreen_editor_id=d.id;g.theme_advanced_resizing=false;g.save_onsavecallback=function(){d.setContent(tinyMCE.get(g.id).getContent());d.execCommand("mceSave")};tinymce.each(d.getParam("fullscreen_settings"),function(m,l){g[l]=m});if(g.theme_advanced_toolbar_location==="external"){g.theme_advanced_toolbar_location="top"}f.fullscreenEditor=new tinymce.Editor("mce_fullscreen",g);f.fullscreenEditor.onInit.add(function(){f.fullscreenEditor.setContent(d.getContent());f.fullscreenEditor.focus()});f.fullscreenEditor.render();f.fullscreenElement=new tinymce.dom.Element("mce_fullscreen_container");f.fullscreenElement.update();f.resizeFunc=tinymce.dom.Event.add(a.win,"resize",function(){var o=tinymce.DOM.getViewPort(),l=f.fullscreenEditor,k,m;k=l.dom.getSize(l.getContainer().firstChild);m=l.dom.getSize(l.getContainer().getElementsByTagName("iframe")[0]);l.theme.resizeTo(o.w-k.w+m.w,o.h-k.h+m.h)})}});d.addButton("fullscreen",{title:"fullscreen.desc",cmd:"mceFullScreen"});d.onNodeChange.add(function(i,h){h.setActive("fullscreen",i.getParam("fullscreen_is_enabled"))})},getInfo:function(){return{longname:"Fullscreen",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("fullscreen",tinymce.plugins.FullScreenPlugin)})();
1
+ (function(){var a=tinymce.DOM;tinymce.create("tinymce.plugins.FullScreenPlugin",{init:function(d,e){var f=this,g={},c,b;f.editor=d;d.addCommand("mceFullScreen",function(){var i,j=a.doc.documentElement;if(d.getParam("fullscreen_is_enabled")){if(d.getParam("fullscreen_new_window")){closeFullscreen()}else{a.win.setTimeout(function(){tinymce.dom.Event.remove(a.win,"resize",f.resizeFunc);tinyMCE.get(d.getParam("fullscreen_editor_id")).setContent(d.getContent());tinyMCE.remove(d);a.remove("mce_fullscreen_container");j.style.overflow=d.getParam("fullscreen_html_overflow");a.setStyle(a.doc.body,"overflow",d.getParam("fullscreen_overflow"));a.win.scrollTo(d.getParam("fullscreen_scrollx"),d.getParam("fullscreen_scrolly"));tinyMCE.settings=tinyMCE.oldSettings},10)}return}if(d.getParam("fullscreen_new_window")){i=a.win.open(e+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{i.resizeTo(screen.availWidth,screen.availHeight)}catch(h){}}else{tinyMCE.oldSettings=tinyMCE.settings;g.fullscreen_overflow=a.getStyle(a.doc.body,"overflow",1)||"auto";g.fullscreen_html_overflow=a.getStyle(j,"overflow",1);c=a.getViewPort();g.fullscreen_scrollx=c.x;g.fullscreen_scrolly=c.y;if(tinymce.isOpera&&g.fullscreen_overflow=="visible"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&g.fullscreen_overflow=="scroll"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&(g.fullscreen_html_overflow=="visible"||g.fullscreen_html_overflow=="scroll")){g.fullscreen_html_overflow="auto"}if(g.fullscreen_overflow=="0px"){g.fullscreen_overflow=""}a.setStyle(a.doc.body,"overflow","hidden");j.style.overflow="hidden";c=a.getViewPort();a.win.scrollTo(0,0);if(tinymce.isIE){c.h-=1}if(tinymce.isIE6||document.compatMode=="BackCompat"){b="absolute;top:"+c.y}else{b="fixed;top:0"}n=a.add(a.doc.body,"div",{id:"mce_fullscreen_container",style:"position:"+b+";left:0;width:"+c.w+"px;height:"+c.h+"px;z-index:200000;"});a.add(n,"div",{id:"mce_fullscreen"});tinymce.each(d.settings,function(k,l){g[l]=k});g.id="mce_fullscreen";g.width=n.clientWidth;g.height=n.clientHeight-15;g.fullscreen_is_enabled=true;g.fullscreen_editor_id=d.id;g.theme_advanced_resizing=false;g.save_onsavecallback=function(){d.setContent(tinyMCE.get(g.id).getContent());d.execCommand("mceSave")};tinymce.each(d.getParam("fullscreen_settings"),function(m,l){g[l]=m});if(g.theme_advanced_toolbar_location==="external"){g.theme_advanced_toolbar_location="top"}f.fullscreenEditor=new tinymce.Editor("mce_fullscreen",g);f.fullscreenEditor.onInit.add(function(){f.fullscreenEditor.setContent(d.getContent());f.fullscreenEditor.focus()});f.fullscreenEditor.render();f.fullscreenElement=new tinymce.dom.Element("mce_fullscreen_container");f.fullscreenElement.update();f.resizeFunc=tinymce.dom.Event.add(a.win,"resize",function(){var o=tinymce.DOM.getViewPort(),l=f.fullscreenEditor,k,m;k=l.dom.getSize(l.getContainer().getElementsByTagName("table")[0]);m=l.dom.getSize(l.getContainer().getElementsByTagName("iframe")[0]);l.theme.resizeTo(o.w-k.w+m.w,o.h-k.h+m.h)})}});d.addButton("fullscreen",{title:"fullscreen.desc",cmd:"mceFullScreen"});d.onNodeChange.add(function(i,h){h.setActive("fullscreen",i.getParam("fullscreen_is_enabled"))})},getInfo:function(){return{longname:"Fullscreen",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("fullscreen",tinymce.plugins.FullScreenPlugin)})();
tiny_mce/plugins/fullscreen/editor_plugin_src.js CHANGED
@@ -65,7 +65,7 @@
65
 
66
  // Fixes an IE bug where the scrollbars doesn't reappear
67
  if (tinymce.isIE && (s.fullscreen_html_overflow == 'visible' || s.fullscreen_html_overflow == 'scroll'))
68
- s.fullscreen_html_overflow = 'auto';
69
 
70
  if (s.fullscreen_overflow == '0px')
71
  s.fullscreen_overflow = '';
@@ -79,13 +79,13 @@
79
  vp.h -= 1;
80
 
81
  // Use fixed position if it exists
82
- if (tinymce.isIE6)
83
  posCss = 'absolute;top:' + vp.y;
84
  else
85
  posCss = 'fixed;top:0';
86
 
87
  n = DOM.add(DOM.doc.body, 'div', {
88
- id : 'mce_fullscreen_container',
89
  style : 'position:' + posCss + ';left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'});
90
  DOM.add(n, 'div', {id : 'mce_fullscreen'});
91
 
@@ -127,7 +127,7 @@
127
  var vp = tinymce.DOM.getViewPort(), fed = t.fullscreenEditor, outerSize, innerSize;
128
 
129
  // Get outer/inner size to get a delta size that can be used to calc the new iframe size
130
- outerSize = fed.dom.getSize(fed.getContainer().firstChild);
131
  innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]);
132
 
133
  fed.theme.resizeTo(vp.w - outerSize.w + innerSize.w, vp.h - outerSize.h + innerSize.h);
@@ -156,4 +156,4 @@
156
 
157
  // Register plugin
158
  tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin);
159
- })();
65
 
66
  // Fixes an IE bug where the scrollbars doesn't reappear
67
  if (tinymce.isIE && (s.fullscreen_html_overflow == 'visible' || s.fullscreen_html_overflow == 'scroll'))
68
+ s.fullscreen_html_overflow = 'auto';
69
 
70
  if (s.fullscreen_overflow == '0px')
71
  s.fullscreen_overflow = '';
79
  vp.h -= 1;
80
 
81
  // Use fixed position if it exists
82
+ if (tinymce.isIE6 || document.compatMode == 'BackCompat')
83
  posCss = 'absolute;top:' + vp.y;
84
  else
85
  posCss = 'fixed;top:0';
86
 
87
  n = DOM.add(DOM.doc.body, 'div', {
88
+ id : 'mce_fullscreen_container',
89
  style : 'position:' + posCss + ';left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'});
90
  DOM.add(n, 'div', {id : 'mce_fullscreen'});
91
 
127
  var vp = tinymce.DOM.getViewPort(), fed = t.fullscreenEditor, outerSize, innerSize;
128
 
129
  // Get outer/inner size to get a delta size that can be used to calc the new iframe size
130
+ outerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('table')[0]);
131
  innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]);
132
 
133
  fed.theme.resizeTo(vp.w - outerSize.w + innerSize.w, vp.h - outerSize.h + innerSize.h);
156
 
157
  // Register plugin
158
  tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin);
159
+ })();
tiny_mce/plugins/inlinepopups/editor_plugin.js ADDED
@@ -0,0 +1 @@
 
1
+ (function(){var d=tinymce.DOM,b=tinymce.dom.Element,a=tinymce.dom.Event,e=tinymce.each,c=tinymce.is;tinymce.create("tinymce.plugins.InlinePopups",{init:function(f,g){f.onBeforeRenderUI.add(function(){f.windowManager=new tinymce.InlineWindowManager(f);d.loadCSS(g+"/skins/"+(f.settings.inlinepopups_skin||"clearlooks2")+"/window.css")})},getInfo:function(){return{longname:"InlinePopups",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.create("tinymce.InlineWindowManager:tinymce.WindowManager",{InlineWindowManager:function(f){var g=this;g.parent(f);g.zIndex=300000;g.count=0;g.windows={}},open:function(s,j){var z=this,i,k="",r=z.editor,g=0,v=0,h,m,o,q,l,x,y,n;s=s||{};j=j||{};if(!s.inline){return z.parent(s,j)}n=z._frontWindow();if(n&&d.get(n.id+"_ifr")){n.focussedElement=d.get(n.id+"_ifr").contentWindow.document.activeElement}if(!s.type){z.bookmark=r.selection.getBookmark(1)}i=d.uniqueId();h=d.getViewPort();s.width=parseInt(s.width||320);s.height=parseInt(s.height||240)+(tinymce.isIE?8:0);s.min_width=parseInt(s.min_width||150);s.min_height=parseInt(s.min_height||100);s.max_width=parseInt(s.max_width||2000);s.max_height=parseInt(s.max_height||2000);s.left=s.left||Math.round(Math.max(h.x,h.x+(h.w/2)-(s.width/2)));s.top=s.top||Math.round(Math.max(h.y,h.y+(h.h/2)-(s.height/2)));s.movable=s.resizable=true;j.mce_width=s.width;j.mce_height=s.height;j.mce_inline=true;j.mce_window_id=i;j.mce_auto_focus=s.auto_focus;z.features=s;z.params=j;z.onOpen.dispatch(z,s,j);if(s.type){k+=" mceModal";if(s.type){k+=" mce"+s.type.substring(0,1).toUpperCase()+s.type.substring(1)}s.resizable=false}if(s.statusbar){k+=" mceStatusbar"}if(s.resizable){k+=" mceResizable"}if(s.minimizable){k+=" mceMinimizable"}if(s.maximizable){k+=" mceMaximizable"}if(s.movable){k+=" mceMovable"}z._addAll(d.doc.body,["div",{id:i,role:"dialog","aria-labelledby":s.type?i+"_content":i+"_title","class":(r.settings.inlinepopups_skin||"clearlooks2")+(tinymce.isIE&&window.getSelection?" ie9":""),style:"width:100px;height:100px"},["div",{id:i+"_wrapper","class":"mceWrapper"+k},["div",{id:i+"_top","class":"mceTop"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_title"},s.title||""]],["div",{id:i+"_middle","class":"mceMiddle"},["div",{id:i+"_left","class":"mceLeft",tabindex:"0"}],["span",{id:i+"_content"}],["div",{id:i+"_right","class":"mceRight",tabindex:"0"}]],["div",{id:i+"_bottom","class":"mceBottom"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_status"},"Content"]],["a",{"class":"mceMove",tabindex:"-1",href:"javascript:;"}],["a",{"class":"mceMin",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMax",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMed",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceClose",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{id:i+"_resize_n","class":"mceResize mceResizeN",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_s","class":"mceResize mceResizeS",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_w","class":"mceResize mceResizeW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_e","class":"mceResize mceResizeE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_nw","class":"mceResize mceResizeNW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_ne","class":"mceResize mceResizeNE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_sw","class":"mceResize mceResizeSW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_se","class":"mceResize mceResizeSE",tabindex:"-1",href:"javascript:;"}]]]);d.setStyles(i,{top:-10000,left:-10000});if(tinymce.isGecko){d.setStyle(i,"overflow","auto")}if(!s.type){g+=d.get(i+"_left").clientWidth;g+=d.get(i+"_right").clientWidth;v+=d.get(i+"_top").clientHeight;v+=d.get(i+"_bottom").clientHeight}d.setStyles(i,{top:s.top,left:s.left,width:s.width+g,height:s.height+v});y=s.url||s.file;if(y){if(tinymce.relaxedDomain){y+=(y.indexOf("?")==-1?"?":"&")+"mce_rdomain="+tinymce.relaxedDomain}y=tinymce._addVer(y)}if(!s.type){d.add(i+"_content","iframe",{id:i+"_ifr",src:'javascript:""',frameBorder:0,style:"border:0;width:10px;height:10px"});d.setStyles(i+"_ifr",{width:s.width,height:s.height});d.setAttrib(i+"_ifr","src",y)}else{d.add(i+"_wrapper","a",{id:i+"_ok","class":"mceButton mceOk",href:"javascript:;",onmousedown:"return false;"},"Ok");if(s.type=="confirm"){d.add(i+"_wrapper","a",{"class":"mceButton mceCancel",href:"javascript:;",onmousedown:"return false;"},"Cancel")}d.add(i+"_middle","div",{"class":"mceIcon"});d.setHTML(i+"_content",s.content.replace("\n","<br />"));a.add(i,"keyup",function(f){var p=27;if(f.keyCode===p){s.button_func(false);return a.cancel(f)}});a.add(i,"keydown",function(f){var t,p=9;if(f.keyCode===p){t=d.select("a.mceCancel",i+"_wrapper")[0];if(t&&t!==f.target){t.focus()}else{d.get(i+"_ok").focus()}return a.cancel(f)}})}o=a.add(i,"mousedown",function(t){var u=t.target,f,p;f=z.windows[i];z.focus(i);if(u.nodeName=="A"||u.nodeName=="a"){if(u.className=="mceClose"){z.close(null,i);return a.cancel(t)}else{if(u.className=="mceMax"){f.oldPos=f.element.getXY();f.oldSize=f.element.getSize();p=d.getViewPort();p.w-=2;p.h-=2;f.element.moveTo(p.x,p.y);f.element.resizeTo(p.w,p.h);d.setStyles(i+"_ifr",{width:p.w-f.deltaWidth,height:p.h-f.deltaHeight});d.addClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMed"){f.element.moveTo(f.oldPos.x,f.oldPos.y);f.element.resizeTo(f.oldSize.w,f.oldSize.h);f.iframeElement.resizeTo(f.oldSize.w-f.deltaWidth,f.oldSize.h-f.deltaHeight);d.removeClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMove"){return z._startDrag(i,t,u.className)}else{if(d.hasClass(u,"mceResize")){return z._startDrag(i,t,u.className.substring(13))}}}}}}});q=a.add(i,"click",function(f){var p=f.target;z.focus(i);if(p.nodeName=="A"||p.nodeName=="a"){switch(p.className){case"mceClose":z.close(null,i);return a.cancel(f);case"mceButton mceOk":case"mceButton mceCancel":s.button_func(p.className=="mceButton mceOk");return a.cancel(f)}}});a.add([i+"_left",i+"_right"],"focus",function(p){var t=d.get(i+"_ifr");if(t){var f=t.contentWindow.document.body;var u=d.select(":input:enabled,*[tabindex=0]",f);if(p.target.id===(i+"_left")){u[u.length-1].focus()}else{u[0].focus()}}else{d.get(i+"_ok").focus()}});x=z.windows[i]={id:i,mousedown_func:o,click_func:q,element:new b(i,{blocker:1,container:r.getContainer()}),iframeElement:new b(i+"_ifr"),features:s,deltaWidth:g,deltaHeight:v};x.iframeElement.on("focus",function(){z.focus(i)});if(z.count==0&&z.editor.getParam("dialog_type","modal")=="modal"){d.add(d.doc.body,"div",{id:"mceModalBlocker","class":(z.editor.settings.inlinepopups_skin||"clearlooks2")+"_modalBlocker",style:{zIndex:z.zIndex-1}});d.show("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","true")}else{d.setStyle("mceModalBlocker","z-index",z.zIndex-1)}if(tinymce.isIE6||/Firefox\/2\./.test(navigator.userAgent)||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceModalBlocker",{position:"absolute",left:h.x,top:h.y,width:h.w-2,height:h.h-2})}d.setAttrib(i,"aria-hidden","false");z.focus(i);z._fixIELayout(i,1);if(d.get(i+"_ok")){d.get(i+"_ok").focus()}z.count++;return x},focus:function(h){var g=this,f;if(f=g.windows[h]){f.zIndex=this.zIndex++;f.element.setStyle("zIndex",f.zIndex);f.element.update();h=h+"_wrapper";d.removeClass(g.lastId,"mceFocus");d.addClass(h,"mceFocus");g.lastId=h;if(f.focussedElement){f.focussedElement.focus()}else{if(d.get(h+"_ok")){d.get(f.id+"_ok").focus()}else{if(d.get(f.id+"_ifr")){d.get(f.id+"_ifr").focus()}}}}},_addAll:function(k,h){var g,l,f=this,j=tinymce.DOM;if(c(h,"string")){k.appendChild(j.doc.createTextNode(h))}else{if(h.length){k=k.appendChild(j.create(h[0],h[1]));for(g=2;g<h.length;g++){f._addAll(k,h[g])}}}},_startDrag:function(v,G,E){var o=this,u,z,C=d.doc,f,l=o.windows[v],h=l.element,y=h.getXY(),x,q,F,g,A,s,r,j,i,m,k,n,B;g={x:0,y:0};A=d.getViewPort();A.w-=2;A.h-=2;j=G.screenX;i=G.screenY;m=k=n=B=0;u=a.add(C,"mouseup",function(p){a.remove(C,"mouseup",u);a.remove(C,"mousemove",z);if(f){f.remove()}h.moveBy(m,k);h.resizeBy(n,B);q=h.getSize();d.setStyles(v+"_ifr",{width:q.w-l.deltaWidth,height:q.h-l.deltaHeight});o._fixIELayout(v,1);return a.cancel(p)});if(E!="Move"){D()}function D(){if(f){return}o._fixIELayout(v,0);d.add(C.body,"div",{id:"mceEventBlocker","class":"mceEventBlocker "+(o.editor.settings.inlinepopups_skin||"clearlooks2"),style:{zIndex:o.zIndex+1}});if(tinymce.isIE6||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceEventBlocker",{position:"absolute",left:A.x,top:A.y,width:A.w-2,height:A.h-2})}f=new b("mceEventBlocker");f.update();x=h.getXY();q=h.getSize();s=g.x+x.x-A.x;r=g.y+x.y-A.y;d.add(f.get(),"div",{id:"mcePlaceHolder","class":"mcePlaceHolder",style:{left:s,top:r,width:q.w,height:q.h}});F=new b("mcePlaceHolder")}z=a.add(C,"mousemove",function(w){var p,H,t;D();p=w.screenX-j;H=w.screenY-i;switch(E){case"ResizeW":m=p;n=0-p;break;case"ResizeE":n=p;break;case"ResizeN":case"ResizeNW":case"ResizeNE":if(E=="ResizeNW"){m=p;n=0-p}else{if(E=="ResizeNE"){n=p}}k=H;B=0-H;break;case"ResizeS":case"ResizeSW":case"ResizeSE":if(E=="ResizeSW"){m=p;n=0-p}else{if(E=="ResizeSE"){n=p}}B=H;break;case"mceMove":m=p;k=H;break}if(n<(t=l.features.min_width-q.w)){if(m!==0){m+=n-t}n=t}if(B<(t=l.features.min_height-q.h)){if(k!==0){k+=B-t}B=t}n=Math.min(n,l.features.max_width-q.w);B=Math.min(B,l.features.max_height-q.h);m=Math.max(m,A.x-(s+A.x));k=Math.max(k,A.y-(r+A.y));m=Math.min(m,(A.w+A.x)-(s+q.w+A.x));k=Math.min(k,(A.h+A.y)-(r+q.h+A.y));if(m+k!==0){if(s+m<0){m=0}if(r+k<0){k=0}F.moveTo(s+m,r+k)}if(n+B!==0){F.resizeTo(q.w+n,q.h+B)}return a.cancel(w)});return a.cancel(G)},resizeBy:function(g,h,i){var f=this.windows[i];if(f){f.element.resizeBy(g,h);f.iframeElement.resizeBy(g,h)}},close:function(i,k){var g=this,f,j=d.doc,h,k;k=g._findId(k||i);if(!g.windows[k]){g.parent(i);return}g.count--;if(g.count==0){d.remove("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","false");g.editor.focus()}if(f=g.windows[k]){g.onClose.dispatch(g);a.remove(j,"mousedown",f.mousedownFunc);a.remove(j,"click",f.clickFunc);a.clear(k);a.clear(k+"_ifr");d.setAttrib(k+"_ifr","src",'javascript:""');f.element.remove();delete g.windows[k];h=g._frontWindow();if(h){g.focus(h.id)}}},_frontWindow:function(){var g,f=0;e(this.windows,function(h){if(h.zIndex>f){g=h;f=h.zIndex}});return g},setTitle:function(f,g){var h;f=this._findId(f);if(h=d.get(f+"_title")){h.innerHTML=d.encode(g)}},alert:function(g,f,j){var i=this,h;h=i.open({title:i,type:"alert",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},confirm:function(g,f,j){var i=this,h;h=i.open({title:i,type:"confirm",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},_findId:function(f){var g=this;if(typeof(f)=="string"){return f}e(g.windows,function(h){var i=d.get(h.id+"_ifr");if(i&&f==i.contentWindow){f=h.id;return false}});return f},_fixIELayout:function(i,h){var f,g;if(!tinymce.isIE6){return}e(["n","s","w","e","nw","ne","sw","se"],function(j){var k=d.get(i+"_resize_"+j);d.setStyles(k,{width:h?k.clientWidth:"",height:h?k.clientHeight:"",cursor:d.getStyle(k,"cursor",1)});d.setStyle(i+"_bottom","bottom","-1px");k=0});if(f=this.windows[i]){f.element.hide();f.element.show();e(d.select("div,a",i),function(k,j){if(k.currentStyle.backgroundImage!="none"){g=new Image();g.src=k.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/,"$1")}});d.get(i).style.filter=""}}});tinymce.PluginManager.add("inlinepopups",tinymce.plugins.InlinePopups)})();
tiny_mce/plugins/inlinepopups/editor_plugin_src.js ADDED
@@ -0,0 +1,699 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * editor_plugin_src.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under LGPL License.
6
+ *
7
+ * License: http://tinymce.moxiecode.com/license
8
+ * Contributing: http://tinymce.moxiecode.com/contributing
9
+ */
10
+
11
+ (function() {
12
+ var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;
13
+
14
+ tinymce.create('tinymce.plugins.InlinePopups', {
15
+ init : function(ed, url) {
16
+ // Replace window manager
17
+ ed.onBeforeRenderUI.add(function() {
18
+ ed.windowManager = new tinymce.InlineWindowManager(ed);
19
+ DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css");
20
+ });
21
+ },
22
+
23
+ getInfo : function() {
24
+ return {
25
+ longname : 'InlinePopups',
26
+ author : 'Moxiecode Systems AB',
27
+ authorurl : 'http://tinymce.moxiecode.com',
28
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
29
+ version : tinymce.majorVersion + "." + tinymce.minorVersion
30
+ };
31
+ }
32
+ });
33
+
34
+ tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', {
35
+ InlineWindowManager : function(ed) {
36
+ var t = this;
37
+
38
+ t.parent(ed);
39
+ t.zIndex = 300000;
40
+ t.count = 0;
41
+ t.windows = {};
42
+ },
43
+
44
+ open : function(f, p) {
45
+ var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w, u, parentWindow;
46
+
47
+ f = f || {};
48
+ p = p || {};
49
+
50
+ // Run native windows
51
+ if (!f.inline)
52
+ return t.parent(f, p);
53
+
54
+ parentWindow = t._frontWindow();
55
+ if (parentWindow && DOM.get(parentWindow.id + '_ifr')) {
56
+ parentWindow.focussedElement = DOM.get(parentWindow.id + '_ifr').contentWindow.document.activeElement;
57
+ }
58
+
59
+ // Only store selection if the type is a normal window
60
+ if (!f.type)
61
+ t.bookmark = ed.selection.getBookmark(1);
62
+
63
+ id = DOM.uniqueId();
64
+ vp = DOM.getViewPort();
65
+ f.width = parseInt(f.width || 320);
66
+ f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0);
67
+ f.min_width = parseInt(f.min_width || 150);
68
+ f.min_height = parseInt(f.min_height || 100);
69
+ f.max_width = parseInt(f.max_width || 2000);
70
+ f.max_height = parseInt(f.max_height || 2000);
71
+ f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0)));
72
+ f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0)));
73
+ f.movable = f.resizable = true;
74
+ p.mce_width = f.width;
75
+ p.mce_height = f.height;
76
+ p.mce_inline = true;
77
+ p.mce_window_id = id;
78
+ p.mce_auto_focus = f.auto_focus;
79
+
80
+ // Transpose
81
+ // po = DOM.getPos(ed.getContainer());
82
+ // f.left -= po.x;
83
+ // f.top -= po.y;
84
+
85
+ t.features = f;
86
+ t.params = p;
87
+ t.onOpen.dispatch(t, f, p);
88
+
89
+ if (f.type) {
90
+ opt += ' mceModal';
91
+
92
+ if (f.type)
93
+ opt += ' mce' + f.type.substring(0, 1).toUpperCase() + f.type.substring(1);
94
+
95
+ f.resizable = false;
96
+ }
97
+
98
+ if (f.statusbar)
99
+ opt += ' mceStatusbar';
100
+
101
+ if (f.resizable)
102
+ opt += ' mceResizable';
103
+
104
+ if (f.minimizable)
105
+ opt += ' mceMinimizable';
106
+
107
+ if (f.maximizable)
108
+ opt += ' mceMaximizable';
109
+
110
+ if (f.movable)
111
+ opt += ' mceMovable';
112
+
113
+ // Create DOM objects
114
+ t._addAll(DOM.doc.body,
115
+ ['div', {id : id, role : 'dialog', 'aria-labelledby': f.type ? id + '_content' : id + '_title', 'class' : (ed.settings.inlinepopups_skin || 'clearlooks2') + (tinymce.isIE && window.getSelection ? ' ie9' : ''), style : 'width:100px;height:100px'},
116
+ ['div', {id : id + '_wrapper', 'class' : 'mceWrapper' + opt},
117
+ ['div', {id : id + '_top', 'class' : 'mceTop'},
118
+ ['div', {'class' : 'mceLeft'}],
119
+ ['div', {'class' : 'mceCenter'}],
120
+ ['div', {'class' : 'mceRight'}],
121
+ ['span', {id : id + '_title'}, f.title || '']
122
+ ],
123
+
124
+ ['div', {id : id + '_middle', 'class' : 'mceMiddle'},
125
+ ['div', {id : id + '_left', 'class' : 'mceLeft', tabindex : '0'}],
126
+ ['span', {id : id + '_content'}],
127
+ ['div', {id : id + '_right', 'class' : 'mceRight', tabindex : '0'}]
128
+ ],
129
+
130
+ ['div', {id : id + '_bottom', 'class' : 'mceBottom'},
131
+ ['div', {'class' : 'mceLeft'}],
132
+ ['div', {'class' : 'mceCenter'}],
133
+ ['div', {'class' : 'mceRight'}],
134
+ ['span', {id : id + '_status'}, 'Content']
135
+ ],
136
+
137
+ ['a', {'class' : 'mceMove', tabindex : '-1', href : 'javascript:;'}],
138
+ ['a', {'class' : 'mceMin', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],
139
+ ['a', {'class' : 'mceMax', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],
140
+ ['a', {'class' : 'mceMed', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],
141
+ ['a', {'class' : 'mceClose', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}],
142
+ ['a', {id : id + '_resize_n', 'class' : 'mceResize mceResizeN', tabindex : '-1', href : 'javascript:;'}],
143
+ ['a', {id : id + '_resize_s', 'class' : 'mceResize mceResizeS', tabindex : '-1', href : 'javascript:;'}],
144
+ ['a', {id : id + '_resize_w', 'class' : 'mceResize mceResizeW', tabindex : '-1', href : 'javascript:;'}],
145
+ ['a', {id : id + '_resize_e', 'class' : 'mceResize mceResizeE', tabindex : '-1', href : 'javascript:;'}],
146
+ ['a', {id : id + '_resize_nw', 'class' : 'mceResize mceResizeNW', tabindex : '-1', href : 'javascript:;'}],
147
+ ['a', {id : id + '_resize_ne', 'class' : 'mceResize mceResizeNE', tabindex : '-1', href : 'javascript:;'}],
148
+ ['a', {id : id + '_resize_sw', 'class' : 'mceResize mceResizeSW', tabindex : '-1', href : 'javascript:;'}],
149
+ ['a', {id : id + '_resize_se', 'class' : 'mceResize mceResizeSE', tabindex : '-1', href : 'javascript:;'}]
150
+ ]
151
+ ]
152
+ );
153
+
154
+ DOM.setStyles(id, {top : -10000, left : -10000});
155
+
156
+ // Fix gecko rendering bug, where the editors iframe messed with window contents
157
+ if (tinymce.isGecko)
158
+ DOM.setStyle(id, 'overflow', 'auto');
159
+
160
+ // Measure borders
161
+ if (!f.type) {
162
+ dw += DOM.get(id + '_left').clientWidth;
163
+ dw += DOM.get(id + '_right').clientWidth;
164
+ dh += DOM.get(id + '_top').clientHeight;
165
+ dh += DOM.get(id + '_bottom').clientHeight;
166
+ }
167
+
168
+ // Resize window
169
+ DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh});
170
+
171
+ u = f.url || f.file;
172
+ if (u) {
173
+ if (tinymce.relaxedDomain)
174
+ u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;
175
+
176
+ u = tinymce._addVer(u);
177
+ }
178
+
179
+ if (!f.type) {
180
+ DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'});
181
+ DOM.setStyles(id + '_ifr', {width : f.width, height : f.height});
182
+ DOM.setAttrib(id + '_ifr', 'src', u);
183
+ } else {
184
+ DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'mceButton mceOk', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok');
185
+
186
+ if (f.type == 'confirm')
187
+ DOM.add(id + '_wrapper', 'a', {'class' : 'mceButton mceCancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel');
188
+
189
+ DOM.add(id + '_middle', 'div', {'class' : 'mceIcon'});
190
+ DOM.setHTML(id + '_content', f.content.replace('\n', '<br />'));
191
+
192
+ Event.add(id, 'keyup', function(evt) {
193
+ var VK_ESCAPE = 27;
194
+ if (evt.keyCode === VK_ESCAPE) {
195
+ f.button_func(false);
196
+ return Event.cancel(evt);
197
+ }
198
+ });
199
+
200
+ Event.add(id, 'keydown', function(evt) {
201
+ var cancelButton, VK_TAB = 9;
202
+ if (evt.keyCode === VK_TAB) {
203
+ cancelButton = DOM.select('a.mceCancel', id + '_wrapper')[0];
204
+ if (cancelButton && cancelButton !== evt.target) {
205
+ cancelButton.focus();
206
+ } else {
207
+ DOM.get(id + '_ok').focus();
208
+ }
209
+ return Event.cancel(evt);
210
+ }
211
+ });
212
+ }
213
+
214
+ // Register events
215
+ mdf = Event.add(id, 'mousedown', function(e) {
216
+ var n = e.target, w, vp;
217
+
218
+ w = t.windows[id];
219
+ t.focus(id);
220
+
221
+ if (n.nodeName == 'A' || n.nodeName == 'a') {
222
+ if (n.className == 'mceClose') {
223
+ t.close(null, id);
224
+ return Event.cancel(e);
225
+ } else if (n.className == 'mceMax') {
226
+ w.oldPos = w.element.getXY();
227
+ w.oldSize = w.element.getSize();
228
+
229
+ vp = DOM.getViewPort();
230
+
231
+ // Reduce viewport size to avoid scrollbars
232
+ vp.w -= 2;
233
+ vp.h -= 2;
234
+
235
+ w.element.moveTo(vp.x, vp.y);
236
+ w.element.resizeTo(vp.w, vp.h);
237
+ DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight});
238
+ DOM.addClass(id + '_wrapper', 'mceMaximized');
239
+ } else if (n.className == 'mceMed') {
240
+ // Reset to old size
241
+ w.element.moveTo(w.oldPos.x, w.oldPos.y);
242
+ w.element.resizeTo(w.oldSize.w, w.oldSize.h);
243
+ w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight);
244
+
245
+ DOM.removeClass(id + '_wrapper', 'mceMaximized');
246
+ } else if (n.className == 'mceMove')
247
+ return t._startDrag(id, e, n.className);
248
+ else if (DOM.hasClass(n, 'mceResize'))
249
+ return t._startDrag(id, e, n.className.substring(13));
250
+ }
251
+ });
252
+
253
+ clf = Event.add(id, 'click', function(e) {
254
+ var n = e.target;
255
+
256
+ t.focus(id);
257
+
258
+ if (n.nodeName == 'A' || n.nodeName == 'a') {
259
+ switch (n.className) {
260
+ case 'mceClose':
261
+ t.close(null, id);
262
+ return Event.cancel(e);
263
+
264
+ case 'mceButton mceOk':
265
+ case 'mceButton mceCancel':
266
+ f.button_func(n.className == 'mceButton mceOk');
267
+ return Event.cancel(e);
268
+ }
269
+ }
270
+ });
271
+
272
+ // Make sure the tab order loops within the dialog.
273
+ Event.add([id + '_left', id + '_right'], 'focus', function(evt) {
274
+ var iframe = DOM.get(id + '_ifr');
275
+ if (iframe) {
276
+ var body = iframe.contentWindow.document.body;
277
+ var focusable = DOM.select(':input:enabled,*[tabindex=0]', body);
278
+ if (evt.target.id === (id + '_left')) {
279
+ focusable[focusable.length - 1].focus();
280
+ } else {
281
+ focusable[0].focus();
282
+ }
283
+ } else {
284
+ DOM.get(id + '_ok').focus();
285
+ }
286
+ });
287
+
288
+ // Add window
289
+ w = t.windows[id] = {
290
+ id : id,
291
+ mousedown_func : mdf,
292
+ click_func : clf,
293
+ element : new Element(id, {blocker : 1, container : ed.getContainer()}),
294
+ iframeElement : new Element(id + '_ifr'),
295
+ features : f,
296
+ deltaWidth : dw,
297
+ deltaHeight : dh
298
+ };
299
+
300
+ w.iframeElement.on('focus', function() {
301
+ t.focus(id);
302
+ });
303
+
304
+ // Setup blocker
305
+ if (t.count == 0 && t.editor.getParam('dialog_type', 'modal') == 'modal') {
306
+ DOM.add(DOM.doc.body, 'div', {
307
+ id : 'mceModalBlocker',
308
+ 'class' : (t.editor.settings.inlinepopups_skin || 'clearlooks2') + '_modalBlocker',
309
+ style : {zIndex : t.zIndex - 1}
310
+ });
311
+
312
+ DOM.show('mceModalBlocker'); // Reduces flicker in IE
313
+ DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'true');
314
+ } else
315
+ DOM.setStyle('mceModalBlocker', 'z-index', t.zIndex - 1);
316
+
317
+ if (tinymce.isIE6 || /Firefox\/2\./.test(navigator.userAgent) || (tinymce.isIE && !DOM.boxModel))
318
+ DOM.setStyles('mceModalBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2});
319
+
320
+ DOM.setAttrib(id, 'aria-hidden', 'false');
321
+ t.focus(id);
322
+ t._fixIELayout(id, 1);
323
+
324
+ // Focus ok button
325
+ if (DOM.get(id + '_ok'))
326
+ DOM.get(id + '_ok').focus();
327
+ t.count++;
328
+
329
+ return w;
330
+ },
331
+
332
+ focus : function(id) {
333
+ var t = this, w;
334
+
335
+ if (w = t.windows[id]) {
336
+ w.zIndex = this.zIndex++;
337
+ w.element.setStyle('zIndex', w.zIndex);
338
+ w.element.update();
339
+
340
+ id = id + '_wrapper';
341
+ DOM.removeClass(t.lastId, 'mceFocus');
342
+ DOM.addClass(id, 'mceFocus');
343
+ t.lastId = id;
344
+
345
+ if (w.focussedElement) {
346
+ w.focussedElement.focus();
347
+ } else if (DOM.get(id + '_ok')) {
348
+ DOM.get(w.id + '_ok').focus();
349
+ } else if (DOM.get(w.id + '_ifr')) {
350
+ DOM.get(w.id + '_ifr').focus();
351
+ }
352
+ }
353
+ },
354
+
355
+ _addAll : function(te, ne) {
356
+ var i, n, t = this, dom = tinymce.DOM;
357
+
358
+ if (is(ne, 'string'))
359
+ te.appendChild(dom.doc.createTextNode(ne));
360
+ else if (ne.length) {
361
+ te = te.appendChild(dom.create(ne[0], ne[1]));
362
+
363
+ for (i=2; i<ne.length; i++)
364
+ t._addAll(te, ne[i]);
365
+ }
366
+ },
367
+
368
+ _startDrag : function(id, se, ac) {
369
+ var t = this, mu, mm, d = DOM.doc, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh;
370
+
371
+ // Get positons and sizes
372
+ // cp = DOM.getPos(t.editor.getContainer());
373
+ cp = {x : 0, y : 0};
374
+ vp = DOM.getViewPort();
375
+
376
+ // Reduce viewport size to avoid scrollbars while dragging
377
+ vp.w -= 2;
378
+ vp.h -= 2;
379
+
380
+ sex = se.screenX;
381
+ sey = se.screenY;
382
+ dx = dy = dw = dh = 0;
383
+
384
+ // Handle mouse up
385
+ mu = Event.add(d, 'mouseup', function(e) {
386
+ Event.remove(d, 'mouseup', mu);
387
+ Event.remove(d, 'mousemove', mm);
388
+
389
+ if (eb)
390
+ eb.remove();
391
+
392
+ we.moveBy(dx, dy);
393
+ we.resizeBy(dw, dh);
394
+ sz = we.getSize();
395
+ DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight});
396
+ t._fixIELayout(id, 1);
397
+
398
+ return Event.cancel(e);
399
+ });
400
+
401
+ if (ac != 'Move')
402
+ startMove();
403
+
404
+ function startMove() {
405
+ if (eb)
406
+ return;
407
+
408
+ t._fixIELayout(id, 0);
409
+
410
+ // Setup event blocker
411
+ DOM.add(d.body, 'div', {
412
+ id : 'mceEventBlocker',
413
+ 'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'),
414
+ style : {zIndex : t.zIndex + 1}
415
+ });
416
+
417
+ if (tinymce.isIE6 || (tinymce.isIE && !DOM.boxModel))
418
+ DOM.setStyles('mceEventBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2});
419
+
420
+ eb = new Element('mceEventBlocker');
421
+ eb.update();
422
+
423
+ // Setup placeholder
424
+ p = we.getXY();
425
+ sz = we.getSize();
426
+ sx = cp.x + p.x - vp.x;
427
+ sy = cp.y + p.y - vp.y;
428
+ DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'mcePlaceHolder', style : {left : sx, top : sy, width : sz.w, height : sz.h}});
429
+ ph = new Element('mcePlaceHolder');
430
+ };
431
+
432
+ // Handle mouse move/drag
433
+ mm = Event.add(d, 'mousemove', function(e) {
434
+ var x, y, v;
435
+
436
+ startMove();
437
+
438
+ x = e.screenX - sex;
439
+ y = e.screenY - sey;
440
+
441
+ switch (ac) {
442
+ case 'ResizeW':
443
+ dx = x;
444
+ dw = 0 - x;
445
+ break;
446
+
447
+ case 'ResizeE':
448
+ dw = x;
449
+ break;
450
+
451
+ case 'ResizeN':
452
+ case 'ResizeNW':
453
+ case 'ResizeNE':
454
+ if (ac == "ResizeNW") {
455
+ dx = x;
456
+ dw = 0 - x;
457
+ } else if (ac == "ResizeNE")
458
+ dw = x;
459
+
460
+ dy = y;
461
+ dh = 0 - y;
462
+ break;
463
+
464
+ case 'ResizeS':
465
+ case 'ResizeSW':
466
+ case 'ResizeSE':
467
+ if (ac == "ResizeSW") {
468
+ dx = x;
469
+ dw = 0 - x;
470
+ } else if (ac == "ResizeSE")
471
+ dw = x;
472
+
473
+ dh = y;
474
+ break;
475
+
476
+ case 'mceMove':
477
+ dx = x;
478
+ dy = y;
479
+ break;
480
+ }
481
+
482
+ // Boundary check
483
+ if (dw < (v = w.features.min_width - sz.w)) {
484
+ if (dx !== 0)
485
+ dx += dw - v;
486
+
487
+ dw = v;
488
+ }
489
+
490
+ if (dh < (v = w.features.min_height - sz.h)) {
491
+ if (dy !== 0)
492
+ dy += dh - v;
493
+
494
+ dh = v;
495
+ }
496
+
497
+ dw = Math.min(dw, w.features.max_width - sz.w);
498
+ dh = Math.min(dh, w.features.max_height - sz.h);
499
+ dx = Math.max(dx, vp.x - (sx + vp.x));
500
+ dy = Math.max(dy, vp.y - (sy + vp.y));
501
+ dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x));
502
+ dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y));
503
+
504
+ // Move if needed
505
+ if (dx + dy !== 0) {
506
+ if (sx + dx < 0)
507
+ dx = 0;
508
+
509
+ if (sy + dy < 0)
510
+ dy = 0;
511
+
512
+ ph.moveTo(sx + dx, sy + dy);
513
+ }
514
+
515
+ // Resize if needed
516
+ if (dw + dh !== 0)
517
+ ph.resizeTo(sz.w + dw, sz.h + dh);
518
+
519
+ return Event.cancel(e);
520
+ });
521
+
522
+ return Event.cancel(se);
523
+ },
524
+
525
+ resizeBy : function(dw, dh, id) {
526
+ var w = this.windows[id];
527
+
528
+ if (w) {
529
+ w.element.resizeBy(dw, dh);
530
+ w.iframeElement.resizeBy(dw, dh);
531
+ }
532
+ },
533
+
534
+ close : function(win, id) {
535
+ var t = this, w, d = DOM.doc, fw, id;
536
+
537
+ id = t._findId(id || win);
538
+
539
+ // Probably not inline
540
+ if (!t.windows[id]) {
541
+ t.parent(win);
542
+ return;
543
+ }
544
+
545
+ t.count--;
546
+
547
+ if (t.count == 0) {
548
+ DOM.remove('mceModalBlocker');
549
+ DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'false');
550
+ t.editor.focus();
551
+ }
552
+
553
+ if (w = t.windows[id]) {
554
+ t.onClose.dispatch(t);
555
+ Event.remove(d, 'mousedown', w.mousedownFunc);
556
+ Event.remove(d, 'click', w.clickFunc);
557
+ Event.clear(id);
558
+ Event.clear(id + '_ifr');
559
+
560
+ DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak
561
+ w.element.remove();
562
+ delete t.windows[id];
563
+
564
+ fw = t._frontWindow();
565
+
566
+ if (fw)
567
+ t.focus(fw.id);
568
+ }
569
+ },
570
+
571
+ // Find front most window
572
+ _frontWindow : function() {
573
+ var fw, ix = 0;
574
+ // Find front most window and focus that
575
+ each (this.windows, function(w) {
576
+ if (w.zIndex > ix) {
577
+ fw = w;
578
+ ix = w.zIndex;
579
+ }
580
+ });
581
+ return fw;
582
+ },
583
+
584
+ setTitle : function(w, ti) {
585
+ var e;
586
+
587
+ w = this._findId(w);
588
+
589
+ if (e = DOM.get(w + '_title'))
590
+ e.innerHTML = DOM.encode(ti);
591
+ },
592
+
593
+ alert : function(txt, cb, s) {
594
+ var t = this, w;
595
+
596
+ w = t.open({
597
+ title : t,
598
+ type : 'alert',
599
+ button_func : function(s) {
600
+ if (cb)
601
+ cb.call(s || t, s);
602
+
603
+ t.close(null, w.id);
604
+ },
605
+ content : DOM.encode(t.editor.getLang(txt, txt)),
606
+ inline : 1,
607
+ width : 400,
608
+ height : 130
609
+ });
610
+ },
611
+
612
+ confirm : function(txt, cb, s) {
613
+ var t = this, w;
614
+
615
+ w = t.open({
616
+ title : t,
617
+ type : 'confirm',
618
+ button_func : function(s) {
619
+ if (cb)
620
+ cb.call(s || t, s);
621
+
622
+ t.close(null, w.id);
623
+ },
624
+ content : DOM.encode(t.editor.getLang(txt, txt)),
625
+ inline : 1,
626
+ width : 400,
627
+ height : 130
628
+ });
629
+ },
630
+
631
+ // Internal functions
632
+
633
+ _findId : function(w) {
634
+ var t = this;
635
+
636
+ if (typeof(w) == 'string')
637
+ return w;
638
+
639
+ each(t.windows, function(wo) {
640
+ var ifr = DOM.get(wo.id + '_ifr');
641
+
642
+ if (ifr && w == ifr.contentWindow) {
643
+ w = wo.id;
644
+ return false;
645
+ }
646
+ });
647
+
648
+ return w;
649
+ },
650
+
651
+ _fixIELayout : function(id, s) {
652
+ var w, img;
653
+
654
+ if (!tinymce.isIE6)
655
+ return;
656
+
657
+ // Fixes the bug where hover flickers and does odd things in IE6
658
+ each(['n','s','w','e','nw','ne','sw','se'], function(v) {
659
+ var e = DOM.get(id + '_resize_' + v);
660
+
661
+ DOM.setStyles(e, {
662
+ width : s ? e.clientWidth : '',
663
+ height : s ? e.clientHeight : '',
664
+ cursor : DOM.getStyle(e, 'cursor', 1)
665
+ });
666
+
667
+ DOM.setStyle(id + "_bottom", 'bottom', '-1px');
668
+
669
+ e = 0;
670
+ });
671
+
672
+ // Fixes graphics glitch
673
+ if (w = this.windows[id]) {
674
+ // Fixes rendering bug after resize
675
+ w.element.hide();
676
+ w.element.show();
677
+
678
+ // Forced a repaint of the window
679
+ //DOM.get(id).style.filter = '';
680
+
681
+ // IE has a bug where images used in CSS won't get loaded
682
+ // sometimes when the cache in the browser is disabled
683
+ // This fix tries to solve it by loading the images using the image object
684
+ each(DOM.select('div,a', id), function(e, i) {
685
+ if (e.currentStyle.backgroundImage != 'none') {
686
+ img = new Image();
687
+ img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1');
688
+ }
689
+ });
690
+
691
+ DOM.get(id).style.filter = '';
692
+ }
693
+ }
694
+ });
695
+
696
+ // Register plugin
697
+ tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups);
698
+ })();
699
+
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif ADDED
Binary file
tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Clearlooks 2 */
2
+
3
+ /* Reset */
4
+ .clearlooks2, .clearlooks2 div, .clearlooks2 span, .clearlooks2 a {vertical-align:baseline; text-align:left; position:absolute; border:0; padding:0; margin:0; background:transparent; font-family:Arial,Verdana; font-size:11px; color:#000; text-decoration:none; font-weight:normal; width:auto; height:auto; overflow:hidden; display:block}
5
+
6
+ /* General */
7
+ .clearlooks2 {position:absolute; direction:ltr}
8
+ .clearlooks2 .mceWrapper {position:static}
9
+ .mceEventBlocker {position:fixed; left:0; top:0; background:url(img/horizontal.gif) no-repeat 0 -75px; width:100%; height:100%}
10
+ .clearlooks2 .mcePlaceHolder {border:1px solid #000; background:#888; top:0; left:0; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50)}
11
+ .clearlooks2_modalBlocker {position:fixed; left:0; top:0; width:100%; height:100%; background:#FFF; opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60); display:none}
12
+
13
+ /* Top */
14
+ .clearlooks2 .mceTop, .clearlooks2 .mceTop div {top:0; width:100%; height:23px}
15
+ .clearlooks2 .mceTop .mceLeft {width:6px; background:url(img/corners.gif)}
16
+ .clearlooks2 .mceTop .mceCenter {right:6px; width:100%; height:23px; background:url(img/horizontal.gif) 12px 0; clip:rect(auto auto auto 12px)}
17
+ .clearlooks2 .mceTop .mceRight {right:0; width:6px; height:23px; background:url(img/corners.gif) -12px 0}
18
+ .clearlooks2 .mceTop span {width:100%; text-align:center; vertical-align:middle; line-height:23px; font-weight:bold}
19
+ .clearlooks2 .mceFocus .mceTop .mceLeft {background:url(img/corners.gif) -6px 0}
20
+ .clearlooks2 .mceFocus .mceTop .mceCenter {background:url(img/horizontal.gif) 0 -23px}
21
+ .clearlooks2 .mceFocus .mceTop .mceRight {background:url(img/corners.gif) -18px 0}
22
+ .clearlooks2 .mceFocus .mceTop span {color:#FFF}
23
+
24
+ /* Middle */
25
+ .clearlooks2 .mceMiddle, .clearlooks2 .mceMiddle div {top:0}
26
+ .clearlooks2 .mceMiddle {width:100%; height:100%; clip:rect(23px auto auto auto)}
27
+ .clearlooks2 .mceMiddle .mceLeft {left:0; width:5px; height:100%; background:url(img/vertical.gif) -5px 0}
28
+ .clearlooks2 .mceMiddle span {top:23px; left:5px; width:100%; height:100%; background:#FFF}
29
+ .clearlooks2 .mceMiddle .mceRight {right:0; width:5px; height:100%; background:url(img/vertical.gif)}
30
+
31
+ /* Bottom */
32
+ .clearlooks2 .mceBottom, .clearlooks2 .mceBottom div {height:6px}
33
+ .clearlooks2 .mceBottom {left:0; bottom:0; width:100%}
34
+ .clearlooks2 .mceBottom div {top:0}
35
+ .clearlooks2 .mceBottom .mceLeft {left:0; width:5px; background:url(img/corners.gif) -34px -6px}
36
+ .clearlooks2 .mceBottom .mceCenter {left:5px; width:100%; background:url(img/horizontal.gif) 0 -46px}
37
+ .clearlooks2 .mceBottom .mceRight {right:0; width:5px; background: url(img/corners.gif) -34px 0}
38
+ .clearlooks2 .mceBottom span {display:none}
39
+ .clearlooks2 .mceStatusbar .mceBottom, .clearlooks2 .mceStatusbar .mceBottom div {height:23px}
40
+ .clearlooks2 .mceStatusbar .mceBottom .mceLeft {background:url(img/corners.gif) -29px 0}
41
+ .clearlooks2 .mceStatusbar .mceBottom .mceCenter {background:url(img/horizontal.gif) 0 -52px}
42
+ .clearlooks2 .mceStatusbar .mceBottom .mceRight {background:url(img/corners.gif) -24px 0}
43
+ .clearlooks2 .mceStatusbar .mceBottom span {display:block; left:7px; font-family:Arial, Verdana; font-size:11px; line-height:23px}
44
+
45
+ /* Actions */
46
+ .clearlooks2 a {width:29px; height:16px; top:3px;}
47
+ .clearlooks2 .mceClose {right:6px; background:url(img/buttons.gif) -87px 0}
48
+ .clearlooks2 .mceMin {display:none; right:68px; background:url(img/buttons.gif) 0 0}
49
+ .clearlooks2 .mceMed {display:none; right:37px; background:url(img/buttons.gif) -29px 0}
50
+ .clearlooks2 .mceMax {display:none; right:37px; background:url(img/buttons.gif) -58px 0}
51
+ .clearlooks2 .mceMove {display:none;width:100%;cursor:move;background:url(img/corners.gif) no-repeat -100px -100px}
52
+ .clearlooks2 .mceMovable .mceMove {display:block}
53
+ .clearlooks2 .mceFocus .mceClose {right:6px; background:url(img/buttons.gif) -87px -16px}
54
+ .clearlooks2 .mceFocus .mceMin {right:68px; background:url(img/buttons.gif) 0 -16px}
55
+ .clearlooks2 .mceFocus .mceMed {right:37px; background:url(img/buttons.gif) -29px -16px}
56
+ .clearlooks2 .mceFocus .mceMax {right:37px; background:url(img/buttons.gif) -58px -16px}
57
+ .clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
58
+ .clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
59
+ .clearlooks2 .mceFocus .mceMin:hover {right:68px; background:url(img/buttons.gif) 0 -32px}
60
+ .clearlooks2 .mceFocus .mceMed:hover {right:37px; background:url(img/buttons.gif) -29px -32px}
61
+ .clearlooks2 .mceFocus .mceMax:hover {right:37px; background:url(img/buttons.gif) -58px -32px}
62
+
63
+ /* Resize */
64
+ .clearlooks2 .mceResize {top:auto; left:auto; display:none; width:5px; height:5px; background:url(img/horizontal.gif) no-repeat 0 -75px}
65
+ .clearlooks2 .mceResizable .mceResize {display:block}
66
+ .clearlooks2 .mceResizable .mceMin, .clearlooks2 .mceMax {display:none}
67
+ .clearlooks2 .mceMinimizable .mceMin {display:block}
68
+ .clearlooks2 .mceMaximizable .mceMax {display:block}
69
+ .clearlooks2 .mceMaximized .mceMed {display:block}
70
+ .clearlooks2 .mceMaximized .mceMax {display:none}
71
+ .clearlooks2 a.mceResizeN {top:0; left:0; width:100%; cursor:n-resize}
72
+ .clearlooks2 a.mceResizeNW {top:0; left:0; cursor:nw-resize}
73
+ .clearlooks2 a.mceResizeNE {top:0; right:0; cursor:ne-resize}
74
+ .clearlooks2 a.mceResizeW {top:0; left:0; height:100%; cursor:w-resize;}
75
+ .clearlooks2 a.mceResizeE {top:0; right:0; height:100%; cursor:e-resize}
76
+ .clearlooks2 a.mceResizeS {bottom:0; left:0; width:100%; cursor:s-resize}
77
+ .clearlooks2 a.mceResizeSW {bottom:0; left:0; cursor:sw-resize}
78
+ .clearlooks2 a.mceResizeSE {bottom:0; right:0; cursor:se-resize}
79
+
80
+ /* Alert/Confirm */
81
+ .clearlooks2 .mceButton {font-weight:bold; bottom:10px; width:80px; height:30px; background:url(img/button.gif); line-height:30px; vertical-align:middle; text-align:center; outline:0}
82
+ .clearlooks2 .mceMiddle .mceIcon {left:15px; top:35px; width:32px; height:32px}
83
+ .clearlooks2 .mceAlert .mceMiddle span, .clearlooks2 .mceConfirm .mceMiddle span {background:transparent;left:60px; top:35px; width:320px; height:50px; font-weight:bold; overflow:auto; white-space:normal}
84
+ .clearlooks2 a:hover {font-weight:bold;}
85
+ .clearlooks2 .mceAlert .mceMiddle, .clearlooks2 .mceConfirm .mceMiddle {background:#D6D7D5}
86
+ .clearlooks2 .mceAlert .mceOk {left:50%; top:auto; margin-left: -40px}
87
+ .clearlooks2 .mceAlert .mceIcon {background:url(img/alert.gif)}
88
+ .clearlooks2 .mceConfirm .mceOk {left:50%; top:auto; margin-left: -90px}
89
+ .clearlooks2 .mceConfirm .mceCancel {left:50%; top:auto}
90
+ .clearlooks2 .mceConfirm .mceIcon {background:url(img/confirm.gif)}
tiny_mce/plugins/inlinepopups/template.htm ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -->
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <title>Template for dialogs</title>
5
+ <link rel="stylesheet" type="text/css" href="skins/clearlooks2/window.css" />
6
+ </head>
7
+ <body>
8
+
9
+ <div class="mceEditor">
10
+ <div class="clearlooks2" style="width:400px; height:100px; left:10px;">
11
+ <div class="mceWrapper">
12
+ <div class="mceTop">
13
+ <div class="mceLeft"></div>
14
+ <div class="mceCenter"></div>
15
+ <div class="mceRight"></div>
16
+ <span>Blured</span>
17
+ </div>
18
+
19
+ <div class="mceMiddle">
20
+ <div class="mceLeft"></div>
21
+ <span>Content</span>
22
+ <div class="mceRight"></div>
23
+ </div>
24
+
25
+ <div class="mceBottom">
26
+ <div class="mceLeft"></div>
27
+ <div class="mceCenter"></div>
28
+ <div class="mceRight"></div>
29
+ <span>Statusbar text.</span>
30
+ </div>
31
+
32
+ <a class="mceMove" href="#"></a>
33
+ <a class="mceMin" href="#"></a>
34
+ <a class="mceMax" href="#"></a>
35
+ <a class="mceMed" href="#"></a>
36
+ <a class="mceClose" href="#"></a>
37
+ <a class="mceResize mceResizeN" href="#"></a>
38
+ <a class="mceResize mceResizeS" href="#"></a>
39
+ <a class="mceResize mceResizeW" href="#"></a>
40
+ <a class="mceResize mceResizeE" href="#"></a>
41
+ <a class="mceResize mceResizeNW" href="#"></a>
42
+ <a class="mceResize mceResizeNE" href="#"></a>
43
+ <a class="mceResize mceResizeSW" href="#"></a>
44
+ <a class="mceResize mceResizeSE" href="#"></a>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="clearlooks2" style="width:400px; height:100px; left:420px;">
49
+ <div class="mceWrapper mceMovable mceFocus">
50
+ <div class="mceTop">
51
+ <div class="mceLeft"></div>
52
+ <div class="mceCenter"></div>
53
+ <div class="mceRight"></div>
54
+ <span>Focused</span>
55
+ </div>
56
+
57
+ <div class="mceMiddle">
58
+ <div class="mceLeft"></div>
59
+ <span>Content</span>
60
+ <div class="mceRight"></div>
61
+ </div>
62
+
63
+ <div class="mceBottom">
64
+ <div class="mceLeft"></div>
65
+ <div class="mceCenter"></div>
66
+ <div class="mceRight"></div>
67
+ <span>Statusbar text.</span>
68
+ </div>
69
+
70
+ <a class="mceMove" href="#"></a>
71
+ <a class="mceMin" href="#"></a>
72
+ <a class="mceMax" href="#"></a>
73
+ <a class="mceMed" href="#"></a>
74
+ <a class="mceClose" href="#"></a>
75
+ <a class="mceResize mceResizeN" href="#"></a>
76
+ <a class="mceResize mceResizeS" href="#"></a>
77
+ <a class="mceResize mceResizeW" href="#"></a>
78
+ <a class="mceResize mceResizeE" href="#"></a>
79
+ <a class="mceResize mceResizeNW" href="#"></a>
80
+ <a class="mceResize mceResizeNE" href="#"></a>
81
+ <a class="mceResize mceResizeSW" href="#"></a>
82
+ <a class="mceResize mceResizeSE" href="#"></a>
83
+ </div>
84
+ </div>
85
+
86
+ <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:120px;">
87
+ <div class="mceWrapper mceMovable mceFocus mceStatusbar">
88
+ <div class="mceTop">
89
+ <div class="mceLeft"></div>
90
+ <div class="mceCenter"></div>
91
+ <div class="mceRight"></div>
92
+ <span>Statusbar</span>
93
+ </div>
94
+
95
+ <div class="mceMiddle">
96
+ <div class="mceLeft"></div>
97
+ <span>Content</span>
98
+ <div class="mceRight"></div>
99
+ </div>
100
+
101
+ <div class="mceBottom">
102
+ <div class="mceLeft"></div>
103
+ <div class="mceCenter"></div>
104
+ <div class="mceRight"></div>
105
+ <span>Statusbar text.</span>
106
+ </div>
107
+
108
+ <a class="mceMove" href="#"></a>
109
+ <a class="mceMin" href="#"></a>
110
+ <a class="mceMax" href="#"></a>
111
+ <a class="mceMed" href="#"></a>
112
+ <a class="mceClose" href="#"></a>
113
+ <a class="mceResize mceResizeN" href="#"></a>
114
+ <a class="mceResize mceResizeS" href="#"></a>
115
+ <a class="mceResize mceResizeW" href="#"></a>
116
+ <a class="mceResize mceResizeE" href="#"></a>
117
+ <a class="mceResize mceResizeNW" href="#"></a>
118
+ <a class="mceResize mceResizeNE" href="#"></a>
119
+ <a class="mceResize mceResizeSW" href="#"></a>
120
+ <a class="mceResize mceResizeSE" href="#"></a>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:120px;">
125
+ <div class="mceWrapper mceMovable mceFocus mceStatusbar mceResizable">
126
+ <div class="mceTop">
127
+ <div class="mceLeft"></div>
128
+ <div class="mceCenter"></div>
129
+ <div class="mceRight"></div>
130
+ <span>Statusbar, Resizable</span>
131
+ </div>
132
+
133
+ <div class="mceMiddle">
134
+ <div class="mceLeft"></div>
135
+ <span>Content</span>
136
+ <div class="mceRight"></div>
137
+ </div>
138
+
139
+ <div class="mceBottom">
140
+ <div class="mceLeft"></div>
141
+ <div class="mceCenter"></div>
142
+ <div class="mceRight"></div>
143
+ <span>Statusbar text.</span>
144
+ </div>
145
+
146
+ <a class="mceMove" href="#"></a>
147
+ <a class="mceMin" href="#"></a>
148
+ <a class="mceMax" href="#"></a>
149
+ <a class="mceMed" href="#"></a>
150
+ <a class="mceClose" href="#"></a>
151
+ <a class="mceResize mceResizeN" href="#"></a>
152
+ <a class="mceResize mceResizeS" href="#"></a>
153
+ <a class="mceResize mceResizeW" href="#"></a>
154
+ <a class="mceResize mceResizeE" href="#"></a>
155
+ <a class="mceResize mceResizeNW" href="#"></a>
156
+ <a class="mceResize mceResizeNE" href="#"></a>
157
+ <a class="mceResize mceResizeSW" href="#"></a>
158
+ <a class="mceResize mceResizeSE" href="#"></a>
159
+ </div>
160
+ </div>
161
+
162
+ <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:230px;">
163
+ <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximizable">
164
+ <div class="mceTop">
165
+ <div class="mceLeft"></div>
166
+ <div class="mceCenter"></div>
167
+ <div class="mceRight"></div>
168
+ <span>Resizable, Maximizable</span>
169
+ </div>
170
+
171
+ <div class="mceMiddle">
172
+ <div class="mceLeft"></div>
173
+ <span>Content</span>
174
+ <div class="mceRight"></div>
175
+ </div>
176
+
177
+ <div class="mceBottom">
178
+ <div class="mceLeft"></div>
179
+ <div class="mceCenter"></div>
180
+ <div class="mceRight"></div>
181
+ <span>Statusbar text.</span>
182
+ </div>
183
+
184
+ <a class="mceMove" href="#"></a>
185
+ <a class="mceMin" href="#"></a>
186
+ <a class="mceMax" href="#"></a>
187
+ <a class="mceMed" href="#"></a>
188
+ <a class="mceClose" href="#"></a>
189
+ <a class="mceResize mceResizeN" href="#"></a>
190
+ <a class="mceResize mceResizeS" href="#"></a>
191
+ <a class="mceResize mceResizeW" href="#"></a>
192
+ <a class="mceResize mceResizeE" href="#"></a>
193
+ <a class="mceResize mceResizeNW" href="#"></a>
194
+ <a class="mceResize mceResizeNE" href="#"></a>
195
+ <a class="mceResize mceResizeSW" href="#"></a>
196
+ <a class="mceResize mceResizeSE" href="#"></a>
197
+ </div>
198
+ </div>
199
+
200
+ <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:230px;">
201
+ <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximizable">
202
+ <div class="mceTop">
203
+ <div class="mceLeft"></div>
204
+ <div class="mceCenter"></div>
205
+ <div class="mceRight"></div>
206
+ <span>Blurred, Maximizable, Statusbar, Resizable</span>
207
+ </div>
208
+
209
+ <div class="mceMiddle">
210
+ <div class="mceLeft"></div>
211
+ <span>Content</span>
212
+ <div class="mceRight"></div>
213
+ </div>
214
+
215
+ <div class="mceBottom">
216
+ <div class="mceLeft"></div>
217
+ <div class="mceCenter"></div>
218
+ <div class="mceRight"></div>
219
+ <span>Statusbar text.</span>
220
+ </div>
221
+
222
+ <a class="mceMove" href="#"></a>
223
+ <a class="mceMin" href="#"></a>
224
+ <a class="mceMax" href="#"></a>
225
+ <a class="mceMed" href="#"></a>
226
+ <a class="mceClose" href="#"></a>
227
+ <a class="mceResize mceResizeN" href="#"></a>
228
+ <a class="mceResize mceResizeS" href="#"></a>
229
+ <a class="mceResize mceResizeW" href="#"></a>
230
+ <a class="mceResize mceResizeE" href="#"></a>
231
+ <a class="mceResize mceResizeNW" href="#"></a>
232
+ <a class="mceResize mceResizeNE" href="#"></a>
233
+ <a class="mceResize mceResizeSW" href="#"></a>
234
+ <a class="mceResize mceResizeSE" href="#"></a>
235
+ </div>
236
+ </div>
237
+
238
+ <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:340px;">
239
+ <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximized mceMinimizable mceMaximizable">
240
+ <div class="mceTop">
241
+ <div class="mceLeft"></div>
242
+ <div class="mceCenter"></div>
243
+ <div class="mceRight"></div>
244
+ <span>Maximized, Maximizable, Minimizable</span>
245
+ </div>
246
+
247
+ <div class="mceMiddle">
248
+ <div class="mceLeft"></div>
249
+ <span>Content</span>
250
+ <div class="mceRight"></div>
251
+ </div>
252
+
253
+ <div class="mceBottom">
254
+ <div class="mceLeft"></div>
255
+ <div class="mceCenter"></div>
256
+ <div class="mceRight"></div>
257
+ <span>Statusbar text.</span>
258
+ </div>
259
+
260
+ <a class="mceMove" href="#"></a>
261
+ <a class="mceMin" href="#"></a>
262
+ <a class="mceMax" href="#"></a>
263
+ <a class="mceMed" href="#"></a>
264
+ <a class="mceClose" href="#"></a>
265
+ <a class="mceResize mceResizeN" href="#"></a>
266
+ <a class="mceResize mceResizeS" href="#"></a>
267
+ <a class="mceResize mceResizeW" href="#"></a>
268
+ <a class="mceResize mceResizeE" href="#"></a>
269
+ <a class="mceResize mceResizeNW" href="#"></a>
270
+ <a class="mceResize mceResizeNE" href="#"></a>
271
+ <a class="mceResize mceResizeSW" href="#"></a>
272
+ <a class="mceResize mceResizeSE" href="#"></a>
273
+ </div>
274
+ </div>
275
+
276
+ <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:340px;">
277
+ <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximized mceMinimizable mceMaximizable">
278
+ <div class="mceTop">
279
+ <div class="mceLeft"></div>
280
+ <div class="mceCenter"></div>
281
+ <div class="mceRight"></div>
282
+ <span>Blured</span>
283
+ </div>
284
+
285
+ <div class="mceMiddle">
286
+ <div class="mceLeft"></div>
287
+ <span>Content</span>
288
+ <div class="mceRight"></div>
289
+ </div>
290
+
291
+ <div class="mceBottom">
292
+ <div class="mceLeft"></div>
293
+ <div class="mceCenter"></div>
294
+ <div class="mceRight"></div>
295
+ <span>Statusbar text.</span>
296
+ </div>
297
+
298
+ <a class="mceMove" href="#"></a>
299
+ <a class="mceMin" href="#"></a>
300
+ <a class="mceMax" href="#"></a>
301
+ <a class="mceMed" href="#"></a>
302
+ <a class="mceClose" href="#"></a>
303
+ <a class="mceResize mceResizeN" href="#"></a>
304
+ <a class="mceResize mceResizeS" href="#"></a>
305
+ <a class="mceResize mceResizeW" href="#"></a>
306
+ <a class="mceResize mceResizeE" href="#"></a>
307
+ <a class="mceResize mceResizeNW" href="#"></a>
308
+ <a class="mceResize mceResizeNE" href="#"></a>
309
+ <a class="mceResize mceResizeSW" href="#"></a>
310
+ <a class="mceResize mceResizeSE" href="#"></a>
311
+ </div>
312
+ </div>
313
+
314
+ <div class="clearlooks2" style="width:400px; height:130px; left:10px; top:450px;">
315
+ <div class="mceWrapper mceMovable mceFocus mceModal mceAlert">
316
+ <div class="mceTop">
317
+ <div class="mceLeft"></div>
318
+ <div class="mceCenter"></div>
319
+ <div class="mceRight"></div>
320
+ <span>Alert</span>
321
+ </div>
322
+
323
+ <div class="mceMiddle">
324
+ <div class="mceLeft"></div>
325
+ <span>
326
+ This is a very long error message. This is a very long error message.
327
+ This is a very long error message. This is a very long error message.
328
+ This is a very long error message. This is a very long error message.
329
+ This is a very long error message. This is a very long error message.
330
+ This is a very long error message. This is a very long error message.
331
+ This is a very long error message. This is a very long error message.
332
+ </span>
333
+ <div class="mceRight"></div>
334
+ <div class="mceIcon"></div>
335
+ </div>
336
+
337
+ <div class="mceBottom">
338
+ <div class="mceLeft"></div>
339
+ <div class="mceCenter"></div>
340
+ <div class="mceRight"></div>
341
+ </div>
342
+
343
+ <a class="mceMove" href="#"></a>
344
+ <a class="mceButton mceOk" href="#">Ok</a>
345
+ <a class="mceClose" href="#"></a>
346
+ </div>
347
+ </div>
348
+
349
+ <div class="clearlooks2" style="width:400px; height:130px; left:420px; top:450px;">
350
+ <div class="mceWrapper mceMovable mceFocus mceModal mceConfirm">
351
+ <div class="mceTop">
352
+ <div class="mceLeft"></div>
353
+ <div class="mceCenter"></div>
354
+ <div class="mceRight"></div>
355
+ <span>Confirm</span>
356
+ </div>
357
+
358
+ <div class="mceMiddle">
359
+ <div class="mceLeft"></div>
360
+ <span>
361
+ This is a very long error message. This is a very long error message.
362
+ This is a very long error message. This is a very long error message.
363
+ This is a very long error message. This is a very long error message.
364
+ This is a very long error message. This is a very long error message.
365
+ This is a very long error message. This is a very long error message.
366
+ This is a very long error message. This is a very long error message.
367
+ </span>
368
+ <div class="mceRight"></div>
369
+ <div class="mceIcon"></div>
370
+ </div>
371
+
372
+ <div class="mceBottom">
373
+ <div class="mceLeft"></div>
374
+ <div class="mceCenter"></div>
375
+ <div class="mceRight"></div>
376
+ </div>
377
+
378
+ <a class="mceMove" href="#"></a>
379
+ <a class="mceButton mceOk" href="#">Ok</a>
380
+ <a class="mceButton mceCancel" href="#">Cancel</a>
381
+ <a class="mceClose" href="#"></a>
382
+ </div>
383
+ </div>
384
+ </div>
385
+
386
+ </body>
387
+ </html>
tiny_mce/plugins/legacyoutput/editor_plugin.js ADDED
@@ -0,0 +1 @@
 
1
+ (function(a){a.onAddEditor.addToTop(function(c,b){b.settings.inline_styles=false});a.create("tinymce.plugins.LegacyOutput",{init:function(b){b.onInit.add(function(){var c="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",e=a.explode(b.settings.font_size_style_values),d=b.schema;b.formatter.register({alignleft:{selector:c,attributes:{align:"left"}},aligncenter:{selector:c,attributes:{align:"center"}},alignright:{selector:c,attributes:{align:"right"}},alignfull:{selector:c,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:true}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:true}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(f){return a.inArray(e,f.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}});a.each("b,i,u,strike".split(","),function(f){d.addValidElements(f+"[*]")});if(!d.getElementRule("font")){d.addValidElements("font[face|size|color|style]")}a.each(c.split(","),function(f){var h=d.getElementRule(f),g;if(h){if(!h.attributes.align){h.attributes.align={};h.attributesOrder.push("align")}}});b.onNodeChange.add(function(g,k){var j,f,h,i;f=g.dom.getParent(g.selection.getNode(),"font");if(f){h=f.face;i=f.size}if(j=k.get("fontselect")){j.select(function(l){return l==h})}if(j=k.get("fontsizeselect")){j.select(function(m){var l=a.inArray(e,m.fontSize);return l+1==i})}})})},getInfo:function(){return{longname:"LegacyOutput",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput",version:a.majorVersion+"."+a.minorVersion}}});a.PluginManager.add("legacyoutput",a.plugins.LegacyOutput)})(tinymce);
tiny_mce/plugins/legacyoutput/editor_plugin_src.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * editor_plugin_src.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under LGPL License.
6
+ *
7
+ * License: http://tinymce.moxiecode.com/license
8
+ * Contributing: http://tinymce.moxiecode.com/contributing
9
+ *
10
+ * This plugin will force TinyMCE to produce deprecated legacy output such as font elements, u elements, align
11
+ * attributes and so forth. There are a few cases where these old items might be needed for example in email applications or with Flash
12
+ *
13
+ * However you should NOT use this plugin if you are building some system that produces web contents such as a CMS. All these elements are
14
+ * not apart of the newer specifications for HTML and XHTML.
15
+ */
16
+
17
+ (function(tinymce) {
18
+ // Override inline_styles setting to force TinyMCE to produce deprecated contents
19
+ tinymce.onAddEditor.addToTop(function(tinymce, editor) {
20
+ editor.settings.inline_styles = false;
21
+ });
22
+
23
+ // Create the legacy ouput plugin
24
+ tinymce.create('tinymce.plugins.LegacyOutput', {
25
+ init : function(editor) {
26
+ editor.onInit.add(function() {
27
+ var alignElements = 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
28
+ fontSizes = tinymce.explode(editor.settings.font_size_style_values),
29
+ schema = editor.schema;
30
+
31
+ // Override some internal formats to produce legacy elements and attributes
32
+ editor.formatter.register({
33
+ // Change alignment formats to use the deprecated align attribute
34
+ alignleft : {selector : alignElements, attributes : {align : 'left'}},
35
+ aligncenter : {selector : alignElements, attributes : {align : 'center'}},
36
+ alignright : {selector : alignElements, attributes : {align : 'right'}},
37
+ alignfull : {selector : alignElements, attributes : {align : 'justify'}},
38
+
39
+ // Change the basic formatting elements to use deprecated element types
40
+ bold : [
41
+ {inline : 'b', remove : 'all'},
42
+ {inline : 'strong', remove : 'all'},
43
+ {inline : 'span', styles : {fontWeight : 'bold'}}
44
+ ],
45
+ italic : [
46
+ {inline : 'i', remove : 'all'},
47
+ {inline : 'em', remove : 'all'},
48
+ {inline : 'span', styles : {fontStyle : 'italic'}}
49
+ ],
50
+ underline : [
51
+ {inline : 'u', remove : 'all'},
52
+ {inline : 'span', styles : {textDecoration : 'underline'}, exact : true}
53
+ ],
54
+ strikethrough : [
55
+ {inline : 'strike', remove : 'all'},
56
+ {inline : 'span', styles : {textDecoration: 'line-through'}, exact : true}
57
+ ],
58
+
59
+ // Change font size and font family to use the deprecated font element
60
+ fontname : {inline : 'font', attributes : {face : '%value'}},
61
+ fontsize : {
62
+ inline : 'font',
63
+ attributes : {
64
+ size : function(vars) {
65
+ return tinymce.inArray(fontSizes, vars.value) + 1;
66
+ }
67
+ }
68
+ },
69
+
70
+ // Setup font elements for colors as well
71
+ forecolor : {inline : 'font', attributes : {color : '%value'}},
72
+ hilitecolor : {inline : 'font', styles : {backgroundColor : '%value'}}
73
+ });
74
+
75
+ // Check that deprecated elements are allowed if not add them
76
+ tinymce.each('b,i,u,strike'.split(','), function(name) {
77
+ schema.addValidElements(name + '[*]');
78
+ });
79
+
80
+ // Add font element if it's missing
81
+ if (!schema.getElementRule("font"))
82
+ schema.addValidElements("font[face|size|color|style]");
83
+
84
+ // Add the missing and depreacted align attribute for the serialization engine
85
+ tinymce.each(alignElements.split(','), function(name) {
86
+ var rule = schema.getElementRule(name), found;
87
+
88
+ if (rule) {
89
+ if (!rule.attributes.align) {
90
+ rule.attributes.align = {};
91
+ rule.attributesOrder.push('align');
92
+ }
93
+ }
94
+ });
95
+
96
+ // Listen for the onNodeChange event so that we can do special logic for the font size and font name drop boxes
97
+ editor.onNodeChange.add(function(editor, control_manager) {
98
+ var control, fontElm, fontName, fontSize;
99
+
100
+ // Find font element get it's name and size
101
+ fontElm = editor.dom.getParent(editor.selection.getNode(), 'font');
102
+ if (fontElm) {
103
+ fontName = fontElm.face;
104
+ fontSize = fontElm.size;
105
+ }
106
+
107
+ // Select/unselect the font name in droplist
108
+ if (control = control_manager.get('fontselect')) {
109
+ control.select(function(value) {
110
+ return value == fontName;
111
+ });
112
+ }
113
+
114
+ // Select/unselect the font size in droplist
115
+ if (control = control_manager.get('fontsizeselect')) {
116
+ control.select(function(value) {
117
+ var index = tinymce.inArray(fontSizes, value.fontSize);
118
+
119
+ return index + 1 == fontSize;
120
+ });
121
+ }
122
+ });
123
+ });
124
+ },
125
+
126
+ getInfo : function() {
127
+ return {
128
+ longname : 'LegacyOutput',
129
+ author : 'Moxiecode Systems AB',
130
+ authorurl : 'http://tinymce.moxiecode.com',
131
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput',
132
+ version : tinymce.majorVersion + "." + tinymce.minorVersion
133
+ };
134
+ }
135
+ });
136
+
137
+ // Register plugin
138
+ tinymce.PluginManager.add('legacyoutput', tinymce.plugins.LegacyOutput);
139
+ })(tinymce);
tiny_mce/plugins/noneditable/editor_plugin.js ADDED
@@ -0,0 +1 @@
 
1
+ (function(){var c=tinymce.dom.TreeWalker;var a="contenteditable",d="data-mce-"+a;var e=tinymce.VK;function b(n){var j=n.dom,p=n.selection,r,o="mce_noneditablecaret",r="\uFEFF";function m(t){var s;if(t.nodeType===1){s=t.getAttribute(d);if(s&&s!=="inherit"){return s}s=t.contentEditable;if(s!=="inherit"){return s}}return null}function g(s){var t;while(s){t=m(s);if(t){return t==="false"?s:null}s=s.parentNode}}function l(s){while(s){if(s.id===o){return s}s=s.parentNode}}function k(s){var t;if(s){t=new c(s,s);for(s=t.current();s;s=t.next()){if(s.nodeType===3){return s}}}}function f(v,u){var s,t;if(m(v)==="false"){if(j.isBlock(v)){p.select(v);return}}t=j.createRng();if(m(v)==="true"){if(!v.firstChild){v.appendChild(n.getDoc().createTextNode("\u00a0"))}v=v.firstChild;u=true}s=j.create("span",{id:o,"data-mce-bogus":true},r);if(u){v.parentNode.insertBefore(s,v)}else{j.insertAfter(s,v)}t.setStart(s.firstChild,1);t.collapse(true);p.setRng(t);return s}function i(s){var v,t,u;if(s){rng=p.getRng(true);rng.setStartBefore(s);rng.setEndBefore(s);v=k(s);if(v&&v.nodeValue.charAt(0)==r){v=v.deleteData(0,1)}j.remove(s,true);p.setRng(rng)}else{t=l(p.getStart());while((s=j.get(o))&&s!==u){if(t!==s){v=k(s);if(v&&v.nodeValue.charAt(0)==r){v=v.deleteData(0,1)}j.remove(s,true)}u=s}}}function q(){var s,w,u,t,v;function x(B,D){var A,F,E,C,z;A=t.startContainer;F=t.startOffset;if(A.nodeType==3){z=A.nodeValue.length;if((F>0&&F<z)||(D?F==z:F==0)){return}}else{if(F<A.childNodes.length){var G=!D&&F>0?F-1:F;A=A.childNodes[G];if(A.hasChildNodes()){A=A.firstChild}}else{return !D?B:null}}E=new c(A,B);while(C=E[D?"prev":"next"]()){if(C.nodeType===3&&C.nodeValue.length>0){return}else{if(m(C)==="true"){return C}}}return B}i();u=p.isCollapsed();s=g(p.getStart());w=g(p.getEnd());if(s||w){t=p.getRng(true);if(u){s=s||w;var y=p.getStart();if(v=x(s,true)){f(v,true)}else{if(v=x(s,false)){f(v,false)}else{p.select(s)}}}else{t=p.getRng(true);if(s){t.setStartBefore(s)}if(w){t.setEndAfter(w)}p.setRng(t)}}}function h(z,B){var F=B.keyCode,x,C,D,v;function u(H,G){while(H=H[G?"previousSibling":"nextSibling"]){if(H.nodeType!==3||H.nodeValue.length>0){return H}}}function y(G,H){p.select(G);p.collapse(H)}function t(K){var J,I,M,H;function G(O){var N=I;while(N){if(N===O){return}N=N.parentNode}j.remove(O);q()}function L(){var O,P,N=z.schema.getNonEmptyElements();P=new tinymce.dom.TreeWalker(I,z.getBody());while(O=(K?P.prev():P.next())){if(N[O.nodeName.toLowerCase()]){break}if(O.nodeType===3&&tinymce.trim(O.nodeValue).length>0){break}if(m(O)==="false"){G(O);return true}}if(g(O)){return true}return false}if(p.isCollapsed()){J=p.getRng(true);I=J.startContainer;M=J.startOffset;I=l(I)||I;if(H=g(I)){G(H);return false}if(I.nodeType==3&&(K?M>0:M<I.nodeValue.length)){return true}if(I.nodeType==1){I=I.childNodes[M]||I}if(L()){return false}}return true}D=p.getStart();v=p.getEnd();x=g(D)||g(v);if(x&&(F<112||F>124)&&F!=e.DELETE&&F!=e.BACKSPACE){if((tinymce.isMac?B.metaKey:B.ctrlKey)&&(F==67||F==88||F==86)){return}B.preventDefault();if(F==e.LEFT||F==e.RIGHT){var w=F==e.LEFT;if(z.dom.isBlock(x)){var A=w?x.previousSibling:x.nextSibling;var s=new c(A,A);var E=w?s.prev():s.next();y(E,!w)}else{y(x,w)}}}else{if(F==e.LEFT||F==e.RIGHT||F==e.BACKSPACE||F==e.DELETE){C=l(D);if(C){if(F==e.LEFT||F==e.BACKSPACE){x=u(C,true);if(x&&m(x)==="false"){B.preventDefault();if(F==e.LEFT){y(x,true)}else{j.remove(x);return}}else{i(C)}}if(F==e.RIGHT||F==e.DELETE){x=u(C);if(x&&m(x)==="false"){B.preventDefault();if(F==e.RIGHT){y(x,false)}else{j.remove(x);return}}else{i(C)}}}if((F==e.BACKSPACE||F==e.DELETE)&&!t(F==e.BACKSPACE)){B.preventDefault();return false}}}}n.onMouseDown.addToTop(function(s,u){var t=s.selection.getNode();if(m(t)==="false"&&t==u.target){q()}});n.onMouseUp.addToTop(q);n.onKeyDown.addToTop(h);n.onKeyUp.addToTop(q)}tinymce.create("tinymce.plugins.NonEditablePlugin",{init:function(i,k){var h,g,j;function f(m,n){var o=j.length,p=n.content,l=tinymce.trim(g);if(n.format=="raw"){return}while(o--){p=p.replace(j[o],function(s){var r=arguments,q=r[r.length-2];if(q>0&&p.charAt(q-1)=='"'){return s}return'<span class="'+l+'" data-mce-content="'+m.dom.encode(r[0])+'">'+m.dom.encode(typeof(r[1])==="string"?r[1]:r[0])+"</span>"})}n.content=p}h=" "+tinymce.trim(i.getParam("noneditable_editable_class","mceEditable"))+" ";g=" "+tinymce.trim(i.getParam("noneditable_noneditable_class","mceNonEditable"))+" ";j=i.getParam("noneditable_regexp");if(j&&!j.length){j=[j]}i.onPreInit.add(function(){b(i);if(j){i.selection.onBeforeSetContent.add(f);i.onBeforeSetContent.add(f)}i.parser.addAttributeFilter("class",function(l){var m=l.length,n,o;while(m--){o=l[m];n=" "+o.attr("class")+" ";if(n.indexOf(h)!==-1){o.attr(d,"true")}else{if(n.indexOf(g)!==-1){o.attr(d,"false")}}}});i.serializer.addAttributeFilter(d,function(l,m){var n=l.length,o;while(n--){o=l[n];if(j&&o.attr("data-mce-content")){o.name="#text";o.type=3;o.raw=true;o.value=o.attr("data-mce-content")}else{o.attr(a,null);o.attr(d,null)}}});i.parser.addAttributeFilter(a,function(l,m){var n=l.length,o;while(n--){o=l[n];o.attr(d,o.attr(a));o.attr(a,null)}})})},getInfo:function(){return{longname:"Non editable elements",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("noneditable",tinymce.plugins.NonEditablePlugin)})();
tiny_mce/plugins/noneditable/editor_plugin_src.js ADDED
@@ -0,0 +1,537 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * editor_plugin_src.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under LGPL License.
6
+ *
7
+ * License: http://tinymce.moxiecode.com/license
8
+ * Contributing: http://tinymce.moxiecode.com/contributing
9
+ */
10
+
11
+ (function() {
12
+ var TreeWalker = tinymce.dom.TreeWalker;
13
+ var externalName = 'contenteditable', internalName = 'data-mce-' + externalName;
14
+ var VK = tinymce.VK;
15
+
16
+ function handleContentEditableSelection(ed) {
17
+ var dom = ed.dom, selection = ed.selection, invisibleChar, caretContainerId = 'mce_noneditablecaret', invisibleChar = '\uFEFF';
18
+
19
+ // Returns the content editable state of a node "true/false" or null
20
+ function getContentEditable(node) {
21
+ var contentEditable;
22
+
23
+ // Ignore non elements
24
+ if (node.nodeType === 1) {
25
+ // Check for fake content editable
26
+ contentEditable = node.getAttribute(internalName);
27
+ if (contentEditable && contentEditable !== "inherit") {
28
+ return contentEditable;
29
+ }
30
+
31
+ // Check for real content editable
32
+ contentEditable = node.contentEditable;
33
+ if (contentEditable !== "inherit") {
34
+ return contentEditable;
35
+ }
36
+ }
37
+
38
+ return null;
39
+ };
40
+
41
+ // Returns the noneditable parent or null if there is a editable before it or if it wasn't found
42
+ function getNonEditableParent(node) {
43
+ var state;
44
+
45
+ while (node) {
46
+ state = getContentEditable(node);
47
+ if (state) {
48
+ return state === "false" ? node : null;
49
+ }
50
+
51
+ node = node.parentNode;
52
+ }
53
+ };
54
+
55
+ // Get caret container parent for the specified node
56
+ function getParentCaretContainer(node) {
57
+ while (node) {
58
+ if (node.id === caretContainerId) {
59
+ return node;
60
+ }
61
+
62
+ node = node.parentNode;
63
+ }
64
+ };
65
+
66
+ // Finds the first text node in the specified node
67
+ function findFirstTextNode(node) {
68
+ var walker;
69
+
70
+ if (node) {
71
+ walker = new TreeWalker(node, node);
72
+
73
+ for (node = walker.current(); node; node = walker.next()) {
74
+ if (node.nodeType === 3) {
75
+ return node;
76
+ }
77
+ }
78
+ }
79
+ };
80
+
81
+ // Insert caret container before/after target or expand selection to include block
82
+ function insertCaretContainerOrExpandToBlock(target, before) {
83
+ var caretContainer, rng;
84
+
85
+ // Select block
86
+ if (getContentEditable(target) === "false") {
87
+ if (dom.isBlock(target)) {
88
+ selection.select(target);
89
+ return;
90
+ }
91
+ }
92
+
93
+ rng = dom.createRng();
94
+
95
+ if (getContentEditable(target) === "true") {
96
+ if (!target.firstChild) {
97
+ target.appendChild(ed.getDoc().createTextNode('\u00a0'));
98
+ }
99
+
100
+ target = target.firstChild;
101
+ before = true;
102
+ }
103
+
104
+ //caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true, style:'border: 1px solid red'}, invisibleChar);
105
+ caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true}, invisibleChar);
106
+
107
+ if (before) {
108
+ target.parentNode.insertBefore(caretContainer, target);
109
+ } else {
110
+ dom.insertAfter(caretContainer, target);
111
+ }
112
+
113
+ rng.setStart(caretContainer.firstChild, 1);
114
+ rng.collapse(true);
115
+ selection.setRng(rng);
116
+
117
+ return caretContainer;
118
+ };
119
+
120
+ // Removes any caret container except the one we might be in
121
+ function removeCaretContainer(caretContainer) {
122
+ var child, currentCaretContainer, lastContainer;
123
+
124
+ if (caretContainer) {
125
+ rng = selection.getRng(true);
126
+ rng.setStartBefore(caretContainer);
127
+ rng.setEndBefore(caretContainer);
128
+
129
+ child = findFirstTextNode(caretContainer);
130
+ if (child && child.nodeValue.charAt(0) == invisibleChar) {
131
+ child = child.deleteData(0, 1);
132
+ }
133
+
134
+ dom.remove(caretContainer, true);
135
+
136
+ selection.setRng(rng);
137
+ } else {
138
+ currentCaretContainer = getParentCaretContainer(selection.getStart());
139
+ while ((caretContainer = dom.get(caretContainerId)) && caretContainer !== lastContainer) {
140
+ if (currentCaretContainer !== caretContainer) {
141
+ child = findFirstTextNode(caretContainer);
142
+ if (child && child.nodeValue.charAt(0) == invisibleChar) {
143
+ child = child.deleteData(0, 1);
144
+ }
145
+
146
+ dom.remove(caretContainer, true);
147
+ }
148
+
149
+ lastContainer = caretContainer;
150
+ }
151
+ }
152
+ };
153
+
154
+ // Modifies the selection to include contentEditable false elements or insert caret containers
155
+ function moveSelection() {
156
+ var nonEditableStart, nonEditableEnd, isCollapsed, rng, element;
157
+
158
+ // Checks if there is any contents to the left/right side of caret returns the noneditable element or any editable element if it finds one inside
159
+ function hasSideContent(element, left) {
160
+ var container, offset, walker, node, len;
161
+
162
+ container = rng.startContainer;
163
+ offset = rng.startOffset;
164
+
165
+ // If endpoint is in middle of text node then expand to beginning/end of element
166
+ if (container.nodeType == 3) {
167
+ len = container.nodeValue.length;
168
+ if ((offset > 0 && offset < len) || (left ? offset == len : offset == 0)) {
169
+ return;
170
+ }
171
+ } else {
172
+ // Can we resolve the node by index
173
+ if (offset < container.childNodes.length) {
174
+ // Browser represents caret position as the offset at the start of an element. When moving right
175
+ // this is the element we are moving into so we consider our container to be child node at offset-1
176
+ var pos = !left && offset > 0 ? offset-1 : offset;
177
+ container = container.childNodes[pos];
178
+ if (container.hasChildNodes()) {
179
+ container = container.firstChild;
180
+ }
181
+ } else {
182
+ // If not then the caret is at the last position in it's container and the caret container should be inserted after the noneditable element
183
+ return !left ? element : null;
184
+ }
185
+ }
186
+
187
+ // Walk left/right to look for contents
188
+ walker = new TreeWalker(container, element);
189
+ while (node = walker[left ? 'prev' : 'next']()) {
190
+ if (node.nodeType === 3 && node.nodeValue.length > 0) {
191
+ return;
192
+ } else if (getContentEditable(node) === "true") {
193
+ // Found contentEditable=true element return this one to we can move the caret inside it
194
+ return node;
195
+ }
196
+ }
197
+
198
+ return element;
199
+ };
200
+
201
+ // Remove any existing caret containers
202
+ removeCaretContainer();
203
+
204
+ // Get noneditable start/end elements
205
+ isCollapsed = selection.isCollapsed();
206
+ nonEditableStart = getNonEditableParent(selection.getStart());
207
+ nonEditableEnd = getNonEditableParent(selection.getEnd());
208
+
209
+ // Is any fo the range endpoints noneditable
210
+ if (nonEditableStart || nonEditableEnd) {
211
+ rng = selection.getRng(true);
212
+
213
+ // If it's a caret selection then look left/right to see if we need to move the caret out side or expand
214
+ if (isCollapsed) {
215
+ nonEditableStart = nonEditableStart || nonEditableEnd;
216
+ var start = selection.getStart();
217
+ if (element = hasSideContent(nonEditableStart, true)) {
218
+ // We have no contents to the left of the caret then insert a caret container before the noneditable element
219
+ insertCaretContainerOrExpandToBlock(element, true);
220
+ } else if (element = hasSideContent(nonEditableStart, false)) {
221
+ // We have no contents to the right of the caret then insert a caret container after the noneditable element
222
+ insertCaretContainerOrExpandToBlock(element, false);
223
+ } else {
224
+ // We are in the middle of a noneditable so expand to select it
225
+ selection.select(nonEditableStart);
226
+ }
227
+ } else {
228
+ rng = selection.getRng(true);
229
+
230
+ // Expand selection to include start non editable element
231
+ if (nonEditableStart) {
232
+ rng.setStartBefore(nonEditableStart);
233
+ }
234
+
235
+ // Expand selection to include end non editable element
236
+ if (nonEditableEnd) {
237
+ rng.setEndAfter(nonEditableEnd);
238
+ }
239
+
240
+ selection.setRng(rng);
241
+ }
242
+ }
243
+ };
244
+
245
+ function handleKey(ed, e) {
246
+ var keyCode = e.keyCode, nonEditableParent, caretContainer, startElement, endElement;
247
+
248
+ function getNonEmptyTextNodeSibling(node, prev) {
249
+ while (node = node[prev ? 'previousSibling' : 'nextSibling']) {
250
+ if (node.nodeType !== 3 || node.nodeValue.length > 0) {
251
+ return node;
252
+ }
253
+ }
254
+ };
255
+
256
+ function positionCaretOnElement(element, start) {
257
+ selection.select(element);
258
+ selection.collapse(start);
259
+ }
260
+
261
+ function canDelete(backspace) {
262
+ var rng, container, offset, nonEditableParent;
263
+
264
+ function removeNodeIfNotParent(node) {
265
+ var parent = container;
266
+
267
+ while (parent) {
268
+ if (parent === node) {
269
+ return;
270
+ }
271
+
272
+ parent = parent.parentNode;
273
+ }
274
+
275
+ dom.remove(node);
276
+ moveSelection();
277
+ }
278
+
279
+ function isNextPrevTreeNodeNonEditable() {
280
+ var node, walker, nonEmptyElements = ed.schema.getNonEmptyElements();
281
+
282
+ walker = new tinymce.dom.TreeWalker(container, ed.getBody());
283
+ while (node = (backspace ? walker.prev() : walker.next())) {
284
+ // Found IMG/INPUT etc
285
+ if (nonEmptyElements[node.nodeName.toLowerCase()]) {
286
+ break;
287
+ }
288
+
289
+ // Found text node with contents
290
+ if (node.nodeType === 3 && tinymce.trim(node.nodeValue).length > 0) {
291
+ break;
292
+ }
293
+
294
+ // Found non editable node
295
+ if (getContentEditable(node) === "false") {
296
+ removeNodeIfNotParent(node);
297
+ return true;
298
+ }
299
+ }
300
+
301
+ // Check if the content node is within a non editable parent
302
+ if (getNonEditableParent(node)) {
303
+ return true;
304
+ }
305
+
306
+ return false;
307
+ }
308
+
309
+ if (selection.isCollapsed()) {
310
+ rng = selection.getRng(true);
311
+ container = rng.startContainer;
312
+ offset = rng.startOffset;
313
+ container = getParentCaretContainer(container) || container;
314
+
315
+ // Is in noneditable parent
316
+ if (nonEditableParent = getNonEditableParent(container)) {
317
+ removeNodeIfNotParent(nonEditableParent);
318
+ return false;
319
+ }
320
+
321
+ // Check if the caret is in the middle of a text node
322
+ if (container.nodeType == 3 && (backspace ? offset > 0 : offset < container.nodeValue.length)) {
323
+ return true;
324
+ }
325
+
326
+ // Resolve container index
327
+ if (container.nodeType == 1) {
328
+ container = container.childNodes[offset] || container;
329
+ }
330
+
331
+ // Check if previous or next tree node is non editable then block the event
332
+ if (isNextPrevTreeNodeNonEditable()) {
333
+ return false;
334
+ }
335
+ }
336
+
337
+ return true;
338
+ }
339
+
340
+ startElement = selection.getStart()
341
+ endElement = selection.getEnd();
342
+
343
+ // Disable all key presses in contentEditable=false except delete or backspace
344
+ nonEditableParent = getNonEditableParent(startElement) || getNonEditableParent(endElement);
345
+ if (nonEditableParent && (keyCode < 112 || keyCode > 124) && keyCode != VK.DELETE && keyCode != VK.BACKSPACE) {
346
+ // Is Ctrl+c, Ctrl+v or Ctrl+x then use default browser behavior
347
+ if ((tinymce.isMac ? e.metaKey : e.ctrlKey) && (keyCode == 67 || keyCode == 88 || keyCode == 86)) {
348
+ return;
349
+ }
350
+
351
+ e.preventDefault();
352
+
353
+ // Arrow left/right select the element and collapse left/right
354
+ if (keyCode == VK.LEFT || keyCode == VK.RIGHT) {
355
+ var left = keyCode == VK.LEFT;
356
+ // If a block element find previous or next element to position the caret
357
+ if (ed.dom.isBlock(nonEditableParent)) {
358
+ var targetElement = left ? nonEditableParent.previousSibling : nonEditableParent.nextSibling;
359
+ var walker = new TreeWalker(targetElement, targetElement);
360
+ var caretElement = left ? walker.prev() : walker.next();
361
+ positionCaretOnElement(caretElement, !left);
362
+ } else {
363
+ positionCaretOnElement(nonEditableParent, left);
364
+ }
365
+ }
366
+ } else {
367
+ // Is arrow left/right, backspace or delete
368
+ if (keyCode == VK.LEFT || keyCode == VK.RIGHT || keyCode == VK.BACKSPACE || keyCode == VK.DELETE) {
369
+ caretContainer = getParentCaretContainer(startElement);
370
+ if (caretContainer) {
371
+ // Arrow left or backspace
372
+ if (keyCode == VK.LEFT || keyCode == VK.BACKSPACE) {
373
+ nonEditableParent = getNonEmptyTextNodeSibling(caretContainer, true);
374
+
375
+ if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
376
+ e.preventDefault();
377
+
378
+ if (keyCode == VK.LEFT) {
379
+ positionCaretOnElement(nonEditableParent, true);
380
+ } else {
381
+ dom.remove(nonEditableParent);
382
+ return;
383
+ }
384
+ } else {
385
+ removeCaretContainer(caretContainer);
386
+ }
387
+ }
388
+
389
+ // Arrow right or delete
390
+ if (keyCode == VK.RIGHT || keyCode == VK.DELETE) {
391
+ nonEditableParent = getNonEmptyTextNodeSibling(caretContainer);
392
+
393
+ if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
394
+ e.preventDefault();
395
+
396
+ if (keyCode == VK.RIGHT) {
397
+ positionCaretOnElement(nonEditableParent, false);
398
+ } else {
399
+ dom.remove(nonEditableParent);
400
+ return;
401
+ }
402
+ } else {
403
+ removeCaretContainer(caretContainer);
404
+ }
405
+ }
406
+ }
407
+
408
+ if ((keyCode == VK.BACKSPACE || keyCode == VK.DELETE) && !canDelete(keyCode == VK.BACKSPACE)) {
409
+ e.preventDefault();
410
+ return false;
411
+ }
412
+ }
413
+ }
414
+ };
415
+
416
+ ed.onMouseDown.addToTop(function(ed, e) {
417
+ var node = ed.selection.getNode();
418
+
419
+ if (getContentEditable(node) === "false" && node == e.target) {
420
+ // Expand selection on mouse down we can't block the default event since it's used for drag/drop
421
+ moveSelection();
422
+ }
423
+ });
424
+
425
+ ed.onMouseUp.addToTop(moveSelection);
426
+ ed.onKeyDown.addToTop(handleKey);
427
+ ed.onKeyUp.addToTop(moveSelection);
428
+ };
429
+
430
+ tinymce.create('tinymce.plugins.NonEditablePlugin', {
431
+ init : function(ed, url) {
432
+ var editClass, nonEditClass, nonEditableRegExps;
433
+
434
+ // Converts configured regexps to noneditable span items
435
+ function convertRegExpsToNonEditable(ed, args) {
436
+ var i = nonEditableRegExps.length, content = args.content, cls = tinymce.trim(nonEditClass);
437
+
438
+ // Don't replace the variables when raw is used for example on undo/redo
439
+ if (args.format == "raw") {
440
+ return;
441
+ }
442
+
443
+ while (i--) {
444
+ content = content.replace(nonEditableRegExps[i], function(match) {
445
+ var args = arguments, index = args[args.length - 2];
446
+
447
+ // Is value inside an attribute then don't replace
448
+ if (index > 0 && content.charAt(index - 1) == '"') {
449
+ return match;
450
+ }
451
+
452
+ return '<span class="' + cls + '" data-mce-content="' + ed.dom.encode(args[0]) + '">' + ed.dom.encode(typeof(args[1]) === "string" ? args[1] : args[0]) + '</span>';
453
+ });
454
+ }
455
+
456
+ args.content = content;
457
+ };
458
+
459
+ editClass = " " + tinymce.trim(ed.getParam("noneditable_editable_class", "mceEditable")) + " ";
460
+ nonEditClass = " " + tinymce.trim(ed.getParam("noneditable_noneditable_class", "mceNonEditable")) + " ";
461
+
462
+ // Setup noneditable regexps array
463
+ nonEditableRegExps = ed.getParam("noneditable_regexp");
464
+ if (nonEditableRegExps && !nonEditableRegExps.length) {
465
+ nonEditableRegExps = [nonEditableRegExps];
466
+ }
467
+
468
+ ed.onPreInit.add(function() {
469
+ handleContentEditableSelection(ed);
470
+
471
+ if (nonEditableRegExps) {
472
+ ed.selection.onBeforeSetContent.add(convertRegExpsToNonEditable);
473
+ ed.onBeforeSetContent.add(convertRegExpsToNonEditable);
474
+ }
475
+
476
+ // Apply contentEditable true/false on elements with the noneditable/editable classes
477
+ ed.parser.addAttributeFilter('class', function(nodes) {
478
+ var i = nodes.length, className, node;
479
+
480
+ while (i--) {
481
+ node = nodes[i];
482
+ className = " " + node.attr("class") + " ";
483
+
484
+ if (className.indexOf(editClass) !== -1) {
485
+ node.attr(internalName, "true");
486
+ } else if (className.indexOf(nonEditClass) !== -1) {
487
+ node.attr(internalName, "false");
488
+ }
489
+ }
490
+ });
491
+
492
+ // Remove internal name
493
+ ed.serializer.addAttributeFilter(internalName, function(nodes, name) {
494
+ var i = nodes.length, node;
495
+
496
+ while (i--) {
497
+ node = nodes[i];
498
+
499
+ if (nonEditableRegExps && node.attr('data-mce-content')) {
500
+ node.name = "#text";
501
+ node.type = 3;
502
+ node.raw = true;
503
+ node.value = node.attr('data-mce-content');
504
+ } else {
505
+ node.attr(externalName, null);
506
+ node.attr(internalName, null);
507
+ }
508
+ }
509
+ });
510
+
511
+ // Convert external name into internal name
512
+ ed.parser.addAttributeFilter(externalName, function(nodes, name) {
513
+ var i = nodes.length, node;
514
+
515
+ while (i--) {
516
+ node = nodes[i];
517
+ node.attr(internalName, node.attr(externalName));
518
+ node.attr(externalName, null);
519
+ }
520
+ });
521
+ });
522
+ },
523
+
524
+ getInfo : function() {
525
+ return {
526
+ longname : 'Non editable elements',
527
+ author : 'Moxiecode Systems AB',
528
+ authorurl : 'http://tinymce.moxiecode.com',
529
+ infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',
530
+ version : tinymce.majorVersion + "." + tinymce.minorVersion
531
+ };
532
+ }
533
+ });
534
+
535
+ // Register plugin
536
+ tinymce.PluginManager.add('noneditable', tinymce.plugins.NonEditablePlugin);
537
+ })();
tiny_mce/plugins/paste/editor_plugin.js DELETED
@@ -1 +0,0 @@
1
- (function(){var c=tinymce.each,a={paste_auto_cleanup_on_paste:true,paste_enable_default_filters:true,paste_block_drop:false,paste_retain_style_properties:"none",paste_strip_class_attributes:"mso",paste_remove_spans:false,paste_remove_styles:false,paste_remove_styles_if_webkit:true,paste_convert_middot_lists:true,paste_convert_headers_to_strong:false,paste_dialog_width:"450",paste_dialog_height:"400",paste_text_use_dialog:false,paste_text_sticky:false,paste_text_sticky_default:false,paste_text_notifyalways:false,paste_text_linebreaktype:"combined",paste_text_replacements:[[/\u2026/g,"..."],[/[\x93\x94\u201c\u201d]/g,'"'],[/[\x60\x91\x92\u2018\u2019]/g,"'"]]};function b(d,e){return d.getParam(e,a[e])}tinymce.create("tinymce.plugins.PastePlugin",{init:function(d,e){var f=this;f.editor=d;f.url=e;f.onPreProcess=new tinymce.util.Dispatcher(f);f.onPostProcess=new tinymce.util.Dispatcher(f);f.onPreProcess.add(f._preProcess);f.onPostProcess.add(f._postProcess);f.onPreProcess.add(function(i,j){d.execCallback("paste_preprocess",i,j)});f.onPostProcess.add(function(i,j){d.execCallback("paste_postprocess",i,j)});d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){return false}});d.pasteAsPlainText=b(d,"paste_text_sticky_default");function h(l,j){var k=d.dom,i;f.onPreProcess.dispatch(f,l);l.node=k.create("div",0,l.content);if(tinymce.isGecko){i=d.selection.getRng(true);if(i.startContainer==i.endContainer&&i.startContainer.nodeType==3){if(l.node.childNodes.length===1&&/^(p|h[1-6]|pre)$/i.test(l.node.firstChild.nodeName)&&l.content.indexOf("__MCE_ITEM__")===-1){k.remove(l.node.firstChild,true)}}}f.onPostProcess.dispatch(f,l);l.content=d.serializer.serialize(l.node,{getInner:1,forced_root_block:""});if((!j)&&(d.pasteAsPlainText)){f._insertPlainText(l.content);if(!b(d,"paste_text_sticky")){d.pasteAsPlainText=false;d.controlManager.setActive("pastetext",false)}}else{f._insert(l.content)}}d.addCommand("mceInsertClipboardContent",function(i,j){h(j,true)});if(!b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(j,i){var k=tinymce.util.Cookie;d.pasteAsPlainText=!d.pasteAsPlainText;d.controlManager.setActive("pastetext",d.pasteAsPlainText);if((d.pasteAsPlainText)&&(!k.get("tinymcePasteText"))){if(b(d,"paste_text_sticky")){d.windowManager.alert(d.translate("paste.plaintext_mode_sticky"))}else{d.windowManager.alert(d.translate("paste.plaintext_mode"))}if(!b(d,"paste_text_notifyalways")){k.set("tinymcePasteText","1",new Date(new Date().getFullYear()+1,12,31))}}})}d.addButton("pastetext",{title:"paste.paste_text_desc",cmd:"mcePasteText"});d.addButton("selectall",{title:"paste.selectall_desc",cmd:"selectall"});function g(s){var l,p,j,t,k=d.selection,o=d.dom,q=d.getBody(),i,r;if(s.clipboardData||o.doc.dataTransfer){r=(s.clipboardData||o.doc.dataTransfer).getData("Text");if(d.pasteAsPlainText){s.preventDefault();h({content:o.encode(r).replace(/\r?\n/g,"<br />")});return}}if(o.get("_mcePaste")){return}l=o.add(q,"div",{id:"_mcePaste","class":"mcePaste","data-mce-bogus":"1"},"\uFEFF\uFEFF");if(q!=d.getDoc().body){i=o.getPos(d.selection.getStart(),q).y}else{i=q.scrollTop+o.getViewPort(d.getWin()).y}o.setStyles(l,{position:"absolute",left:tinymce.isGecko?-40:0,top:i-25,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){t=k.getRng();j=o.doc.body.createTextRange();j.moveToElementText(l);j.execCommand("Paste");o.remove(l);if(l.innerHTML==="\uFEFF\uFEFF"){d.execCommand("mcePasteWord");s.preventDefault();return}k.setRng(t);k.setContent("");setTimeout(function(){h({content:l.innerHTML})},0);return tinymce.dom.Event.cancel(s)}else{function m(n){n.preventDefault()}o.bind(d.getDoc(),"mousedown",m);o.bind(d.getDoc(),"keydown",m);p=d.selection.getRng();l=l.firstChild;j=d.getDoc().createRange();j.setStart(l,0);j.setEnd(l,2);k.setRng(j);window.setTimeout(function(){var u="",n;if(!o.select("div.mcePaste > div.mcePaste").length){n=o.select("div.mcePaste");c(n,function(w){var v=w.firstChild;if(v&&v.nodeName=="DIV"&&v.style.marginTop&&v.style.backgroundColor){o.remove(v,1)}c(o.select("span.Apple-style-span",w),function(x){o.remove(x,1)});c(o.select("br[data-mce-bogus]",w),function(x){o.remove(x)});if(w.parentNode.className!="mcePaste"){u+=w.innerHTML}})}else{u="<p>"+o.encode(r).replace(/\r?\n\r?\n/g,"</p><p>").replace(/\r?\n/g,"<br />")+"</p>"}c(o.select("div.mcePaste"),function(v){o.remove(v)});if(p){k.setRng(p)}h({content:u});o.unbind(d.getDoc(),"mousedown",m);o.unbind(d.getDoc(),"keydown",m)},0)}}if(b(d,"paste_auto_cleanup_on_paste")){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){g(j)}})}else{d.onPaste.addToTop(function(i,j){return g(j)})}}d.onInit.add(function(){d.controlManager.setActive("pastetext",d.pasteAsPlainText);if(b(d,"paste_block_drop")){d.dom.bind(d.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(i){i.preventDefault();i.stopPropagation();return false})}});f._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(g,e){var k=this.editor,j=e.content,p=tinymce.grep,n=tinymce.explode,f=tinymce.trim,l,i;function d(h){c(h,function(o){if(o.constructor==RegExp){j=j.replace(o,"")}else{j=j.replace(o[0],o[1])}})}if(k.settings.paste_enable_default_filters==false){return}if(tinymce.isIE&&document.documentMode>=9){d([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g,"$1"]]);d([[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}if(/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(j)||e.wordContent){e.wordContent=true;d([/^\s*(&nbsp;)+/gi,/(&nbsp;|<br[^>]*>)+\s*$/gi]);if(b(k,"paste_convert_headers_to_strong")){j=j.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi,"<p><strong>$1</strong></p>")}if(b(k,"paste_convert_middot_lists")){d([[/<!--\[if !supportLists\]-->/gi,"$&__MCE_ITEM__"],[/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi,"$1__MCE_ITEM__"],[/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi,"$1__MCE_ITEM__"]])}d([/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/&nbsp;/gi,"\u00a0"]]);do{l=j.length;j=j.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi,"$1")}while(l!=j.length);if(b(k,"paste_retain_style_properties").replace(/^none$/i,"").length==0){j=j.replace(/<\/?span[^>]*>/gi,"")}else{d([[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(o,h){return(h.length>0)?h.replace(/./," ").slice(Math.floor(h.length/2)).split("").join("\u00a0"):""}],[/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,function(t,h,r){var u=[],o=0,q=n(f(r).replace(/&quot;/gi,"'"),";");c(q,function(s){var w,y,z=n(s,":");function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}if(z.length==2){w=z[0].toLowerCase();y=z[1].toLowerCase();switch(w){case"mso-padding-alt":case"mso-padding-top-alt":case"mso-padding-right-alt":case"mso-padding-bottom-alt":case"mso-padding-left-alt":case"mso-margin-alt":case"mso-margin-top-alt":case"mso-margin-right-alt":case"mso-margin-bottom-alt":case"mso-margin-left-alt":case"mso-table-layout-alt":case"mso-height":case"mso-width":case"mso-vertical-align-alt":u[o++]=w.replace(/^mso-|-alt$/g,"")+":"+x(y);return;case"horiz-align":u[o++]="text-align:"+y;return;case"vert-align":u[o++]="vertical-align:"+y;return;case"font-color":case"mso-foreground":u[o++]="color:"+y;return;case"mso-background":case"mso-highlight":u[o++]="background:"+y;return;case"mso-default-height":u[o++]="min-height:"+x(y);return;case"mso-default-width":u[o++]="min-width:"+x(y);return;case"mso-padding-between-alt":u[o++]="border-collapse:separate;border-spacing:"+x(y);return;case"text-line-through":if((y=="single")||(y=="double")){u[o++]="text-decoration:line-through"}return;case"mso-zero-height":if(y=="yes"){u[o++]="display:none"}return}if(/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(w)){return}u[o++]=w+":"+z[1]}});if(o>0){return h+' style="'+u.join(";")+'"'}else{return h}}]])}}if(b(k,"paste_convert_headers_to_strong")){d([[/<h[1-6][^>]*>/gi,"<p><strong>"],[/<\/h[1-6][^>]*>/gi,"</strong></p>"]])}d([[/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi,""]]);i=b(k,"paste_strip_class_attributes");if(i!=="none"){function m(q,o){if(i==="all"){return""}var h=p(n(o.replace(/^(["'])(.*)\1$/,"$2")," "),function(r){return(/^(?!mso)/i.test(r))});return h.length?' class="'+h.join(" ")+'"':""}j=j.replace(/ class="([^"]+)"/gi,m);j=j.replace(/ class=([\-\w]+)/gi,m)}if(b(k,"paste_remove_spans")){j=j.replace(/<\/?span[^>]*>/gi,"")}e.content=j},_postProcess:function(g,i){var f=this,e=f.editor,h=e.dom,d;if(e.settings.paste_enable_default_filters==false){return}if(i.wordContent){c(h.select("a",i.node),function(j){if(!j.href||j.href.indexOf("#_Toc")!=-1){h.remove(j,1)}});if(b(e,"paste_convert_middot_lists")){f._convertLists(g,i)}d=b(e,"paste_retain_style_properties");if((tinymce.is(d,"string"))&&(d!=="all")&&(d!=="*")){d=tinymce.explode(d.replace(/^none$/i,""));c(h.select("*",i.node),function(m){var n={},k=0,l,o,j;if(d){for(l=0;l<d.length;l++){o=d[l];j=h.getStyle(m,o);if(j){n[o]=j;k++}}}h.setAttrib(m,"style","");if(d&&k>0){h.setStyles(m,n)}else{if(m.nodeName=="SPAN"&&!m.className){h.remove(m,true)}}})}}if(b(e,"paste_remove_styles")||(b(e,"paste_remove_styles_if_webkit")&&tinymce.isWebKit)){c(h.select("*[style]",i.node),function(j){j.removeAttribute("style");j.removeAttribute("data-mce-style")})}else{if(tinymce.isWebKit){c(h.select("*",i.node),function(j){j.removeAttribute("data-mce-style")})}}},_convertLists:function(g,e){var i=g.editor.dom,h,l,d=-1,f,m=[],k,j;c(i.select("p",e.node),function(t){var q,u="",s,r,n,o;for(q=t.firstChild;q&&q.nodeType==3;q=q.nextSibling){u+=q.nodeValue}u=t.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/&nbsp;/g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(u)){s="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(u)){s="ol"}if(s){f=parseFloat(t.style.marginLeft||0);if(f>d){m.push(f)}if(!h||s!=k){h=i.create(s);i.insertAfter(h,t)}else{if(f>d){h=l.appendChild(i.create(s))}else{if(f<d){n=tinymce.inArray(m,f);o=i.getParents(h.parentNode,s);h=o[o.length-1-n]||h}}}c(i.select("span",t),function(v){var p=v.innerHTML.replace(/<\/?\w+[^>]*>/gi,"");if(s=="ul"&&/^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(p)){i.remove(v)}else{if(/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(p)){i.remove(v)}}});r=t.innerHTML;if(s=="ul"){r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/,"")}else{r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/,"")}l=h.appendChild(i.create("li",0,r));i.remove(t);d=f;k=s}else{h=d=0}});j=e.node.innerHTML;if(j.indexOf("__MCE_ITEM__")!=-1){e.node.innerHTML=j.replace(/__MCE_ITEM__/g,"")}},_insert:function(f,d){var e=this.editor,g=e.selection.getRng();if(!e.selection.isCollapsed()&&g.startContainer!=g.endContainer){e.getDoc().execCommand("Delete",false,null)}e.execCommand("mceInsertContent",false,f,{skip_undo:d})},_insertPlainText:function(g){var d=this.editor,e=b(d,"paste_text_linebreaktype"),i=b(d,"paste_text_replacements"),f=tinymce.is;function h(j){c(j,function(k){if(k.constructor==RegExp){g=g.replace(k,"")}else{g=g.replace(k[0],k[1])}})}if((typeof(g)==="string")&&(g.length>0)){if(/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(g)){h([/[\n\r]+/g])}else{h([/\r+/g])}h([[/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi,"\n\n"],[/<br[^>]*>|<\/tr>/gi,"\n"],[/<\/t[dh]>\s*<t[dh][^>]*>/gi,"\t"],/<[a-z!\/?][^>]*>/gi,[/&nbsp;/gi," "],[/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi,"$1"],[/\n{3,}/g,"\n\n"]]);g=d.dom.decode(tinymce.html.Entities.encodeRaw(g));if(f(i,"array")){h(i)}else{if(f(i,"string")){h(new RegExp(i,"gi"))}}if(e=="none"){h([[/\n+/g," "]])}else{if(e=="br"){h([[/\n/g,"<br />"]])}else{if(e=="p"){h([[/\n+/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"]])}else{h([[/\n\n/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"],[/\n/g,"<br />"]])}}}d.execCommand("mceInsertContent",false,g)}},_legacySupport:function(){var e=this,d=e.editor;d.addCommand("mcePasteWord",function(){d.windowManager.open({file:e.url+"/pasteword.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})});if(b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(){d.windowManager.open({file:e.url+"/pastetext.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})})}d.addButton("pasteword",{title:"paste.paste_word_desc",cmd:"mcePasteWord"})}});tinymce.PluginManager.add("paste",tinymce.plugins.PastePlugin)})();
 
tiny_mce/plugins/paste/editor_plugin_src.js DELETED
@@ -1,871 +0,0 @@
1
- /**
2
- * editor_plugin_src.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- (function() {
12
- var each = tinymce.each,
13
- defs = {
14
- paste_auto_cleanup_on_paste : true,
15
- paste_enable_default_filters : true,
16
- paste_block_drop : false,
17
- paste_retain_style_properties : "none",
18
- paste_strip_class_attributes : "mso",
19
- paste_remove_spans : false,
20
- paste_remove_styles : false,
21
- paste_remove_styles_if_webkit : true,
22
- paste_convert_middot_lists : true,
23
- paste_convert_headers_to_strong : false,
24
- paste_dialog_width : "450",
25
- paste_dialog_height : "400",
26
- paste_text_use_dialog : false,
27
- paste_text_sticky : false,
28
- paste_text_sticky_default : false,
29
- paste_text_notifyalways : false,
30
- paste_text_linebreaktype : "combined",
31
- paste_text_replacements : [
32
- [/\u2026/g, "..."],
33
- [/[\x93\x94\u201c\u201d]/g, '"'],
34
- [/[\x60\x91\x92\u2018\u2019]/g, "'"]
35
- ]
36
- };
37
-
38
- function getParam(ed, name) {
39
- return ed.getParam(name, defs[name]);
40
- }
41
-
42
- tinymce.create('tinymce.plugins.PastePlugin', {
43
- init : function(ed, url) {
44
- var t = this;
45
-
46
- t.editor = ed;
47
- t.url = url;
48
-
49
- // Setup plugin events
50
- t.onPreProcess = new tinymce.util.Dispatcher(t);
51
- t.onPostProcess = new tinymce.util.Dispatcher(t);
52
-
53
- // Register default handlers
54
- t.onPreProcess.add(t._preProcess);
55
- t.onPostProcess.add(t._postProcess);
56
-
57
- // Register optional preprocess handler
58
- t.onPreProcess.add(function(pl, o) {
59
- ed.execCallback('paste_preprocess', pl, o);
60
- });
61
-
62
- // Register optional postprocess
63
- t.onPostProcess.add(function(pl, o) {
64
- ed.execCallback('paste_postprocess', pl, o);
65
- });
66
-
67
- ed.onKeyDown.addToTop(function(ed, e) {
68
- // Block ctrl+v from adding an undo level since the default logic in tinymce.Editor will add that
69
- if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45))
70
- return false; // Stop other listeners
71
- });
72
-
73
- // Initialize plain text flag
74
- ed.pasteAsPlainText = getParam(ed, 'paste_text_sticky_default');
75
-
76
- // This function executes the process handlers and inserts the contents
77
- // force_rich overrides plain text mode set by user, important for pasting with execCommand
78
- function process(o, force_rich) {
79
- var dom = ed.dom, rng;
80
-
81
- // Execute pre process handlers
82
- t.onPreProcess.dispatch(t, o);
83
-
84
- // Create DOM structure
85
- o.node = dom.create('div', 0, o.content);
86
-
87
- // If pasting inside the same element and the contents is only one block
88
- // remove the block and keep the text since Firefox will copy parts of pre and h1-h6 as a pre element
89
- if (tinymce.isGecko) {
90
- rng = ed.selection.getRng(true);
91
- if (rng.startContainer == rng.endContainer && rng.startContainer.nodeType == 3) {
92
- // Is only one block node and it doesn't contain word stuff
93
- if (o.node.childNodes.length === 1 && /^(p|h[1-6]|pre)$/i.test(o.node.firstChild.nodeName) && o.content.indexOf('__MCE_ITEM__') === -1)
94
- dom.remove(o.node.firstChild, true);
95
- }
96
- }
97
-
98
- // Execute post process handlers
99
- t.onPostProcess.dispatch(t, o);
100
-
101
- // Serialize content
102
- o.content = ed.serializer.serialize(o.node, {getInner : 1, forced_root_block : ''});
103
-
104
- // Plain text option active?
105
- if ((!force_rich) && (ed.pasteAsPlainText)) {
106
- t._insertPlainText(o.content);
107
-
108
- if (!getParam(ed, "paste_text_sticky")) {
109
- ed.pasteAsPlainText = false;
110
- ed.controlManager.setActive("pastetext", false);
111
- }
112
- } else {
113
- t._insert(o.content);
114
- }
115
- }
116
-
117
- // Add command for external usage
118
- ed.addCommand('mceInsertClipboardContent', function(u, o) {
119
- process(o, true);
120
- });
121
-
122
- if (!getParam(ed, "paste_text_use_dialog")) {
123
- ed.addCommand('mcePasteText', function(u, v) {
124
- var cookie = tinymce.util.Cookie;
125
-
126
- ed.pasteAsPlainText = !ed.pasteAsPlainText;
127
- ed.controlManager.setActive('pastetext', ed.pasteAsPlainText);
128
-
129
- if ((ed.pasteAsPlainText) && (!cookie.get("tinymcePasteText"))) {
130
- if (getParam(ed, "paste_text_sticky")) {
131
- ed.windowManager.alert(ed.translate('paste.plaintext_mode_sticky'));
132
- } else {
133
- ed.windowManager.alert(ed.translate('paste.plaintext_mode'));
134
- }
135
-
136
- if (!getParam(ed, "paste_text_notifyalways")) {
137
- cookie.set("tinymcePasteText", "1", new Date(new Date().getFullYear() + 1, 12, 31))
138
- }
139
- }
140
- });
141
- }
142
-
143
- ed.addButton('pastetext', {title: 'paste.paste_text_desc', cmd: 'mcePasteText'});
144
- ed.addButton('selectall', {title: 'paste.selectall_desc', cmd: 'selectall'});
145
-
146
- // This function grabs the contents from the clipboard by adding a
147
- // hidden div and placing the caret inside it and after the browser paste
148
- // is done it grabs that contents and processes that
149
- function grabContent(e) {
150
- var n, or, rng, oldRng, sel = ed.selection, dom = ed.dom, body = ed.getBody(), posY, textContent;
151
-
152
- // Check if browser supports direct plaintext access
153
- if (e.clipboardData || dom.doc.dataTransfer) {
154
- textContent = (e.clipboardData || dom.doc.dataTransfer).getData('Text');
155
-
156
- if (ed.pasteAsPlainText) {
157
- e.preventDefault();
158
- process({content : dom.encode(textContent).replace(/\r?\n/g, '<br />')});
159
- return;
160
- }
161
- }
162
-
163
- if (dom.get('_mcePaste'))
164
- return;
165
-
166
- // Create container to paste into
167
- n = dom.add(body, 'div', {id : '_mcePaste', 'class' : 'mcePaste', 'data-mce-bogus' : '1'}, '\uFEFF\uFEFF');
168
-
169
- // If contentEditable mode we need to find out the position of the closest element
170
- if (body != ed.getDoc().body)
171
- posY = dom.getPos(ed.selection.getStart(), body).y;
172
- else
173
- posY = body.scrollTop + dom.getViewPort(ed.getWin()).y;
174
-
175
- // Styles needs to be applied after the element is added to the document since WebKit will otherwise remove all styles
176
- // If also needs to be in view on IE or the paste would fail
177
- dom.setStyles(n, {
178
- position : 'absolute',
179
- left : tinymce.isGecko ? -40 : 0, // Need to move it out of site on Gecko since it will othewise display a ghost resize rect for the div
180
- top : posY - 25,
181
- width : 1,
182
- height : 1,
183
- overflow : 'hidden'
184
- });
185
-
186
- if (tinymce.isIE) {
187
- // Store away the old range
188
- oldRng = sel.getRng();
189
-
190
- // Select the container
191
- rng = dom.doc.body.createTextRange();
192
- rng.moveToElementText(n);
193
- rng.execCommand('Paste');
194
-
195
- // Remove container
196
- dom.remove(n);
197
-
198
- // Check if the contents was changed, if it wasn't then clipboard extraction failed probably due
199
- // to IE security settings so we pass the junk though better than nothing right
200
- if (n.innerHTML === '\uFEFF\uFEFF') {
201
- ed.execCommand('mcePasteWord');
202
- e.preventDefault();
203
- return;
204
- }
205
-
206
- // Restore the old range and clear the contents before pasting
207
- sel.setRng(oldRng);
208
- sel.setContent('');
209
-
210
- // For some odd reason we need to detach the the mceInsertContent call from the paste event
211
- // It's like IE has a reference to the parent element that you paste in and the selection gets messed up
212
- // when it tries to restore the selection
213
- setTimeout(function() {
214
- // Process contents
215
- process({content : n.innerHTML});
216
- }, 0);
217
-
218
- // Block the real paste event
219
- return tinymce.dom.Event.cancel(e);
220
- } else {
221
- function block(e) {
222
- e.preventDefault();
223
- };
224
-
225
- // Block mousedown and click to prevent selection change
226
- dom.bind(ed.getDoc(), 'mousedown', block);
227
- dom.bind(ed.getDoc(), 'keydown', block);
228
-
229
- or = ed.selection.getRng();
230
-
231
- // Move select contents inside DIV
232
- n = n.firstChild;
233
- rng = ed.getDoc().createRange();
234
- rng.setStart(n, 0);
235
- rng.setEnd(n, 2);
236
- sel.setRng(rng);
237
-
238
- // Wait a while and grab the pasted contents
239
- window.setTimeout(function() {
240
- var h = '', nl;
241
-
242
- // Paste divs duplicated in paste divs seems to happen when you paste plain text so lets first look for that broken behavior in WebKit
243
- if (!dom.select('div.mcePaste > div.mcePaste').length) {
244
- nl = dom.select('div.mcePaste');
245
-
246
- // WebKit will split the div into multiple ones so this will loop through then all and join them to get the whole HTML string
247
- each(nl, function(n) {
248
- var child = n.firstChild;
249
-
250
- // WebKit inserts a DIV container with lots of odd styles
251
- if (child && child.nodeName == 'DIV' && child.style.marginTop && child.style.backgroundColor) {
252
- dom.remove(child, 1);
253
- }
254
-
255
- // Remove apply style spans
256
- each(dom.select('span.Apple-style-span', n), function(n) {
257
- dom.remove(n, 1);
258
- });
259
-
260
- // Remove bogus br elements
261
- each(dom.select('br[data-mce-bogus]', n), function(n) {
262
- dom.remove(n);
263
- });
264
-
265
- // WebKit will make a copy of the DIV for each line of plain text pasted and insert them into the DIV
266
- if (n.parentNode.className != 'mcePaste')
267
- h += n.innerHTML;
268
- });
269
- } else {
270
- // Found WebKit weirdness so force the content into paragraphs this seems to happen when you paste plain text from Nodepad etc
271
- // So this logic will replace double enter with paragraphs and single enter with br so it kind of looks the same
272
- h = '<p>' + dom.encode(textContent).replace(/\r?\n\r?\n/g, '</p><p>').replace(/\r?\n/g, '<br />') + '</p>';
273
- }
274
-
275
- // Remove the nodes
276
- each(dom.select('div.mcePaste'), function(n) {
277
- dom.remove(n);
278
- });
279
-
280
- // Restore the old selection
281
- if (or)
282
- sel.setRng(or);
283
-
284
- process({content : h});
285
-
286
- // Unblock events ones we got the contents
287
- dom.unbind(ed.getDoc(), 'mousedown', block);
288
- dom.unbind(ed.getDoc(), 'keydown', block);
289
- }, 0);
290
- }
291
- }
292
-
293
- // Check if we should use the new auto process method
294
- if (getParam(ed, "paste_auto_cleanup_on_paste")) {
295
- // Is it's Opera or older FF use key handler
296
- if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) {
297
- ed.onKeyDown.addToTop(function(ed, e) {
298
- if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45))
299
- grabContent(e);
300
- });
301
- } else {
302
- // Grab contents on paste event on Gecko and WebKit
303
- ed.onPaste.addToTop(function(ed, e) {
304
- return grabContent(e);
305
- });
306
- }
307
- }
308
-
309
- ed.onInit.add(function() {
310
- ed.controlManager.setActive("pastetext", ed.pasteAsPlainText);
311
-
312
- // Block all drag/drop events
313
- if (getParam(ed, "paste_block_drop")) {
314
- ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) {
315
- e.preventDefault();
316
- e.stopPropagation();
317
-
318
- return false;
319
- });
320
- }
321
- });
322
-
323
- // Add legacy support
324
- t._legacySupport();
325
- },
326
-
327
- getInfo : function() {
328
- return {
329
- longname : 'Paste text/word',
330
- author : 'Moxiecode Systems AB',
331
- authorurl : 'http://tinymce.moxiecode.com',
332
- infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
333
- version : tinymce.majorVersion + "." + tinymce.minorVersion
334
- };
335
- },
336
-
337
- _preProcess : function(pl, o) {
338
- var ed = this.editor,
339
- h = o.content,
340
- grep = tinymce.grep,
341
- explode = tinymce.explode,
342
- trim = tinymce.trim,
343
- len, stripClass;
344
-
345
- //console.log('Before preprocess:' + o.content);
346
-
347
- function process(items) {
348
- each(items, function(v) {
349
- // Remove or replace
350
- if (v.constructor == RegExp)
351
- h = h.replace(v, '');
352
- else
353
- h = h.replace(v[0], v[1]);
354
- });
355
- }
356
-
357
- if (ed.settings.paste_enable_default_filters == false) {
358
- return;
359
- }
360
-
361
- // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser
362
- if (tinymce.isIE && document.documentMode >= 9) {
363
- // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser
364
- process([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g, '$1']]);
365
-
366
- // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break
367
- process([
368
- [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact
369
- [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s
370
- [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR
371
- ]);
372
- }
373
-
374
- // Detect Word content and process it more aggressive
375
- if (/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(h) || o.wordContent) {
376
- o.wordContent = true; // Mark the pasted contents as word specific content
377
- //console.log('Word contents detected.');
378
-
379
- // Process away some basic content
380
- process([
381
- /^\s*(&nbsp;)+/gi, // &nbsp; entities at the start of contents
382
- /(&nbsp;|<br[^>]*>)+\s*$/gi // &nbsp; entities at the end of contents
383
- ]);
384
-
385
- if (getParam(ed, "paste_convert_headers_to_strong")) {
386
- h = h.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>");
387
- }
388
-
389
- if (getParam(ed, "paste_convert_middot_lists")) {
390
- process([
391
- [/<!--\[if !supportLists\]-->/gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker
392
- [/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert mso-list and symbol spans to item markers
393
- [/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list and symbol paragraphs to item markers (FF)
394
- ]);
395
- }
396
-
397
- process([
398
- // Word comments like conditional comments etc
399
- /<!--[\s\S]+?-->/gi,
400
-
401
- // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags
402
- /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,
403
-
404
- // Convert <s> into <strike> for line-though
405
- [/<(\/?)s>/gi, "<$1strike>"],
406
-
407
- // Replace nsbp entites to char since it's easier to handle
408
- [/&nbsp;/gi, "\u00a0"]
409
- ]);
410
-
411
- // Remove bad attributes, with or without quotes, ensuring that attribute text is really inside a tag.
412
- // If JavaScript had a RegExp look-behind, we could have integrated this with the last process() array and got rid of the loop. But alas, it does not, so we cannot.
413
- do {
414
- len = h.length;
415
- h = h.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1");
416
- } while (len != h.length);
417
-
418
- // Remove all spans if no styles is to be retained
419
- if (getParam(ed, "paste_retain_style_properties").replace(/^none$/i, "").length == 0) {
420
- h = h.replace(/<\/?span[^>]*>/gi, "");
421
- } else {
422
- // We're keeping styles, so at least clean them up.
423
- // CSS Reference: http://msdn.microsoft.com/en-us/library/aa155477.aspx
424
-
425
- process([
426
- // Convert <span style="mso-spacerun:yes">___</span> to string of alternating breaking/non-breaking spaces of same length
427
- [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,
428
- function(str, spaces) {
429
- return (spaces.length > 0)? spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : "";
430
- }
431
- ],
432
-
433
- // Examine all styles: delete junk, transform some, and keep the rest
434
- [/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,
435
- function(str, tag, style) {
436
- var n = [],
437
- i = 0,
438
- s = explode(trim(style).replace(/&quot;/gi, "'"), ";");
439
-
440
- // Examine each style definition within the tag's style attribute
441
- each(s, function(v) {
442
- var name, value,
443
- parts = explode(v, ":");
444
-
445
- function ensureUnits(v) {
446
- return v + ((v !== "0") && (/\d$/.test(v)))? "px" : "";
447
- }
448
-
449
- if (parts.length == 2) {
450
- name = parts[0].toLowerCase();
451
- value = parts[1].toLowerCase();
452
-
453
- // Translate certain MS Office styles into their CSS equivalents
454
- switch (name) {
455
- case "mso-padding-alt":
456
- case "mso-padding-top-alt":
457
- case "mso-padding-right-alt":
458
- case "mso-padding-bottom-alt":
459
- case "mso-padding-left-alt":
460
- case "mso-margin-alt":
461
- case "mso-margin-top-alt":
462
- case "mso-margin-right-alt":
463
- case "mso-margin-bottom-alt":
464
- case "mso-margin-left-alt":
465
- case "mso-table-layout-alt":
466
- case "mso-height":
467
- case "mso-width":
468
- case "mso-vertical-align-alt":
469
- n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value);
470
- return;
471
-
472
- case "horiz-align":
473
- n[i++] = "text-align:" + value;
474
- return;
475
-
476
- case "vert-align":
477
- n[i++] = "vertical-align:" + value;
478
- return;
479
-
480
- case "font-color":
481
- case "mso-foreground":
482
- n[i++] = "color:" + value;
483
- return;
484
-
485
- case "mso-background":
486
- case "mso-highlight":
487
- n[i++] = "background:" + value;
488
- return;
489
-
490
- case "mso-default-height":
491
- n[i++] = "min-height:" + ensureUnits(value);
492
- return;
493
-
494
- case "mso-default-width":
495
- n[i++] = "min-width:" + ensureUnits(value);
496
- return;
497
-
498
- case "mso-padding-between-alt":
499
- n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value);
500
- return;
501
-
502
- case "text-line-through":
503
- if ((value == "single") || (value == "double")) {
504
- n[i++] = "text-decoration:line-through";
505
- }
506
- return;
507
-
508
- case "mso-zero-height":
509
- if (value == "yes") {
510
- n[i++] = "display:none";
511
- }
512
- return;
513
- }
514
-
515
- // Eliminate all MS Office style definitions that have no CSS equivalent by examining the first characters in the name
516
- if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(name)) {
517
- return;
518
- }
519
-
520
- // If it reached this point, it must be a valid CSS style
521
- n[i++] = name + ":" + parts[1]; // Lower-case name, but keep value case
522
- }
523
- });
524
-
525
- // If style attribute contained any valid styles the re-write it; otherwise delete style attribute.
526
- if (i > 0) {
527
- return tag + ' style="' + n.join(';') + '"';
528
- } else {
529
- return tag;
530
- }
531
- }
532
- ]
533
- ]);
534
- }
535
- }
536
-
537
- // Replace headers with <strong>
538
- if (getParam(ed, "paste_convert_headers_to_strong")) {
539
- process([
540
- [/<h[1-6][^>]*>/gi, "<p><strong>"],
541
- [/<\/h[1-6][^>]*>/gi, "</strong></p>"]
542
- ]);
543
- }
544
-
545
- process([
546
- // Copy paste from Java like Open Office will produce this junk on FF
547
- [/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi, '']
548
- ]);
549
-
550
- // Class attribute options are: leave all as-is ("none"), remove all ("all"), or remove only those starting with mso ("mso").
551
- // Note:- paste_strip_class_attributes: "none", verify_css_classes: true is also a good variation.
552
- stripClass = getParam(ed, "paste_strip_class_attributes");
553
-
554
- if (stripClass !== "none") {
555
- function removeClasses(match, g1) {
556
- if (stripClass === "all")
557
- return '';
558
-
559
- var cls = grep(explode(g1.replace(/^(["'])(.*)\1$/, "$2"), " "),
560
- function(v) {
561
- return (/^(?!mso)/i.test(v));
562
- }
563
- );
564
-
565
- return cls.length ? ' class="' + cls.join(" ") + '"' : '';
566
- };
567
-
568
- h = h.replace(/ class="([^"]+)"/gi, removeClasses);
569
- h = h.replace(/ class=([\-\w]+)/gi, removeClasses);
570
- }
571
-
572
- // Remove spans option
573
- if (getParam(ed, "paste_remove_spans")) {
574
- h = h.replace(/<\/?span[^>]*>/gi, "");
575
- }
576
-
577
- //console.log('After preprocess:' + h);
578
-
579
- o.content = h;
580
- },
581
-
582
- /**
583
- * Various post process items.
584
- */
585
- _postProcess : function(pl, o) {
586
- var t = this, ed = t.editor, dom = ed.dom, styleProps;
587
-
588
- if (ed.settings.paste_enable_default_filters == false) {
589
- return;
590
- }
591
-
592
- if (o.wordContent) {
593
- // Remove named anchors or TOC links
594
- each(dom.select('a', o.node), function(a) {
595
- if (!a.href || a.href.indexOf('#_Toc') != -1)
596
- dom.remove(a, 1);
597
- });
598
-
599
- if (getParam(ed, "paste_convert_middot_lists")) {
600
- t._convertLists(pl, o);
601
- }
602
-
603
- // Process styles
604
- styleProps = getParam(ed, "paste_retain_style_properties"); // retained properties
605
-
606
- // Process only if a string was specified and not equal to "all" or "*"
607
- if ((tinymce.is(styleProps, "string")) && (styleProps !== "all") && (styleProps !== "*")) {
608
- styleProps = tinymce.explode(styleProps.replace(/^none$/i, ""));
609
-
610
- // Retains some style properties
611
- each(dom.select('*', o.node), function(el) {
612
- var newStyle = {}, npc = 0, i, sp, sv;
613
-
614
- // Store a subset of the existing styles
615
- if (styleProps) {
616
- for (i = 0; i < styleProps.length; i++) {
617
- sp = styleProps[i];
618
- sv = dom.getStyle(el, sp);
619
-
620
- if (sv) {
621
- newStyle[sp] = sv;
622
- npc++;
623
- }
624
- }
625
- }
626
-
627
- // Remove all of the existing styles
628
- dom.setAttrib(el, 'style', '');
629
-
630
- if (styleProps && npc > 0)
631
- dom.setStyles(el, newStyle); // Add back the stored subset of styles
632
- else // Remove empty span tags that do not have class attributes
633
- if (el.nodeName == 'SPAN' && !el.className)
634
- dom.remove(el, true);
635
- });
636
- }
637
- }
638
-
639
- // Remove all style information or only specifically on WebKit to avoid the style bug on that browser
640
- if (getParam(ed, "paste_remove_styles") || (getParam(ed, "paste_remove_styles_if_webkit") && tinymce.isWebKit)) {
641
- each(dom.select('*[style]', o.node), function(el) {
642
- el.removeAttribute('style');
643
- el.removeAttribute('data-mce-style');
644
- });
645
- } else {
646
- if (tinymce.isWebKit) {
647
- // We need to compress the styles on WebKit since if you paste <img border="0" /> it will become <img border="0" style="... lots of junk ..." />
648
- // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles
649
- each(dom.select('*', o.node), function(el) {
650
- el.removeAttribute('data-mce-style');
651
- });
652
- }
653
- }
654
- },
655
-
656
- /**
657
- * Converts the most common bullet and number formats in Office into a real semantic UL/LI list.
658
- */
659
- _convertLists : function(pl, o) {
660
- var dom = pl.editor.dom, listElm, li, lastMargin = -1, margin, levels = [], lastType, html;
661
-
662
- // Convert middot lists into real semantic lists
663
- each(dom.select('p', o.node), function(p) {
664
- var sib, val = '', type, html, idx, parents;
665
-
666
- // Get text node value at beginning of paragraph
667
- for (sib = p.firstChild; sib && sib.nodeType == 3; sib = sib.nextSibling)
668
- val += sib.nodeValue;
669
-
670
- val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/&nbsp;/g, '\u00a0');
671
-
672
- // Detect unordered lists look for bullets
673
- if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(val))
674
- type = 'ul';
675
-
676
- // Detect ordered lists 1., a. or ixv.
677
- if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(val))
678
- type = 'ol';
679
-
680
- // Check if node value matches the list pattern: o&nbsp;&nbsp;
681
- if (type) {
682
- margin = parseFloat(p.style.marginLeft || 0);
683
-
684
- if (margin > lastMargin)
685
- levels.push(margin);
686
-
687
- if (!listElm || type != lastType) {
688
- listElm = dom.create(type);
689
- dom.insertAfter(listElm, p);
690
- } else {
691
- // Nested list element
692
- if (margin > lastMargin) {
693
- listElm = li.appendChild(dom.create(type));
694
- } else if (margin < lastMargin) {
695
- // Find parent level based on margin value
696
- idx = tinymce.inArray(levels, margin);
697
- parents = dom.getParents(listElm.parentNode, type);
698
- listElm = parents[parents.length - 1 - idx] || listElm;
699
- }
700
- }
701
-
702
- // Remove middot or number spans if they exists
703
- each(dom.select('span', p), function(span) {
704
- var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, '');
705
-
706
- // Remove span with the middot or the number
707
- if (type == 'ul' && /^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(html))
708
- dom.remove(span);
709
- else if (/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(html))
710
- dom.remove(span);
711
- });
712
-
713
- html = p.innerHTML;
714
-
715
- // Remove middot/list items
716
- if (type == 'ul')
717
- html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/, '');
718
- else
719
- html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/, '');
720
-
721
- // Create li and add paragraph data into the new li
722
- li = listElm.appendChild(dom.create('li', 0, html));
723
- dom.remove(p);
724
-
725
- lastMargin = margin;
726
- lastType = type;
727
- } else
728
- listElm = lastMargin = 0; // End list element
729
- });
730
-
731
- // Remove any left over makers
732
- html = o.node.innerHTML;
733
- if (html.indexOf('__MCE_ITEM__') != -1)
734
- o.node.innerHTML = html.replace(/__MCE_ITEM__/g, '');
735
- },
736
-
737
- /**
738
- * Inserts the specified contents at the caret position.
739
- */
740
- _insert : function(h, skip_undo) {
741
- var ed = this.editor, r = ed.selection.getRng();
742
-
743
- // First delete the contents seems to work better on WebKit when the selection spans multiple list items or multiple table cells.
744
- if (!ed.selection.isCollapsed() && r.startContainer != r.endContainer)
745
- ed.getDoc().execCommand('Delete', false, null);
746
-
747
- ed.execCommand('mceInsertContent', false, h, {skip_undo : skip_undo});
748
- },
749
-
750
- /**
751
- * Instead of the old plain text method which tried to re-create a paste operation, the
752
- * new approach adds a plain text mode toggle switch that changes the behavior of paste.
753
- * This function is passed the same input that the regular paste plugin produces.
754
- * It performs additional scrubbing and produces (and inserts) the plain text.
755
- * This approach leverages all of the great existing functionality in the paste
756
- * plugin, and requires minimal changes to add the new functionality.
757
- * Speednet - June 2009
758
- */
759
- _insertPlainText : function(content) {
760
- var ed = this.editor,
761
- linebr = getParam(ed, "paste_text_linebreaktype"),
762
- rl = getParam(ed, "paste_text_replacements"),
763
- is = tinymce.is;
764
-
765
- function process(items) {
766
- each(items, function(v) {
767
- if (v.constructor == RegExp)
768
- content = content.replace(v, "");
769
- else
770
- content = content.replace(v[0], v[1]);
771
- });
772
- };
773
-
774
- if ((typeof(content) === "string") && (content.length > 0)) {
775
- // If HTML content with line-breaking tags, then remove all cr/lf chars because only tags will break a line
776
- if (/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(content)) {
777
- process([
778
- /[\n\r]+/g
779
- ]);
780
- } else {
781
- // Otherwise just get rid of carriage returns (only need linefeeds)
782
- process([
783
- /\r+/g
784
- ]);
785
- }
786
-
787
- process([
788
- [/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi, "\n\n"], // Block tags get a blank line after them
789
- [/<br[^>]*>|<\/tr>/gi, "\n"], // Single linebreak for <br /> tags and table rows
790
- [/<\/t[dh]>\s*<t[dh][^>]*>/gi, "\t"], // Table cells get tabs betweem them
791
- /<[a-z!\/?][^>]*>/gi, // Delete all remaining tags
792
- [/&nbsp;/gi, " "], // Convert non-break spaces to regular spaces (remember, *plain text*)
793
- [/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi, "$1"],// Cool little RegExp deletes whitespace around linebreak chars.
794
- [/\n{3,}/g, "\n\n"] // Max. 2 consecutive linebreaks
795
- ]);
796
-
797
- content = ed.dom.decode(tinymce.html.Entities.encodeRaw(content));
798
-
799
- // Perform default or custom replacements
800
- if (is(rl, "array")) {
801
- process(rl);
802
- } else if (is(rl, "string")) {
803
- process(new RegExp(rl, "gi"));
804
- }
805
-
806
- // Treat paragraphs as specified in the config
807
- if (linebr == "none") {
808
- // Convert all line breaks to space
809
- process([
810
- [/\n+/g, " "]
811
- ]);
812
- } else if (linebr == "br") {
813
- // Convert all line breaks to <br />
814
- process([
815
- [/\n/g, "<br />"]
816
- ]);
817
- } else if (linebr == "p") {
818
- // Convert all line breaks to <p>...</p>
819
- process([
820
- [/\n+/g, "</p><p>"],
821
- [/^(.*<\/p>)(<p>)$/, '<p>$1']
822
- ]);
823
- } else {
824
- // defaults to "combined"
825
- // Convert single line breaks to <br /> and double line breaks to <p>...</p>
826
- process([
827
- [/\n\n/g, "</p><p>"],
828
- [/^(.*<\/p>)(<p>)$/, '<p>$1'],
829
- [/\n/g, "<br />"]
830
- ]);
831
- }
832
-
833
- ed.execCommand('mceInsertContent', false, content);
834
- }
835
- },
836
-
837
- /**
838
- * This method will open the old style paste dialogs. Some users might want the old behavior but still use the new cleanup engine.
839
- */
840
- _legacySupport : function() {
841
- var t = this, ed = t.editor;
842
-
843
- // Register command(s) for backwards compatibility
844
- ed.addCommand("mcePasteWord", function() {
845
- ed.windowManager.open({
846
- file: t.url + "/pasteword.htm",
847
- width: parseInt(getParam(ed, "paste_dialog_width")),
848
- height: parseInt(getParam(ed, "paste_dialog_height")),
849
- inline: 1
850
- });
851
- });
852
-
853
- if (getParam(ed, "paste_text_use_dialog")) {
854
- ed.addCommand("mcePasteText", function() {
855
- ed.windowManager.open({
856
- file : t.url + "/pastetext.htm",
857
- width: parseInt(getParam(ed, "paste_dialog_width")),
858
- height: parseInt(getParam(ed, "paste_dialog_height")),
859
- inline : 1
860
- });
861
- });
862
- }
863
-
864
- // Register button for backwards compatibility
865
- ed.addButton("pasteword", {title : "paste.paste_word_desc", cmd : "mcePasteWord"});
866
- }
867
- });
868
-
869
- // Register plugin
870
- tinymce.PluginManager.add("paste", tinymce.plugins.PastePlugin);
871
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/paste/js/pastetext.js DELETED
@@ -1,36 +0,0 @@
1
- tinyMCEPopup.requireLangPack();
2
-
3
- var PasteTextDialog = {
4
- init : function() {
5
- this.resize();
6
- },
7
-
8
- insert : function() {
9
- var h = tinyMCEPopup.dom.encode(document.getElementById('content').value), lines;
10
-
11
- // Convert linebreaks into paragraphs
12
- if (document.getElementById('linebreaks').checked) {
13
- lines = h.split(/\r?\n/);
14
- if (lines.length > 1) {
15
- h = '';
16
- tinymce.each(lines, function(row) {
17
- h += '<p>' + row + '</p>';
18
- });
19
- }
20
- }
21
-
22
- tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h});
23
- tinyMCEPopup.close();
24
- },
25
-
26
- resize : function() {
27
- var vp = tinyMCEPopup.dom.getViewPort(window), el;
28
-
29
- el = document.getElementById('content');
30
-
31
- el.style.width = (vp.w - 20) + 'px';
32
- el.style.height = (vp.h - 90) + 'px';
33
- }
34
- };
35
-
36
- tinyMCEPopup.onInit.add(PasteTextDialog.init, PasteTextDialog);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/paste/js/pasteword.js DELETED
@@ -1,51 +0,0 @@
1
- tinyMCEPopup.requireLangPack();
2
-
3
- var PasteWordDialog = {
4
- init : function() {
5
- var ed = tinyMCEPopup.editor, el = document.getElementById('iframecontainer'), ifr, doc, css, cssHTML = '';
6
-
7
- // Create iframe
8
- el.innerHTML = '<iframe id="iframe" src="javascript:\'\';" frameBorder="0" style="border: 1px solid gray"></iframe>';
9
- ifr = document.getElementById('iframe');
10
- doc = ifr.contentWindow.document;
11
-
12
- // Force absolute CSS urls
13
- css = [ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css")];
14
- css = css.concat(tinymce.explode(ed.settings.content_css) || []);
15
- tinymce.each(css, function(u) {
16
- cssHTML += '<link href="' + ed.documentBaseURI.toAbsolute('' + u) + '" rel="stylesheet" type="text/css" />';
17
- });
18
-
19
- // Write content into iframe
20
- doc.open();
21
- doc.write('<html><head>' + cssHTML + '</head><body class="mceContentBody" spellcheck="false"></body></html>');
22
- doc.close();
23
-
24
- doc.designMode = 'on';
25
- this.resize();
26
-
27
- window.setTimeout(function() {
28
- ifr.contentWindow.focus();
29
- }, 10);
30
- },
31
-
32
- insert : function() {
33
- var h = document.getElementById('iframe').contentWindow.document.body.innerHTML;
34
-
35
- tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h, wordContent : true});
36
- tinyMCEPopup.close();
37
- },
38
-
39
- resize : function() {
40
- var vp = tinyMCEPopup.dom.getViewPort(window), el;
41
-
42
- el = document.getElementById('iframe');
43
-
44
- if (el) {
45
- el.style.width = (vp.w - 20) + 'px';
46
- el.style.height = (vp.h - 90) + 'px';
47
- }
48
- }
49
- };
50
-
51
- tinyMCEPopup.onInit.add(PasteWordDialog.init, PasteWordDialog);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/paste/langs/en_dlg.js DELETED
@@ -1 +0,0 @@
1
- tinyMCE.addI18n('en.paste_dlg',{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."});
 
tiny_mce/plugins/paste/pastetext.htm DELETED
@@ -1,27 +0,0 @@
1
- <html xmlns="http://www.w3.org/1999/xhtml">
2
- <head>
3
- <title>{#paste.paste_text_desc}</title>
4
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
5
- <script type="text/javascript" src="js/pastetext.js"></script>
6
- </head>
7
- <body onresize="PasteTextDialog.resize();" style="display:none; overflow:hidden;">
8
- <form name="source" onsubmit="return PasteTextDialog.insert();" action="#">
9
- <div style="float: left" class="title">{#paste.paste_text_desc}</div>
10
-
11
- <div style="float: right">
12
- <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label>
13
- </div>
14
-
15
- <br style="clear: both" />
16
-
17
- <div>{#paste_dlg.text_title}</div>
18
-
19
- <textarea id="content" name="content" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft" class="mceFocus"></textarea>
20
-
21
- <div class="mceActionPanel">
22
- <input type="submit" name="insert" value="{#insert}" id="insert" />
23
- <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
24
- </div>
25
- </form>
26
- </body>
27
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/paste/pasteword.htm DELETED
@@ -1,21 +0,0 @@
1
- <html xmlns="http://www.w3.org/1999/xhtml">
2
- <head>
3
- <title>{#paste.paste_word_desc}</title>
4
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
5
- <script type="text/javascript" src="js/pasteword.js"></script>
6
- </head>
7
- <body onresize="PasteWordDialog.resize();" style="display:none; overflow:hidden;">
8
- <form name="source" onsubmit="return PasteWordDialog.insert();" action="#">
9
- <div class="title">{#paste.paste_word_desc}</div>
10
-
11
- <div>{#paste_dlg.word_title}</div>
12
-
13
- <div id="iframecontainer"></div>
14
-
15
- <div class="mceActionPanel">
16
- <input type="submit" id="insert" name="insert" value="{#insert}" />
17
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
18
- </div>
19
- </form>
20
- </body>
21
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/table/editor_plugin.js CHANGED
@@ -1 +1 @@
1
- (function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}})}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD,TH");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(C,N){var L=d.VK;var Q=N.keyCode;function O(Y,U,S){var T=Y?"previousSibling":"nextSibling";var Z=C.dom.getParent(U,"tr");var X=Z[T];if(X){z(C,U,X,Y);d.dom.Event.cancel(S);return true}else{var aa=C.dom.getParent(Z,"table");var W=Z.parentNode;var R=W.nodeName.toLowerCase();if(R==="tbody"||R===(Y?"tfoot":"thead")){var V=w(Y,aa,W,"tbody");if(V!==null){return K(Y,V,U,S)}}return M(Y,Z,T,aa,S)}}function w(V,T,U,X){var S=C.dom.select(">"+X,T);var R=S.indexOf(U);if(V&&R===0||!V&&R===S.length-1){return B(V,T)}else{if(R===-1){var W=U.tagName.toLowerCase()==="thead"?0:S.length-1;return S[W]}else{return S[R+(V?-1:1)]}}}function B(U,T){var S=U?"thead":"tfoot";var R=C.dom.select(">"+S,T);return R.length!==0?R[0]:null}function K(V,T,S,U){var R=J(T,V);R&&z(C,S,R,V);d.dom.Event.cancel(U);return true}function M(Y,U,R,X,W){var S=X[R];if(S){F(S);return true}else{var V=C.dom.getParent(X,"td,th");if(V){return O(Y,V,W)}else{var T=J(U,!Y);F(T);return d.dom.Event.cancel(W)}}}function J(S,R){return S&&S[R?"lastChild":"firstChild"]}function F(R){C.selection.setCursorLocation(R,0)}function A(){return Q==L.UP||Q==L.DOWN}function D(R){var T=R.selection.getNode();var S=R.dom.getParent(T,"tr");return S!==null}function P(S){var R=0;var T=S;while(T.previousSibling){T=T.previousSibling;R=R+a(T,"colspan")}return R}function E(T,R){var U=0;var S=0;e(T.children,function(V,W){U=U+a(V,"colspan");S=W;if(U>R){return false}});return S}function z(T,W,Y,V){var X=P(T.dom.getParent(W,"td,th"));var S=E(Y,X);var R=Y.childNodes[S];var U=J(R,V);F(U||R)}function H(R){var T=C.selection.getNode();var U=C.dom.getParent(T,"td,th");var S=C.dom.getParent(R,"td,th");return U&&U!==S&&I(U,S)}function I(S,R){return C.dom.getParent(S,"TABLE")===C.dom.getParent(R,"TABLE")}if(A()&&D(C)){var G=C.selection.getNode();setTimeout(function(){if(H(G)){O(!N.shiftKey&&Q===L.UP,G,N)}},0)}}r.onKeyDown.add(v)}if(!d.isIE){function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){r.dom.add(r.getBody(),"p",null,'<br mce_bogus="1" />')}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&z.childNodes.length==1&&z.firstChild.nodeName=="BR"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})}});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce);
1
+ (function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{L=D=null;e(g,function(Z,aa){e(Z,function(ac,ab){if(j(ac)){if(!L){L={x:ab,y:aa}}D={x:ab,y:aa}}})});P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}});G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected")}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD,TH");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(C,N){var L=d.VK;var Q=N.keyCode;function O(Y,U,S){var T=Y?"previousSibling":"nextSibling";var Z=C.dom.getParent(U,"tr");var X=Z[T];if(X){z(C,U,X,Y);d.dom.Event.cancel(S);return true}else{var aa=C.dom.getParent(Z,"table");var W=Z.parentNode;var R=W.nodeName.toLowerCase();if(R==="tbody"||R===(Y?"tfoot":"thead")){var V=w(Y,aa,W,"tbody");if(V!==null){return K(Y,V,U,S)}}return M(Y,Z,T,aa,S)}}function w(V,T,U,X){var S=C.dom.select(">"+X,T);var R=S.indexOf(U);if(V&&R===0||!V&&R===S.length-1){return B(V,T)}else{if(R===-1){var W=U.tagName.toLowerCase()==="thead"?0:S.length-1;return S[W]}else{return S[R+(V?-1:1)]}}}function B(U,T){var S=U?"thead":"tfoot";var R=C.dom.select(">"+S,T);return R.length!==0?R[0]:null}function K(V,T,S,U){var R=J(T,V);R&&z(C,S,R,V);d.dom.Event.cancel(U);return true}function M(Y,U,R,X,W){var S=X[R];if(S){F(S);return true}else{var V=C.dom.getParent(X,"td,th");if(V){return O(Y,V,W)}else{var T=J(U,!Y);F(T);return d.dom.Event.cancel(W)}}}function J(S,R){var T=S&&S[R?"lastChild":"firstChild"];return T&&T.nodeName==="BR"?C.dom.getParent(T,"td,th"):T}function F(R){C.selection.setCursorLocation(R,0)}function A(){return Q==L.UP||Q==L.DOWN}function D(R){var T=R.selection.getNode();var S=R.dom.getParent(T,"tr");return S!==null}function P(S){var R=0;var T=S;while(T.previousSibling){T=T.previousSibling;R=R+a(T,"colspan")}return R}function E(T,R){var U=0;var S=0;e(T.children,function(V,W){U=U+a(V,"colspan");S=W;if(U>R){return false}});return S}function z(T,W,Y,V){var X=P(T.dom.getParent(W,"td,th"));var S=E(Y,X);var R=Y.childNodes[S];var U=J(R,V);F(U||R)}function H(R){var T=C.selection.getNode();var U=C.dom.getParent(T,"td,th");var S=C.dom.getParent(R,"td,th");return U&&U!==S&&I(U,S)}function I(S,R){return C.dom.getParent(S,"TABLE")===C.dom.getParent(R,"TABLE")}if(A()&&D(C)){var G=C.selection.getNode();setTimeout(function(){if(H(G)){O(!N.shiftKey&&Q===L.UP,G,N)}},0)}}r.onKeyDown.add(v)}function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){if(r.settings.forced_root_block){r.dom.add(r.getBody(),r.settings.forced_root_block,null,d.isIE?"&nbsp;":'<br data-mce-bogus="1" />')}else{r.dom.add(r.getBody(),"br",{"data-mce-bogus":"1"})}}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&(z.nodeName=="BR"||(z.childNodes.length==1&&(z.firstChild.nodeName=="BR"||z.firstChild.nodeValue=="\u00a0")))&&z.previousSibling&&z.previousSibling.nodeName=="TABLE"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce);
tiny_mce/plugins/table/editor_plugin_src.js CHANGED
@@ -287,6 +287,21 @@
287
  endX = startX + (cols - 1);
288
  endY = startY + (rows - 1);
289
  } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  // Use selection
291
  startX = startPos.x;
292
  startY = startPos.y;
@@ -599,6 +614,9 @@
599
  else
600
  dom.insertAfter(row, targetRow);
601
  });
 
 
 
602
  };
603
 
604
  function getPos(target) {
@@ -1144,7 +1162,9 @@
1144
  }
1145
 
1146
  function getChildForDirection(parent, up) {
1147
- return parent && parent[up ? 'lastChild' : 'firstChild'];
 
 
1148
  }
1149
 
1150
  function moveCursorToStartOfElement(n) {
@@ -1214,62 +1234,86 @@
1214
 
1215
  ed.onKeyDown.add(moveSelection);
1216
  }
1217
-
1218
  // Fixes an issue on Gecko where it's impossible to place the caret behind a table
1219
  // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
1220
- if (!tinymce.isIE) {
1221
- function fixTableCaretPos() {
1222
- var last;
1223
 
1224
- // Skip empty text nodes form the end
1225
- for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
1226
 
1227
- if (last && last.nodeName == 'TABLE')
1228
- ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />');
1229
- };
 
 
 
 
1230
 
1231
- // Fixes an bug where it's impossible to place the caret before a table in Gecko
1232
- // this fix solves it by detecting when the caret is at the beginning of such a table
1233
- // and then manually moves the caret infront of the table
1234
- if (tinymce.isGecko) {
1235
- ed.onKeyDown.add(function(ed, e) {
1236
- var rng, table, dom = ed.dom;
1237
 
1238
- // On gecko it's not possible to place the caret before a table
1239
- if (e.keyCode == 37 || e.keyCode == 38) {
1240
- rng = ed.selection.getRng();
1241
- table = dom.getParent(rng.startContainer, 'table');
1242
 
1243
- if (table && ed.getBody().firstChild == table) {
1244
- if (isAtStart(rng, table)) {
1245
- rng = dom.createRng();
1246
 
1247
- rng.setStartBefore(table);
1248
- rng.setEndBefore(table);
1249
 
1250
- ed.selection.setRng(rng);
1251
 
1252
- e.preventDefault();
1253
- }
1254
  }
1255
  }
1256
- });
1257
- }
 
1258
 
1259
- ed.onKeyUp.add(fixTableCaretPos);
1260
- ed.onSetContent.add(fixTableCaretPos);
1261
- ed.onVisualAid.add(fixTableCaretPos);
1262
 
1263
- ed.onPreProcess.add(function(ed, o) {
1264
- var last = o.node.lastChild;
 
 
 
 
 
1265
 
1266
- if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR')
1267
- ed.dom.remove(last);
1268
- });
1269
 
1270
- fixTableCaretPos();
1271
- ed.startContent = ed.getContent({format : 'raw'});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1272
  }
 
 
 
 
1273
  });
1274
 
1275
  // Register action commands
287
  endX = startX + (cols - 1);
288
  endY = startY + (rows - 1);
289
  } else {
290
+ startPos = endPos = null;
291
+
292
+ // Calculate start/end pos by checking for selected cells in grid works better with context menu
293
+ each(grid, function(row, y) {
294
+ each(row, function(cell, x) {
295
+ if (isCellSelected(cell)) {
296
+ if (!startPos) {
297
+ startPos = {x: x, y: y};
298
+ }
299
+
300
+ endPos = {x: x, y: y};
301
+ }
302
+ });
303
+ });
304
+
305
  // Use selection
306
  startX = startPos.x;
307
  startY = startPos.y;
614
  else
615
  dom.insertAfter(row, targetRow);
616
  });
617
+
618
+ // Remove current selection
619
+ dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
620
  };
621
 
622
  function getPos(target) {
1162
  }
1163
 
1164
  function getChildForDirection(parent, up) {
1165
+ var child = parent && parent[up ? 'lastChild' : 'firstChild'];
1166
+ // BR is not a valid table child to return in this case we return the table cell
1167
+ return child && child.nodeName === 'BR' ? ed.dom.getParent(child, 'td,th') : child;
1168
  }
1169
 
1170
  function moveCursorToStartOfElement(n) {
1234
 
1235
  ed.onKeyDown.add(moveSelection);
1236
  }
1237
+
1238
  // Fixes an issue on Gecko where it's impossible to place the caret behind a table
1239
  // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
1240
+ function fixTableCaretPos() {
1241
+ var last;
 
1242
 
1243
+ // Skip empty text nodes form the end
1244
+ for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
1245
 
1246
+ if (last && last.nodeName == 'TABLE') {
1247
+ if (ed.settings.forced_root_block)
1248
+ ed.dom.add(ed.getBody(), ed.settings.forced_root_block, null, tinymce.isIE ? '&nbsp;' : '<br data-mce-bogus="1" />');
1249
+ else
1250
+ ed.dom.add(ed.getBody(), 'br', {'data-mce-bogus': '1'});
1251
+ }
1252
+ };
1253
 
1254
+ // Fixes an bug where it's impossible to place the caret before a table in Gecko
1255
+ // this fix solves it by detecting when the caret is at the beginning of such a table
1256
+ // and then manually moves the caret infront of the table
1257
+ if (tinymce.isGecko) {
1258
+ ed.onKeyDown.add(function(ed, e) {
1259
+ var rng, table, dom = ed.dom;
1260
 
1261
+ // On gecko it's not possible to place the caret before a table
1262
+ if (e.keyCode == 37 || e.keyCode == 38) {
1263
+ rng = ed.selection.getRng();
1264
+ table = dom.getParent(rng.startContainer, 'table');
1265
 
1266
+ if (table && ed.getBody().firstChild == table) {
1267
+ if (isAtStart(rng, table)) {
1268
+ rng = dom.createRng();
1269
 
1270
+ rng.setStartBefore(table);
1271
+ rng.setEndBefore(table);
1272
 
1273
+ ed.selection.setRng(rng);
1274
 
1275
+ e.preventDefault();
 
1276
  }
1277
  }
1278
+ }
1279
+ });
1280
+ }
1281
 
1282
+ ed.onKeyUp.add(fixTableCaretPos);
1283
+ ed.onSetContent.add(fixTableCaretPos);
1284
+ ed.onVisualAid.add(fixTableCaretPos);
1285
 
1286
+ ed.onPreProcess.add(function(ed, o) {
1287
+ var last = o.node.lastChild;
1288
+
1289
+ if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 && (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) && last.previousSibling && last.previousSibling.nodeName == "TABLE") {
1290
+ ed.dom.remove(last);
1291
+ }
1292
+ });
1293
 
 
 
 
1294
 
1295
+ /**
1296
+ * Fixes bug in Gecko where shift-enter in table cell does not place caret on new line
1297
+ *
1298
+ * Removed: Since the new enter logic seems to fix this one.
1299
+ */
1300
+ /*
1301
+ if (tinymce.isGecko) {
1302
+ ed.onKeyDown.add(function(ed, e) {
1303
+ if (e.keyCode === tinymce.VK.ENTER && e.shiftKey) {
1304
+ var node = ed.selection.getRng().startContainer;
1305
+ var tableCell = dom.getParent(node, 'td,th');
1306
+ if (tableCell) {
1307
+ var zeroSizedNbsp = ed.getDoc().createTextNode("\uFEFF");
1308
+ dom.insertAfter(zeroSizedNbsp, node);
1309
+ }
1310
+ }
1311
+ });
1312
  }
1313
+ */
1314
+
1315
+ fixTableCaretPos();
1316
+ ed.startContent = ed.getContent({format : 'raw'});
1317
  });
1318
 
1319
  // Register action commands
tiny_mce/plugins/table/js/cell.js CHANGED
@@ -137,7 +137,7 @@ function updateAction() {
137
  do {
138
  if (cell == tdElm)
139
  break;
140
- col += cell.getAttribute("colspan");
141
  } while ((cell = nextCell(cell)) != null);
142
 
143
  for (var i=0; i<rows.length; i++) {
@@ -152,7 +152,7 @@ function updateAction() {
152
  cell = updateCell(cell, true);
153
  break;
154
  }
155
- curr += cell.getAttribute("colspan");
156
  } while ((cell = nextCell(cell)) != null);
157
  }
158
 
137
  do {
138
  if (cell == tdElm)
139
  break;
140
+ col += cell.getAttribute("colspan")?cell.getAttribute("colspan"):1;
141
  } while ((cell = nextCell(cell)) != null);
142
 
143
  for (var i=0; i<rows.length; i++) {
152
  cell = updateCell(cell, true);
153
  break;
154
  }
155
+ curr += cell.getAttribute("colspan")?cell.getAttribute("colspan"):1;
156
  } while ((cell = nextCell(cell)) != null);
157
  }
158
 
tiny_mce/plugins/table/js/table.js CHANGED
@@ -144,7 +144,7 @@ function insertTable() {
144
  //elm.outerHTML = elm.outerHTML;
145
 
146
  inst.nodeChanged();
147
- inst.execCommand('mceEndUndoLevel');
148
 
149
  // Repaint if dimensions changed
150
  if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
@@ -242,8 +242,16 @@ function insertTable() {
242
  } else
243
  inst.execCommand('mceInsertContent', false, html);
244
 
245
- tinymce.each(dom.select('table[data-mce-new]'), function(node) {
246
  var tdorth = dom.select('td,th', node);
 
 
 
 
 
 
 
 
247
 
248
  try {
249
  // IE9 might fail to do this selection
@@ -256,7 +264,7 @@ function insertTable() {
256
  });
257
 
258
  inst.addVisual();
259
- inst.execCommand('mceEndUndoLevel');
260
 
261
  tinyMCEPopup.close();
262
  }
@@ -299,6 +307,15 @@ function init() {
299
  var formObj = document.forms[0];
300
  var elm = dom.getParent(inst.selection.getNode(), "table");
301
 
 
 
 
 
 
 
 
 
 
302
  action = tinyMCEPopup.getWindowArg('action');
303
 
304
  if (!action)
144
  //elm.outerHTML = elm.outerHTML;
145
 
146
  inst.nodeChanged();
147
+ inst.execCommand('mceEndUndoLevel', false, {}, {skip_undo: true});
148
 
149
  // Repaint if dimensions changed
150
  if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
242
  } else
243
  inst.execCommand('mceInsertContent', false, html);
244
 
245
+ tinymce.each(dom.select('table[data-mce-new]'), function(node) {
246
  var tdorth = dom.select('td,th', node);
247
+
248
+ // Fixes a bug in IE where the caret cannot be placed after the table if the table is at the end of the document
249
+ if (tinymce.isIE && node.nextSibling == null) {
250
+ if (inst.settings.forced_root_block)
251
+ dom.insertAfter(dom.create(inst.settings.forced_root_block), node);
252
+ else
253
+ dom.insertAfter(dom.create('br', {'data-mce-bogus': '1'}), node);
254
+ }
255
 
256
  try {
257
  // IE9 might fail to do this selection
264
  });
265
 
266
  inst.addVisual();
267
+ inst.execCommand('mceEndUndoLevel', false, {}, {skip_undo: true});
268
 
269
  tinyMCEPopup.close();
270
  }
307
  var formObj = document.forms[0];
308
  var elm = dom.getParent(inst.selection.getNode(), "table");
309
 
310
+ // Hide advanced fields that isn't available in the schema
311
+ tinymce.each("summary id rules dir style frame".split(" "), function(name) {
312
+ var tr = tinyMCEPopup.dom.getParent(name, "tr") || tinyMCEPopup.dom.getParent("t" + name, "tr");
313
+
314
+ if (tr && !tinyMCEPopup.editor.schema.isValid("table", name)) {
315
+ tr.style.display = 'none';
316
+ }
317
+ });
318
+
319
  action = tinyMCEPopup.getWindowArg('action');
320
 
321
  if (!action)
tiny_mce/plugins/xhtmlxtras/abbr.htm DELETED
@@ -1,142 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.title_abbr_element}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
8
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
9
- <script type="text/javascript" src="js/element_common.js"></script>
10
- <script type="text/javascript" src="js/abbr.js"></script>
11
- <link rel="stylesheet" type="text/css" href="css/popup.css" />
12
- </head>
13
- <body style="display: none" role="application" aria-labelledby="app_title">
14
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_abbr_element}</span>
15
- <form onsubmit="insertAbbr();return false;" action="#">
16
- <div class="tabs">
17
- <ul>
18
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
19
- <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
20
- </ul>
21
- </div>
22
-
23
- <div class="panel_wrapper">
24
- <div id="general_panel" class="panel current">
25
- <fieldset>
26
- <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
27
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
28
- <tr>
29
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
30
- <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td>
31
- </tr>
32
- <tr>
33
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
34
- <td><input id="id" name="id" type="text" value="" class="field" /></td>
35
- </tr>
36
- <tr>
37
- <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td>
38
- <td>
39
- <select id="class" name="class" class="field mceEditableSelect">
40
- <option value="">{#not_set}</option>
41
- </select>
42
- </td>
43
- </tr>
44
- <tr>
45
- <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
46
- <td><input id="style" name="style" type="text" value="" class="field" /></td>
47
- </tr>
48
- <tr>
49
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
50
- <td>
51
- <select id="dir" name="dir" class="field">
52
- <option value="">{#not_set}</option>
53
- <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option>
54
- <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option>
55
- </select>
56
- </td>
57
- </tr>
58
- <tr>
59
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
60
- <td>
61
- <input id="lang" name="lang" type="text" value="" class="field" />
62
- </td>
63
- </tr>
64
- </table>
65
- </fieldset>
66
- </div>
67
- <div id="events_panel" class="panel">
68
- <fieldset>
69
- <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
70
-
71
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
72
- <tr>
73
- <td class="label"><label for="onfocus">onfocus</label>:</td>
74
- <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td>
75
- </tr>
76
-
77
- <tr>
78
- <td class="label"><label for="onblur">onblur</label>:</td>
79
- <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td>
80
- </tr>
81
-
82
- <tr>
83
- <td class="label"><label for="onclick">onclick</label>:</td>
84
- <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td>
85
- </tr>
86
-
87
- <tr>
88
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
89
- <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td>
90
- </tr>
91
-
92
- <tr>
93
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
94
- <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td>
95
- </tr>
96
-
97
- <tr>
98
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
99
- <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td>
100
- </tr>
101
-
102
- <tr>
103
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
104
- <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td>
105
- </tr>
106
-
107
- <tr>
108
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
109
- <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td>
110
- </tr>
111
-
112
- <tr>
113
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
114
- <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td>
115
- </tr>
116
-
117
- <tr>
118
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
119
- <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td>
120
- </tr>
121
-
122
- <tr>
123
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
124
- <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td>
125
- </tr>
126
-
127
- <tr>
128
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
129
- <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td>
130
- </tr>
131
- </table>
132
- </fieldset>
133
- </div>
134
- </div>
135
- <div class="mceActionPanel">
136
- <input type="submit" id="insert" name="insert" value="{#update}" />
137
- <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAbbr();" style="display: none;" />
138
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
139
- </div>
140
- </form>
141
- </body>
142
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/acronym.htm DELETED
@@ -1,142 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.title_acronym_element}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
8
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
9
- <script type="text/javascript" src="js/element_common.js"></script>
10
- <script type="text/javascript" src="js/acronym.js"></script>
11
- <link rel="stylesheet" type="text/css" href="css/popup.css" />
12
- </head>
13
- <body style="display: none" role="application" aria-labelledby="app_title">
14
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_acronym_element}</span>
15
- <form onsubmit="insertAcronym();return false;" action="#">
16
- <div class="tabs">
17
- <ul>
18
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
19
- <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
20
- </ul>
21
- </div>
22
-
23
- <div class="panel_wrapper">
24
- <div id="general_panel" class="panel current">
25
- <fieldset>
26
- <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
27
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
28
- <tr>
29
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
30
- <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td>
31
- </tr>
32
- <tr>
33
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
34
- <td><input id="id" name="id" type="text" value="" class="field" /></td>
35
- </tr>
36
- <tr>
37
- <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td>
38
- <td>
39
- <select id="class" name="class" class="field mceEditableSelect">
40
- <option value="">{#not_set}</option>
41
- </select>
42
- </td>
43
- </tr>
44
- <tr>
45
- <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
46
- <td><input id="style" name="style" type="text" value="" class="field" /></td>
47
- </tr>
48
- <tr>
49
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
50
- <td>
51
- <select id="dir" name="dir" class="field">
52
- <option value="">{#not_set}</option>
53
- <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option>
54
- <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option>
55
- </select>
56
- </td>
57
- </tr>
58
- <tr>
59
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
60
- <td>
61
- <input id="lang" name="lang" type="text" value="" class="field" />
62
- </td>
63
- </tr>
64
- </table>
65
- </fieldset>
66
- </div>
67
- <div id="events_panel" class="panel">
68
- <fieldset>
69
- <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
70
-
71
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
72
- <tr>
73
- <td class="label"><label for="onfocus">onfocus</label>:</td>
74
- <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td>
75
- </tr>
76
-
77
- <tr>
78
- <td class="label"><label for="onblur">onblur</label>:</td>
79
- <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td>
80
- </tr>
81
-
82
- <tr>
83
- <td class="label"><label for="onclick">onclick</label>:</td>
84
- <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td>
85
- </tr>
86
-
87
- <tr>
88
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
89
- <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td>
90
- </tr>
91
-
92
- <tr>
93
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
94
- <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td>
95
- </tr>
96
-
97
- <tr>
98
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
99
- <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td>
100
- </tr>
101
-
102
- <tr>
103
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
104
- <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td>
105
- </tr>
106
-
107
- <tr>
108
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
109
- <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td>
110
- </tr>
111
-
112
- <tr>
113
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
114
- <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td>
115
- </tr>
116
-
117
- <tr>
118
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
119
- <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td>
120
- </tr>
121
-
122
- <tr>
123
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
124
- <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td>
125
- </tr>
126
-
127
- <tr>
128
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
129
- <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td>
130
- </tr>
131
- </table>
132
- </fieldset>
133
- </div>
134
- </div>
135
- <div class="mceActionPanel">
136
- <input type="submit" id="insert" name="insert" value="{#update}" />
137
- <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAcronym();" style="display: none;" />
138
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
139
- </div>
140
- </form>
141
- </body>
142
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/attributes.htm DELETED
@@ -1,149 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.attribs_title}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
8
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
9
- <script type="text/javascript" src="js/attributes.js"></script>
10
- <link rel="stylesheet" type="text/css" href="css/attributes.css" />
11
- </head>
12
- <body style="display: none" role="application" aria-labelledby="app_title">
13
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.attribs_title}</span>
14
- <form onsubmit="insertAction();return false;" action="#">
15
- <div class="tabs">
16
- <ul>
17
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_attrib_tab}</a></span></li>
18
- <li id="events_tab" aria-controls="events_panel"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_events_tab}</a></span></li>
19
- </ul>
20
- </div>
21
-
22
- <div class="panel_wrapper">
23
- <div id="general_panel" class="panel current">
24
- <fieldset>
25
- <legend>{#xhtmlxtras_dlg.attribute_attrib_tab}</legend>
26
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
27
- <tr>
28
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
29
- <td><input id="title" name="title" type="text" value="" class="mceFocus" /></td>
30
- </tr>
31
- <tr>
32
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
33
- <td><input id="id" name="id" type="text" value="" /></td>
34
- </tr>
35
- <tr>
36
- <td><label id="classlabel" for="classlist">{#class_name}</label></td>
37
- <td>
38
- <select id="classlist" name="classlist" class="mceEditableSelect">
39
- <option value="" selected="selected">{#not_set}</option>
40
- </select>
41
- </td>
42
- </tr>
43
- <tr>
44
- <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
45
- <td><input id="style" name="style" type="text" value="" /></td>
46
- </tr>
47
- <tr>
48
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
49
- <td>
50
- <select id="dir" name="dir">
51
- <option value="">{#not_set}</option>
52
- <option value="ltr">{#xhtmlxtras_dlg.option_ltr}</option>
53
- <option value="rtl">{#xhtmlxtras_dlg.option_rtl}</option>
54
- </select>
55
- </td>
56
- </tr>
57
- <tr>
58
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
59
- <td>
60
- <input id="lang" name="lang" type="text" value="" />
61
- </td>
62
- </tr>
63
- <tr>
64
- <td><label id="tabindexlabel" for="tabindex">{#xhtmlxtras_dlg.attribute_label_tabindex}</label></td>
65
- <td><input type="text" id="tabindex" name="tabindex" value="" /></td>
66
- </tr>
67
-
68
- <tr>
69
- <td><label id="accesskeylabel" for="accesskey">{#xhtmlxtras_dlg.attribute_label_accesskey}</label></td>
70
- <td><input type="text" id="accesskey" name="accesskey" value="" /></td>
71
- </tr>
72
- </table>
73
- </fieldset>
74
- </div>
75
- <div id="events_panel" class="panel">
76
- <fieldset>
77
- <legend>{#xhtmlxtras_dlg.attribute_events_tab}</legend>
78
-
79
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
80
- <tr>
81
- <td class="label"><label for="onfocus">onfocus</label>:</td>
82
- <td><input id="onfocus" name="onfocus" type="text" value="" /></td>
83
- </tr>
84
-
85
- <tr>
86
- <td class="label"><label for="onblur">onblur</label>:</td>
87
- <td><input id="onblur" name="onblur" type="text" value="" /></td>
88
- </tr>
89
-
90
- <tr>
91
- <td class="label"><label for="onclick">onclick</label>:</td>
92
- <td><input id="onclick" name="onclick" type="text" value="" /></td>
93
- </tr>
94
-
95
- <tr>
96
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
97
- <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td>
98
- </tr>
99
-
100
- <tr>
101
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
102
- <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td>
103
- </tr>
104
-
105
- <tr>
106
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
107
- <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td>
108
- </tr>
109
-
110
- <tr>
111
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
112
- <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td>
113
- </tr>
114
-
115
- <tr>
116
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
117
- <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td>
118
- </tr>
119
-
120
- <tr>
121
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
122
- <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td>
123
- </tr>
124
-
125
- <tr>
126
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
127
- <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td>
128
- </tr>
129
-
130
- <tr>
131
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
132
- <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td>
133
- </tr>
134
-
135
- <tr>
136
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
137
- <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td>
138
- </tr>
139
- </table>
140
- </fieldset>
141
- </div>
142
- </div>
143
- <div class="mceActionPanel">
144
- <input type="submit" id="insert" name="insert" value="{#insert}" />
145
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
146
- </div>
147
- </form>
148
- </body>
149
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/cite.htm DELETED
@@ -1,142 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.title_cite_element}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
8
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
9
- <script type="text/javascript" src="js/element_common.js"></script>
10
- <script type="text/javascript" src="js/cite.js"></script>
11
- <link rel="stylesheet" type="text/css" href="css/popup.css" />
12
- </head>
13
- <body style="display: none" role="application" aria-labelledby="app_title">
14
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_cite_element}</span>
15
- <form onsubmit="insertCite();return false;" action="#">
16
- <div class="tabs">
17
- <ul>
18
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
19
- <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
20
- </ul>
21
- </div>
22
-
23
- <div class="panel_wrapper">
24
- <div id="general_panel" class="panel current">
25
- <fieldset>
26
- <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
27
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
28
- <tr>
29
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
30
- <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td>
31
- </tr>
32
- <tr>
33
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
34
- <td><input id="id" name="id" type="text" value="" class="field" /></td>
35
- </tr>
36
- <tr>
37
- <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td>
38
- <td>
39
- <select id="class" name="class" class="field mceEditableSelect">
40
- <option value="">{#not_set}</option>
41
- </select>
42
- </td>
43
- </tr>
44
- <tr>
45
- <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
46
- <td><input id="style" name="style" type="text" value="" class="field" /></td>
47
- </tr>
48
- <tr>
49
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
50
- <td>
51
- <select id="dir" name="dir" class="field">
52
- <option value="">{#not_set}</option>
53
- <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option>
54
- <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option>
55
- </select>
56
- </td>
57
- </tr>
58
- <tr>
59
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
60
- <td>
61
- <input id="lang" name="lang" type="text" value="" class="field" />
62
- </td>
63
- </tr>
64
- </table>
65
- </fieldset>
66
- </div>
67
- <div id="events_panel" class="panel">
68
- <fieldset>
69
- <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
70
-
71
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
72
- <tr>
73
- <td class="label"><label for="onfocus">onfocus</label>:</td>
74
- <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td>
75
- </tr>
76
-
77
- <tr>
78
- <td class="label"><label for="onblur">onblur</label>:</td>
79
- <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td>
80
- </tr>
81
-
82
- <tr>
83
- <td class="label"><label for="onclick">onclick</label>:</td>
84
- <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td>
85
- </tr>
86
-
87
- <tr>
88
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
89
- <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td>
90
- </tr>
91
-
92
- <tr>
93
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
94
- <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td>
95
- </tr>
96
-
97
- <tr>
98
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
99
- <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td>
100
- </tr>
101
-
102
- <tr>
103
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
104
- <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td>
105
- </tr>
106
-
107
- <tr>
108
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
109
- <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td>
110
- </tr>
111
-
112
- <tr>
113
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
114
- <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td>
115
- </tr>
116
-
117
- <tr>
118
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
119
- <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td>
120
- </tr>
121
-
122
- <tr>
123
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
124
- <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td>
125
- </tr>
126
-
127
- <tr>
128
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
129
- <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td>
130
- </tr>
131
- </table>
132
- </fieldset>
133
- </div>
134
- </div>
135
- <div class="mceActionPanel">
136
- <input type="submit" id="insert" name="insert" value="{#update}" />
137
- <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeCite();" style="display: none;" />
138
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
139
- </div>
140
- </form>
141
- </body>
142
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/css/attributes.css DELETED
@@ -1,11 +0,0 @@
1
- .panel_wrapper div.current {
2
- height: 290px;
3
- }
4
-
5
- #id, #style, #title, #dir, #hreflang, #lang, #classlist, #tabindex, #accesskey {
6
- width: 200px;
7
- }
8
-
9
- #events_panel input {
10
- width: 200px;
11
- }
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/css/popup.css DELETED
@@ -1,9 +0,0 @@
1
- input.field, select.field {width:200px;}
2
- input.picker {width:179px; margin-left: 5px;}
3
- input.disabled {border-color:#F2F2F2;}
4
- img.picker {vertical-align:text-bottom; cursor:pointer;}
5
- h1 {padding: 0 0 5px 0;}
6
- .panel_wrapper div.current {height:160px;}
7
- #xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {height: 230px;}
8
- a.browse span {display:block; width:20px; height:20px; background:url('../../../themes/advanced/img/icons.gif') -140px -20px;}
9
- #datetime {width:180px;}
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/del.htm DELETED
@@ -1,162 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.title_del_element}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
8
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
9
- <script type="text/javascript" src="js/element_common.js"></script>
10
- <script type="text/javascript" src="js/del.js"></script>
11
- <link rel="stylesheet" type="text/css" href="css/popup.css" />
12
- </head>
13
- <body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title">
14
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_del_element}</span>
15
- <form onsubmit="insertDel();return false;" action="#">
16
- <div class="tabs">
17
- <ul>
18
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
19
- <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
20
- </ul>
21
- </div>
22
-
23
- <div class="panel_wrapper">
24
- <div id="general_panel" class="panel current">
25
- <fieldset>
26
- <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>
27
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
28
- <tr>
29
- <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td>
30
- <td>
31
- <table role="presentation" border="0" cellspacing="0" cellpadding="0">
32
- <tr>
33
- <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td>
34
- <td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>
35
- </tr>
36
- </table>
37
- </td>
38
- </tr>
39
- <tr>
40
- <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td>
41
- <td><input id="cite" name="cite" type="text" value="" class="field" /></td>
42
- </tr>
43
- </table>
44
- </fieldset>
45
- <fieldset>
46
- <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
47
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
48
- <tr>
49
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
50
- <td><input id="title" name="title" type="text" value="" class="field" /></td>
51
- </tr>
52
- <tr>
53
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
54
- <td><input id="id" name="id" type="text" value="" class="field" /></td>
55
- </tr>
56
- <tr>
57
- <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td>
58
- <td>
59
- <select id="class" name="class" class="field mceEditableSelect">
60
- <option value="">{#not_set}</option>
61
- </select>
62
- </td>
63
- </tr>
64
- <tr>
65
- <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
66
- <td><input id="style" name="style" type="text" value="" class="field" /></td>
67
- </tr>
68
- <tr>
69
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
70
- <td>
71
- <select id="dir" name="dir" class="field">
72
- <option value="">{#not_set}</option>
73
- <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option>
74
- <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option>
75
- </select>
76
- </td>
77
- </tr>
78
- <tr>
79
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
80
- <td>
81
- <input id="lang" name="lang" type="text" value="" class="field" />
82
- </td>
83
- </tr>
84
- </table>
85
- </fieldset>
86
- </div>
87
- <div id="events_panel" class="panel">
88
- <fieldset>
89
- <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
90
-
91
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
92
- <tr>
93
- <td class="label"><label for="onfocus">onfocus</label>:</td>
94
- <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td>
95
- </tr>
96
-
97
- <tr>
98
- <td class="label"><label for="onblur">onblur</label>:</td>
99
- <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td>
100
- </tr>
101
-
102
- <tr>
103
- <td class="label"><label for="onclick">onclick</label>:</td>
104
- <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td>
105
- </tr>
106
-
107
- <tr>
108
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
109
- <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td>
110
- </tr>
111
-
112
- <tr>
113
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
114
- <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td>
115
- </tr>
116
-
117
- <tr>
118
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
119
- <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td>
120
- </tr>
121
-
122
- <tr>
123
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
124
- <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td>
125
- </tr>
126
-
127
- <tr>
128
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
129
- <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td>
130
- </tr>
131
-
132
- <tr>
133
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
134
- <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td>
135
- </tr>
136
-
137
- <tr>
138
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
139
- <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td>
140
- </tr>
141
-
142
- <tr>
143
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
144
- <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td>
145
- </tr>
146
-
147
- <tr>
148
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
149
- <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td>
150
- </tr>
151
- </table>
152
- </fieldset>
153
- </div>
154
- </div>
155
- <div class="mceActionPanel">
156
- <input type="submit" id="insert" name="insert" value="{#update}" />
157
- <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeDel();" style="display: none;" />
158
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
159
- </div>
160
- </form>
161
- </body>
162
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/editor_plugin.js DELETED
@@ -1 +0,0 @@
1
- (function(){tinymce.create("tinymce.plugins.XHTMLXtrasPlugin",{init:function(a,b){a.addCommand("mceCite",function(){a.windowManager.open({file:b+"/cite.htm",width:350+parseInt(a.getLang("xhtmlxtras.cite_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.cite_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAcronym",function(){a.windowManager.open({file:b+"/acronym.htm",width:350+parseInt(a.getLang("xhtmlxtras.acronym_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.acronym_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAbbr",function(){a.windowManager.open({file:b+"/abbr.htm",width:350+parseInt(a.getLang("xhtmlxtras.abbr_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.abbr_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceDel",function(){a.windowManager.open({file:b+"/del.htm",width:340+parseInt(a.getLang("xhtmlxtras.del_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.del_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceIns",function(){a.windowManager.open({file:b+"/ins.htm",width:340+parseInt(a.getLang("xhtmlxtras.ins_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.ins_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAttributes",function(){a.windowManager.open({file:b+"/attributes.htm",width:380+parseInt(a.getLang("xhtmlxtras.attr_delta_width",0)),height:370+parseInt(a.getLang("xhtmlxtras.attr_delta_height",0)),inline:1},{plugin_url:b})});a.addButton("cite",{title:"xhtmlxtras.cite_desc",cmd:"mceCite"});a.addButton("acronym",{title:"xhtmlxtras.acronym_desc",cmd:"mceAcronym"});a.addButton("abbr",{title:"xhtmlxtras.abbr_desc",cmd:"mceAbbr"});a.addButton("del",{title:"xhtmlxtras.del_desc",cmd:"mceDel"});a.addButton("ins",{title:"xhtmlxtras.ins_desc",cmd:"mceIns"});a.addButton("attribs",{title:"xhtmlxtras.attribs_desc",cmd:"mceAttributes"});a.onNodeChange.add(function(d,c,f,e){f=d.dom.getParent(f,"CITE,ACRONYM,ABBR,DEL,INS");c.setDisabled("cite",e);c.setDisabled("acronym",e);c.setDisabled("abbr",e);c.setDisabled("del",e);c.setDisabled("ins",e);c.setDisabled("attribs",f&&f.nodeName=="BODY");c.setActive("cite",0);c.setActive("acronym",0);c.setActive("abbr",0);c.setActive("del",0);c.setActive("ins",0);if(f){do{c.setDisabled(f.nodeName.toLowerCase(),0);c.setActive(f.nodeName.toLowerCase(),1)}while(f=f.parentNode)}});a.onPreInit.add(function(){a.dom.create("abbr")})},getInfo:function(){return{longname:"XHTML Xtras Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("xhtmlxtras",tinymce.plugins.XHTMLXtrasPlugin)})();
 
tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js DELETED
@@ -1,132 +0,0 @@
1
- /**
2
- * editor_plugin_src.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- (function() {
12
- tinymce.create('tinymce.plugins.XHTMLXtrasPlugin', {
13
- init : function(ed, url) {
14
- // Register commands
15
- ed.addCommand('mceCite', function() {
16
- ed.windowManager.open({
17
- file : url + '/cite.htm',
18
- width : 350 + parseInt(ed.getLang('xhtmlxtras.cite_delta_width', 0)),
19
- height : 250 + parseInt(ed.getLang('xhtmlxtras.cite_delta_height', 0)),
20
- inline : 1
21
- }, {
22
- plugin_url : url
23
- });
24
- });
25
-
26
- ed.addCommand('mceAcronym', function() {
27
- ed.windowManager.open({
28
- file : url + '/acronym.htm',
29
- width : 350 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)),
30
- height : 250 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_height', 0)),
31
- inline : 1
32
- }, {
33
- plugin_url : url
34
- });
35
- });
36
-
37
- ed.addCommand('mceAbbr', function() {
38
- ed.windowManager.open({
39
- file : url + '/abbr.htm',
40
- width : 350 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)),
41
- height : 250 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_height', 0)),
42
- inline : 1
43
- }, {
44
- plugin_url : url
45
- });
46
- });
47
-
48
- ed.addCommand('mceDel', function() {
49
- ed.windowManager.open({
50
- file : url + '/del.htm',
51
- width : 340 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)),
52
- height : 310 + parseInt(ed.getLang('xhtmlxtras.del_delta_height', 0)),
53
- inline : 1
54
- }, {
55
- plugin_url : url
56
- });
57
- });
58
-
59
- ed.addCommand('mceIns', function() {
60
- ed.windowManager.open({
61
- file : url + '/ins.htm',
62
- width : 340 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)),
63
- height : 310 + parseInt(ed.getLang('xhtmlxtras.ins_delta_height', 0)),
64
- inline : 1
65
- }, {
66
- plugin_url : url
67
- });
68
- });
69
-
70
- ed.addCommand('mceAttributes', function() {
71
- ed.windowManager.open({
72
- file : url + '/attributes.htm',
73
- width : 380 + parseInt(ed.getLang('xhtmlxtras.attr_delta_width', 0)),
74
- height : 370 + parseInt(ed.getLang('xhtmlxtras.attr_delta_height', 0)),
75
- inline : 1
76
- }, {
77
- plugin_url : url
78
- });
79
- });
80
-
81
- // Register buttons
82
- ed.addButton('cite', {title : 'xhtmlxtras.cite_desc', cmd : 'mceCite'});
83
- ed.addButton('acronym', {title : 'xhtmlxtras.acronym_desc', cmd : 'mceAcronym'});
84
- ed.addButton('abbr', {title : 'xhtmlxtras.abbr_desc', cmd : 'mceAbbr'});
85
- ed.addButton('del', {title : 'xhtmlxtras.del_desc', cmd : 'mceDel'});
86
- ed.addButton('ins', {title : 'xhtmlxtras.ins_desc', cmd : 'mceIns'});
87
- ed.addButton('attribs', {title : 'xhtmlxtras.attribs_desc', cmd : 'mceAttributes'});
88
-
89
- ed.onNodeChange.add(function(ed, cm, n, co) {
90
- n = ed.dom.getParent(n, 'CITE,ACRONYM,ABBR,DEL,INS');
91
-
92
- cm.setDisabled('cite', co);
93
- cm.setDisabled('acronym', co);
94
- cm.setDisabled('abbr', co);
95
- cm.setDisabled('del', co);
96
- cm.setDisabled('ins', co);
97
- cm.setDisabled('attribs', n && n.nodeName == 'BODY');
98
- cm.setActive('cite', 0);
99
- cm.setActive('acronym', 0);
100
- cm.setActive('abbr', 0);
101
- cm.setActive('del', 0);
102
- cm.setActive('ins', 0);
103
-
104
- // Activate all
105
- if (n) {
106
- do {
107
- cm.setDisabled(n.nodeName.toLowerCase(), 0);
108
- cm.setActive(n.nodeName.toLowerCase(), 1);
109
- } while (n = n.parentNode);
110
- }
111
- });
112
-
113
- ed.onPreInit.add(function() {
114
- // Fixed IE issue where it can't handle these elements correctly
115
- ed.dom.create('abbr');
116
- });
117
- },
118
-
119
- getInfo : function() {
120
- return {
121
- longname : 'XHTML Xtras Plugin',
122
- author : 'Moxiecode Systems AB',
123
- authorurl : 'http://tinymce.moxiecode.com',
124
- infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',
125
- version : tinymce.majorVersion + "." + tinymce.minorVersion
126
- };
127
- }
128
- });
129
-
130
- // Register plugin
131
- tinymce.PluginManager.add('xhtmlxtras', tinymce.plugins.XHTMLXtrasPlugin);
132
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/ins.htm DELETED
@@ -1,162 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <title>{#xhtmlxtras_dlg.title_ins_element}</title>
5
- <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
6
- <script type="text/javascript" src="../../utils/mctabs.js"></script>
7
- <script type="text/javascript" src="../../utils/form_utils.js"></script>
8
- <script type="text/javascript" src="../../utils/editable_selects.js"></script>
9
- <script type="text/javascript" src="js/element_common.js"></script>
10
- <script type="text/javascript" src="js/ins.js"></script>
11
- <link rel="stylesheet" type="text/css" href="css/popup.css" />
12
- </head>
13
- <body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title">
14
- <span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_ins_element}</span>
15
- <form onsubmit="insertIns();return false;" action="#">
16
- <div class="tabs">
17
- <ul>
18
- <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
19
- <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
20
- </ul>
21
- </div>
22
-
23
- <div class="panel_wrapper">
24
- <div id="general_panel" class="panel current">
25
- <fieldset>
26
- <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>
27
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
28
- <tr>
29
- <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td>
30
- <td>
31
- <table role="presentation" border="0" cellspacing="0" cellpadding="0">
32
- <tr>
33
- <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td>
34
- <td ><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>
35
- </tr>
36
- </table>
37
- </td>
38
- </tr>
39
- <tr >
40
- <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td>
41
- <td><input id="cite" name="cite" type="text" value="" class="field" /></td>
42
- </tr>
43
- </table>
44
- </fieldset>
45
- <fieldset>
46
- <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
47
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
48
- <tr>
49
- <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td>
50
- <td><input id="title" name="title" type="text" value="" class="field" /></td>
51
- </tr>
52
- <tr>
53
- <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td>
54
- <td><input id="id" name="id" type="text" value="" class="field" /></td>
55
- </tr>
56
- <tr>
57
- <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td>
58
- <td>
59
- <select id="class" name="class" class="field mceEditableSelect">
60
- <option value="">{#not_set}</option>
61
- </select>
62
- </td>
63
- </tr>
64
- <tr>
65
- <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td>
66
- <td><input id="style" name="style" type="text" value="" class="field" /></td>
67
- </tr>
68
- <tr>
69
- <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td>
70
- <td>
71
- <select id="dir" name="dir" class="field">
72
- <option value="">{#not_set}</option>
73
- <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option>
74
- <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option>
75
- </select>
76
- </td>
77
- </tr>
78
- <tr>
79
- <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td>
80
- <td>
81
- <input id="lang" name="lang" type="text" value="" class="field" />
82
- </td>
83
- </tr>
84
- </table>
85
- </fieldset>
86
- </div>
87
- <div id="events_panel" class="panel">
88
- <fieldset>
89
- <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
90
-
91
- <table role="presentation" border="0" cellpadding="0" cellspacing="4">
92
- <tr>
93
- <td class="label"><label for="onfocus">onfocus</label>:</td>
94
- <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td>
95
- </tr>
96
-
97
- <tr>
98
- <td class="label"><label for="onblur">onblur</label>:</td>
99
- <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td>
100
- </tr>
101
-
102
- <tr>
103
- <td class="label"><label for="onclick">onclick</label>:</td>
104
- <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td>
105
- </tr>
106
-
107
- <tr>
108
- <td class="label"><label for="ondblclick">ondblclick</label>:</td>
109
- <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td>
110
- </tr>
111
-
112
- <tr>
113
- <td class="label"><label for="onmousedown">onmousedown</label>:</td>
114
- <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td>
115
- </tr>
116
-
117
- <tr>
118
- <td class="label"><label for="onmouseup">onmouseup</label>:</td>
119
- <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td>
120
- </tr>
121
-
122
- <tr>
123
- <td class="label"><label for="onmouseover">onmouseover</label>:</td>
124
- <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td>
125
- </tr>
126
-
127
- <tr>
128
- <td class="label"><label for="onmousemove">onmousemove</label>:</td>
129
- <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td>
130
- </tr>
131
-
132
- <tr>
133
- <td class="label"><label for="onmouseout">onmouseout</label>:</td>
134
- <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td>
135
- </tr>
136
-
137
- <tr>
138
- <td class="label"><label for="onkeypress">onkeypress</label>:</td>
139
- <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td>
140
- </tr>
141
-
142
- <tr>
143
- <td class="label"><label for="onkeydown">onkeydown</label>:</td>
144
- <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td>
145
- </tr>
146
-
147
- <tr>
148
- <td class="label"><label for="onkeyup">onkeyup</label>:</td>
149
- <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td>
150
- </tr>
151
- </table>
152
- </fieldset>
153
- </div>
154
- </div>
155
- <div class="mceActionPanel">
156
- <input type="submit" id="insert" name="insert" value="{#update}" />
157
- <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeIns();" style="display: none;" />
158
- <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
159
- </div>
160
- </form>
161
- </body>
162
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/abbr.js DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * abbr.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- SXE.initElementDialog('abbr');
13
- if (SXE.currentAction == "update") {
14
- SXE.showRemoveButton();
15
- }
16
- }
17
-
18
- function insertAbbr() {
19
- SXE.insertElement('abbr');
20
- tinyMCEPopup.close();
21
- }
22
-
23
- function removeAbbr() {
24
- SXE.removeElement('abbr');
25
- tinyMCEPopup.close();
26
- }
27
-
28
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/acronym.js DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * acronym.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- SXE.initElementDialog('acronym');
13
- if (SXE.currentAction == "update") {
14
- SXE.showRemoveButton();
15
- }
16
- }
17
-
18
- function insertAcronym() {
19
- SXE.insertElement('acronym');
20
- tinyMCEPopup.close();
21
- }
22
-
23
- function removeAcronym() {
24
- SXE.removeElement('acronym');
25
- tinyMCEPopup.close();
26
- }
27
-
28
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/attributes.js DELETED
@@ -1,111 +0,0 @@
1
- /**
2
- * attributes.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- tinyMCEPopup.resizeToInnerSize();
13
- var inst = tinyMCEPopup.editor;
14
- var dom = inst.dom;
15
- var elm = inst.selection.getNode();
16
- var f = document.forms[0];
17
- var onclick = dom.getAttrib(elm, 'onclick');
18
-
19
- setFormValue('title', dom.getAttrib(elm, 'title'));
20
- setFormValue('id', dom.getAttrib(elm, 'id'));
21
- setFormValue('style', dom.getAttrib(elm, "style"));
22
- setFormValue('dir', dom.getAttrib(elm, 'dir'));
23
- setFormValue('lang', dom.getAttrib(elm, 'lang'));
24
- setFormValue('tabindex', dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
25
- setFormValue('accesskey', dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
26
- setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));
27
- setFormValue('onblur', dom.getAttrib(elm, 'onblur'));
28
- setFormValue('onclick', onclick);
29
- setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));
30
- setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));
31
- setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));
32
- setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));
33
- setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));
34
- setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));
35
- setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));
36
- setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));
37
- setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));
38
- className = dom.getAttrib(elm, 'class');
39
-
40
- addClassesToList('classlist', 'advlink_styles');
41
- selectByValue(f, 'classlist', className, true);
42
-
43
- TinyMCE_EditableSelects.init();
44
- }
45
-
46
- function setFormValue(name, value) {
47
- if(value && document.forms[0].elements[name]){
48
- document.forms[0].elements[name].value = value;
49
- }
50
- }
51
-
52
- function insertAction() {
53
- var inst = tinyMCEPopup.editor;
54
- var elm = inst.selection.getNode();
55
-
56
- setAllAttribs(elm);
57
- tinyMCEPopup.execCommand("mceEndUndoLevel");
58
- tinyMCEPopup.close();
59
- }
60
-
61
- function setAttrib(elm, attrib, value) {
62
- var formObj = document.forms[0];
63
- var valueElm = formObj.elements[attrib.toLowerCase()];
64
- var inst = tinyMCEPopup.editor;
65
- var dom = inst.dom;
66
-
67
- if (typeof(value) == "undefined" || value == null) {
68
- value = "";
69
-
70
- if (valueElm)
71
- value = valueElm.value;
72
- }
73
-
74
- dom.setAttrib(elm, attrib.toLowerCase(), value);
75
- }
76
-
77
- function setAllAttribs(elm) {
78
- var f = document.forms[0];
79
-
80
- setAttrib(elm, 'title');
81
- setAttrib(elm, 'id');
82
- setAttrib(elm, 'style');
83
- setAttrib(elm, 'class', getSelectValue(f, 'classlist'));
84
- setAttrib(elm, 'dir');
85
- setAttrib(elm, 'lang');
86
- setAttrib(elm, 'tabindex');
87
- setAttrib(elm, 'accesskey');
88
- setAttrib(elm, 'onfocus');
89
- setAttrib(elm, 'onblur');
90
- setAttrib(elm, 'onclick');
91
- setAttrib(elm, 'ondblclick');
92
- setAttrib(elm, 'onmousedown');
93
- setAttrib(elm, 'onmouseup');
94
- setAttrib(elm, 'onmouseover');
95
- setAttrib(elm, 'onmousemove');
96
- setAttrib(elm, 'onmouseout');
97
- setAttrib(elm, 'onkeypress');
98
- setAttrib(elm, 'onkeydown');
99
- setAttrib(elm, 'onkeyup');
100
-
101
- // Refresh in old MSIE
102
- // if (tinyMCE.isMSIE5)
103
- // elm.outerHTML = elm.outerHTML;
104
- }
105
-
106
- function insertAttribute() {
107
- tinyMCEPopup.close();
108
- }
109
-
110
- tinyMCEPopup.onInit.add(init);
111
- tinyMCEPopup.requireLangPack();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/cite.js DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * cite.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- SXE.initElementDialog('cite');
13
- if (SXE.currentAction == "update") {
14
- SXE.showRemoveButton();
15
- }
16
- }
17
-
18
- function insertCite() {
19
- SXE.insertElement('cite');
20
- tinyMCEPopup.close();
21
- }
22
-
23
- function removeCite() {
24
- SXE.removeElement('cite');
25
- tinyMCEPopup.close();
26
- }
27
-
28
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/del.js DELETED
@@ -1,53 +0,0 @@
1
- /**
2
- * del.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- SXE.initElementDialog('del');
13
- if (SXE.currentAction == "update") {
14
- setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));
15
- setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));
16
- SXE.showRemoveButton();
17
- }
18
- }
19
-
20
- function setElementAttribs(elm) {
21
- setAllCommonAttribs(elm);
22
- setAttrib(elm, 'datetime');
23
- setAttrib(elm, 'cite');
24
- elm.removeAttribute('data-mce-new');
25
- }
26
-
27
- function insertDel() {
28
- var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'DEL');
29
-
30
- if (elm == null) {
31
- var s = SXE.inst.selection.getContent();
32
- if(s.length > 0) {
33
- insertInlineElement('del');
34
- var elementArray = SXE.inst.dom.select('del[data-mce-new]');
35
- for (var i=0; i<elementArray.length; i++) {
36
- var elm = elementArray[i];
37
- setElementAttribs(elm);
38
- }
39
- }
40
- } else {
41
- setElementAttribs(elm);
42
- }
43
- tinyMCEPopup.editor.nodeChanged();
44
- tinyMCEPopup.execCommand('mceEndUndoLevel');
45
- tinyMCEPopup.close();
46
- }
47
-
48
- function removeDel() {
49
- SXE.removeElement('del');
50
- tinyMCEPopup.close();
51
- }
52
-
53
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/element_common.js DELETED
@@ -1,229 +0,0 @@
1
- /**
2
- * element_common.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- tinyMCEPopup.requireLangPack();
12
-
13
- function initCommonAttributes(elm) {
14
- var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
15
-
16
- // Setup form data for common element attributes
17
- setFormValue('title', dom.getAttrib(elm, 'title'));
18
- setFormValue('id', dom.getAttrib(elm, 'id'));
19
- selectByValue(formObj, 'class', dom.getAttrib(elm, 'class'), true);
20
- setFormValue('style', dom.getAttrib(elm, 'style'));
21
- selectByValue(formObj, 'dir', dom.getAttrib(elm, 'dir'));
22
- setFormValue('lang', dom.getAttrib(elm, 'lang'));
23
- setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));
24
- setFormValue('onblur', dom.getAttrib(elm, 'onblur'));
25
- setFormValue('onclick', dom.getAttrib(elm, 'onclick'));
26
- setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));
27
- setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));
28
- setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));
29
- setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));
30
- setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));
31
- setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));
32
- setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));
33
- setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));
34
- setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));
35
- }
36
-
37
- function setFormValue(name, value) {
38
- if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value;
39
- }
40
-
41
- function insertDateTime(id) {
42
- document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S");
43
- }
44
-
45
- function getDateTime(d, fmt) {
46
- fmt = fmt.replace("%D", "%m/%d/%y");
47
- fmt = fmt.replace("%r", "%I:%M:%S %p");
48
- fmt = fmt.replace("%Y", "" + d.getFullYear());
49
- fmt = fmt.replace("%y", "" + d.getYear());
50
- fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));
51
- fmt = fmt.replace("%d", addZeros(d.getDate(), 2));
52
- fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));
53
- fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));
54
- fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
55
- fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
56
- fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
57
- fmt = fmt.replace("%%", "%");
58
-
59
- return fmt;
60
- }
61
-
62
- function addZeros(value, len) {
63
- var i;
64
-
65
- value = "" + value;
66
-
67
- if (value.length < len) {
68
- for (i=0; i<(len-value.length); i++)
69
- value = "0" + value;
70
- }
71
-
72
- return value;
73
- }
74
-
75
- function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {
76
- if (!form_obj || !form_obj.elements[field_name])
77
- return;
78
-
79
- var sel = form_obj.elements[field_name];
80
-
81
- var found = false;
82
- for (var i=0; i<sel.options.length; i++) {
83
- var option = sel.options[i];
84
-
85
- if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {
86
- option.selected = true;
87
- found = true;
88
- } else
89
- option.selected = false;
90
- }
91
-
92
- if (!found && add_custom && value != '') {
93
- var option = new Option('Value: ' + value, value);
94
- option.selected = true;
95
- sel.options[sel.options.length] = option;
96
- }
97
-
98
- return found;
99
- }
100
-
101
- function setAttrib(elm, attrib, value) {
102
- var formObj = document.forms[0];
103
- var valueElm = formObj.elements[attrib.toLowerCase()];
104
- tinyMCEPopup.editor.dom.setAttrib(elm, attrib, value || valueElm.value);
105
- }
106
-
107
- function setAllCommonAttribs(elm) {
108
- setAttrib(elm, 'title');
109
- setAttrib(elm, 'id');
110
- setAttrib(elm, 'class');
111
- setAttrib(elm, 'style');
112
- setAttrib(elm, 'dir');
113
- setAttrib(elm, 'lang');
114
- /*setAttrib(elm, 'onfocus');
115
- setAttrib(elm, 'onblur');
116
- setAttrib(elm, 'onclick');
117
- setAttrib(elm, 'ondblclick');
118
- setAttrib(elm, 'onmousedown');
119
- setAttrib(elm, 'onmouseup');
120
- setAttrib(elm, 'onmouseover');
121
- setAttrib(elm, 'onmousemove');
122
- setAttrib(elm, 'onmouseout');
123
- setAttrib(elm, 'onkeypress');
124
- setAttrib(elm, 'onkeydown');
125
- setAttrib(elm, 'onkeyup');*/
126
- }
127
-
128
- SXE = {
129
- currentAction : "insert",
130
- inst : tinyMCEPopup.editor,
131
- updateElement : null
132
- }
133
-
134
- SXE.focusElement = SXE.inst.selection.getNode();
135
-
136
- SXE.initElementDialog = function(element_name) {
137
- addClassesToList('class', 'xhtmlxtras_styles');
138
- TinyMCE_EditableSelects.init();
139
-
140
- element_name = element_name.toLowerCase();
141
- var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());
142
- if (elm != null && elm.nodeName.toUpperCase() == element_name.toUpperCase()) {
143
- SXE.currentAction = "update";
144
- }
145
-
146
- if (SXE.currentAction == "update") {
147
- initCommonAttributes(elm);
148
- SXE.updateElement = elm;
149
- }
150
-
151
- document.forms[0].insert.value = tinyMCEPopup.getLang(SXE.currentAction, 'Insert', true);
152
- }
153
-
154
- SXE.insertElement = function(element_name) {
155
- var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()), h, tagName;
156
-
157
- if (elm == null) {
158
- var s = SXE.inst.selection.getContent();
159
- if(s.length > 0) {
160
- tagName = element_name;
161
-
162
- insertInlineElement(element_name);
163
- var elementArray = tinymce.grep(SXE.inst.dom.select(element_name));
164
- for (var i=0; i<elementArray.length; i++) {
165
- var elm = elementArray[i];
166
-
167
- if (SXE.inst.dom.getAttrib(elm, 'data-mce-new')) {
168
- elm.id = '';
169
- elm.setAttribute('id', '');
170
- elm.removeAttribute('id');
171
- elm.removeAttribute('data-mce-new');
172
-
173
- setAllCommonAttribs(elm);
174
- }
175
- }
176
- }
177
- } else {
178
- setAllCommonAttribs(elm);
179
- }
180
- SXE.inst.nodeChanged();
181
- tinyMCEPopup.execCommand('mceEndUndoLevel');
182
- }
183
-
184
- SXE.removeElement = function(element_name){
185
- element_name = element_name.toLowerCase();
186
- elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());
187
- if(elm && elm.nodeName.toUpperCase() == element_name.toUpperCase()){
188
- tinyMCE.execCommand('mceRemoveNode', false, elm);
189
- SXE.inst.nodeChanged();
190
- tinyMCEPopup.execCommand('mceEndUndoLevel');
191
- }
192
- }
193
-
194
- SXE.showRemoveButton = function() {
195
- document.getElementById("remove").style.display = '';
196
- }
197
-
198
- SXE.containsClass = function(elm,cl) {
199
- return (elm.className.indexOf(cl) > -1) ? true : false;
200
- }
201
-
202
- SXE.removeClass = function(elm,cl) {
203
- if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) {
204
- return true;
205
- }
206
- var classNames = elm.className.split(" ");
207
- var newClassNames = "";
208
- for (var x = 0, cnl = classNames.length; x < cnl; x++) {
209
- if (classNames[x] != cl) {
210
- newClassNames += (classNames[x] + " ");
211
- }
212
- }
213
- elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end
214
- }
215
-
216
- SXE.addClass = function(elm,cl) {
217
- if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl;
218
- return true;
219
- }
220
-
221
- function insertInlineElement(en) {
222
- var ed = tinyMCEPopup.editor, dom = ed.dom;
223
-
224
- ed.getDoc().execCommand('FontName', false, 'mceinline');
225
- tinymce.each(dom.select('span,font'), function(n) {
226
- if (n.style.fontFamily == 'mceinline' || n.face == 'mceinline')
227
- dom.replace(dom.create(en, {'data-mce-new' : 1}), n, 1);
228
- });
229
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/js/ins.js DELETED
@@ -1,53 +0,0 @@
1
- /**
2
- * ins.js
3
- *
4
- * Copyright 2009, Moxiecode Systems AB
5
- * Released under LGPL License.
6
- *
7
- * License: http://tinymce.moxiecode.com/license
8
- * Contributing: http://tinymce.moxiecode.com/contributing
9
- */
10
-
11
- function init() {
12
- SXE.initElementDialog('ins');
13
- if (SXE.currentAction == "update") {
14
- setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));
15
- setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));
16
- SXE.showRemoveButton();
17
- }
18
- }
19
-
20
- function setElementAttribs(elm) {
21
- setAllCommonAttribs(elm);
22
- setAttrib(elm, 'datetime');
23
- setAttrib(elm, 'cite');
24
- elm.removeAttribute('data-mce-new');
25
- }
26
-
27
- function insertIns() {
28
- var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'INS');
29
-
30
- if (elm == null) {
31
- var s = SXE.inst.selection.getContent();
32
- if(s.length > 0) {
33
- insertInlineElement('ins');
34
- var elementArray = SXE.inst.dom.select('ins[data-mce-new]');
35
- for (var i=0; i<elementArray.length; i++) {
36
- var elm = elementArray[i];
37
- setElementAttribs(elm);
38
- }
39
- }
40
- } else {
41
- setElementAttribs(elm);
42
- }
43
- tinyMCEPopup.editor.nodeChanged();
44
- tinyMCEPopup.execCommand('mceEndUndoLevel');
45
- tinyMCEPopup.close();
46
- }
47
-
48
- function removeIns() {
49
- SXE.removeElement('ins');
50
- tinyMCEPopup.close();
51
- }
52
-
53
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js DELETED
@@ -1 +0,0 @@
1
- tinyMCE.addI18n('en.xhtmlxtras_dlg',{"attribs_title":"Insert/Edit Attributes","option_rtl":"Right to Left","option_ltr":"Left to Right","insert_date":"Insert Current Date/Time",remove:"Remove","title_cite_element":"Citation Element","title_abbr_element":"Abbreviation Element","title_acronym_element":"Acronym Element","title_del_element":"Deletion Element","title_ins_element":"Insertion Element","fieldset_events_tab":"Element Events","fieldset_attrib_tab":"Element Attributes","fieldset_general_tab":"General Settings","events_tab":"Events","attrib_tab":"Attributes","general_tab":"General","attribute_attrib_tab":"Attributes","attribute_events_tab":"Events","attribute_label_accesskey":"AccessKey","attribute_label_tabindex":"TabIndex","attribute_label_langcode":"Language","attribute_option_rtl":"Right to Left","attribute_option_ltr":"Left to Right","attribute_label_langdir":"Text Direction","attribute_label_datetime":"Date/Time","attribute_label_cite":"Cite","attribute_label_style":"Style","attribute_label_class":"Class","attribute_label_id":"ID","attribute_label_title":"Title"});
 
tiny_mce/themes/advanced/color_picker.htm CHANGED
@@ -62,12 +62,8 @@
62
 
63
  <div class="mceActionPanel">
64
  <input type="submit" id="insert" name="insert" value="{#apply}" />
65
-
66
- <div id="preview"></div>
67
-
68
- <div id="previewblock">
69
- <label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" class="text mceFocus" aria-required="true" />
70
- </div>
71
  </div>
72
  </form>
73
  </body>
62
 
63
  <div class="mceActionPanel">
64
  <input type="submit" id="insert" name="insert" value="{#apply}" />
65
+ <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();"/>
66
+ <div id="preview_wrapper"><div id="previewblock"><label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" class="text mceFocus" aria-required="true" /></div><span id="preview"></span></div>
 
 
 
 
67
  </div>
68
  </form>
69
  </body>
tiny_mce/themes/advanced/editor_template.js CHANGED
@@ -1 +1 @@
1
- (function(e){var d=e.DOM,b=e.dom.Event,h=e.extend,f=e.each,a=e.util.Cookie,g,c=e.explode;e.ThemeManager.requireLangPack("advanced");e.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(j,k){var l=this,m,i,n;l.editor=j;l.url=k;l.onResolveName=new e.util.Dispatcher(this);j.forcedHighContrastMode=j.settings.detect_highcontrast&&l._isHighContrast();j.settings.skin=j.forcedHighContrastMode?"highcontrast":j.settings.skin;l.settings=m=h({theme_advanced_path:true,theme_advanced_toolbar_location:"bottom",theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:j.settings.readonly},j.settings);if(!m.font_size_style_values){m.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(e.is(m.theme_advanced_font_sizes,"string")){m.font_size_style_values=e.explode(m.font_size_style_values);m.font_size_classes=e.explode(m.font_size_classes||"");n={};j.settings.theme_advanced_font_sizes=m.theme_advanced_font_sizes;f(j.getParam("theme_advanced_font_sizes","","hash"),function(q,p){var o;if(p==q&&q>=1&&q<=7){p=q+" ("+l.sizes[q-1]+"pt)";o=m.font_size_classes[q-1];q=m.font_size_style_values[q-1]||(l.sizes[q-1]+"pt")}if(/^\s*\./.test(q)){o=q.replace(/\./g,"")}n[p]=o?{"class":o}:{fontSize:q}});m.theme_advanced_font_sizes=n}if((i=m.theme_advanced_path_location)&&i!="none"){m.theme_advanced_statusbar_location=m.theme_advanced_path_location}if(m.theme_advanced_statusbar_location=="none"){m.theme_advanced_statusbar_location=0}if(j.settings.content_css!==false){j.contentCSS.push(j.baseURI.toAbsolute(k+"/skins/"+j.settings.skin+"/content.css"))}j.onInit.add(function(){if(!j.settings.readonly){j.onNodeChange.add(l._nodeChanged,l);j.onKeyUp.add(l._updateUndoStatus,l);j.onMouseUp.add(l._updateUndoStatus,l);j.dom.bind(j.dom.getRoot(),"dragend",function(){l._updateUndoStatus(j)})}});j.onSetProgressState.add(function(q,o,r){var s,t=q.id,p;if(o){l.progressTimer=setTimeout(function(){s=q.getContainer();s=s.insertBefore(d.create("DIV",{style:"position:relative"}),s.firstChild);p=d.get(q.id+"_tbl");d.add(s,"div",{id:t+"_blocker","class":"mceBlocker",style:{width:p.clientWidth+2,height:p.clientHeight+2}});d.add(s,"div",{id:t+"_progress","class":"mceProgress",style:{left:p.clientWidth/2,top:p.clientHeight/2}})},r||0)}else{d.remove(t+"_blocker");d.remove(t+"_progress");clearTimeout(l.progressTimer)}});d.loadCSS(m.editor_css?j.documentBaseURI.toAbsolute(m.editor_css):k+"/skins/"+j.settings.skin+"/ui.css");if(m.skin_variant){d.loadCSS(k+"/skins/"+j.settings.skin+"/ui_"+m.skin_variant+".css")}},_isHighContrast:function(){var i,j=d.add(d.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});i=(d.getStyle(j,"background-color",true)+"").toLowerCase().replace(/ /g,"");d.remove(j);return i!="rgb(171,239,86)"&&i!="#abef56"},createControl:function(l,i){var j,k;if(k=i.createControl(l)){return k}switch(l){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((j=this.controls[l])){return i.createButton(l,{title:"advanced."+j[0],cmd:j[1],ui:j[2],value:j[3]})}},execCommand:function(k,j,l){var i=this["_"+k];if(i){i.call(this,j,l);return true}return false},_importClasses:function(k){var i=this.editor,j=i.controlManager.get("styleselect");if(j.getLength()==0){f(i.dom.getClasses(),function(n,l){var m="style_"+l;i.formatter.register(m,{inline:"span",attributes:{"class":n["class"]},selector:"*"});j.add(n["class"],m)})}},_createStyleSelect:function(m){var k=this,i=k.editor,j=i.controlManager,l;l=j.createListBox("styleselect",{title:"advanced.style_select",onselect:function(o){var p,n=[];f(l.items,function(q){n.push(q.value)});i.focus();i.undoManager.add();p=i.formatter.matchAll(n);if(!o||p[0]==o){if(p[0]){i.formatter.remove(p[0])}}else{i.formatter.apply(o)}i.undoManager.add();i.nodeChanged();return false}});i.onInit.add(function(){var o=0,n=i.getParam("style_formats");if(n){f(n,function(p){var q,r=0;f(p,function(){r++});if(r>1){q=p.name=p.name||"style_"+(o++);i.formatter.register(q,p);l.add(p.title,q)}else{l.add(p.title)}})}else{f(i.getParam("theme_advanced_styles","","hash"),function(r,q){var p;if(r){p="style_"+(o++);i.formatter.register(p,{inline:"span",classes:r,selector:"*"});l.add(k.editor.translate(q),p)}})}});if(l.getLength()==0){l.onPostRender.add(function(o,p){if(!l.NativeListBox){b.add(p.id+"_text","focus",k._importClasses,k);b.add(p.id+"_text","mousedown",k._importClasses,k);b.add(p.id+"_open","focus",k._importClasses,k);b.add(p.id+"_open","mousedown",k._importClasses,k)}else{b.add(p.id,"focus",k._importClasses,k)}})}return l},_createFontSelect:function(){var k,j=this,i=j.editor;k=i.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(l){var m=k.items[k.selectedIndex];if(!l&&m){i.execCommand("FontName",false,m.value);return}i.execCommand("FontName",false,l);k.select(function(n){return l==n});if(m&&m.value==l){k.select(null)}return false}});if(k){f(i.getParam("theme_advanced_fonts",j.settings.theme_advanced_fonts,"hash"),function(m,l){k.add(i.translate(l),m,{style:m.indexOf("dings")==-1?"font-family:"+m:""})})}return k},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(i){var o=n.items[n.selectedIndex];if(!i&&o){o=o.value;if(o["class"]){k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}return}if(i["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:i["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,i.fontSize)}n.select(function(p){return i==p});if(o&&(o.value.fontSize==i.fontSize||o.value["class"]==i["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(o,i){var p=o.fontSize;if(p>=1&&p<=7){p=m.sizes[parseInt(p)-1]+"pt"}n.add(i,o,{style:"font-size:"+p,"class":"mceFontSize"+(l++)+(" "+(o["class"]||""))})})}return n},_createBlockFormats:function(){var k,i={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},j=this;k=j.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(l){j.editor.execCommand("FormatBlock",false,l);return false}});if(k){f(j.editor.getParam("theme_advanced_blockformats",j.settings.theme_advanced_blockformats,"hash"),function(m,l){k.add(j.editor.translate(l!=m?l:i[m]),m,{"class":"mce_formatPreview mce_"+m})})}return k},_createForeColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_text_colors){l.colors=i}if(k.theme_advanced_default_foreground_color){l.default_color=k.theme_advanced_default_foreground_color}l.title="advanced.forecolor_desc";l.cmd="ForeColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("forecolor",l);return m},_createBackColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_background_colors){l.colors=i}if(k.theme_advanced_default_background_color){l.default_color=k.theme_advanced_default_background_color}l.title="advanced.backcolor_desc";l.cmd="HiliteColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("backcolor",l);return m},renderUI:function(k){var m,l,q,v=this,r=v.editor,w=v.settings,u,j,i;if(r.settings){r.settings.aria_label=w.aria_label+r.getLang("advanced.help_shortcut")}m=j=d.create("span",{role:"application","aria-labelledby":r.id+"_voice",id:r.id+"_parent","class":"mceEditor "+r.settings.skin+"Skin"+(w.skin_variant?" "+r.settings.skin+"Skin"+v._ufirst(w.skin_variant):"")});d.add(m,"span",{"class":"mceVoiceLabel",style:"display:none;",id:r.id+"_voice"},w.aria_label);if(!d.boxModel){m=d.add(m,"div",{"class":"mceOldBoxModel"})}m=u=d.add(m,"table",{role:"presentation",id:r.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});m=q=d.add(m,"tbody");switch((w.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":l=v._rowLayout(w,q,k);break;case"customlayout":l=r.execCallback("theme_advanced_custom_layout",w,q,k,j);break;default:l=v._simpleLayout(w,q,k,j)}m=k.targetNode;i=u.rows;d.addClass(i[0],"mceFirst");d.addClass(i[i.length-1],"mceLast");f(d.select("tr",q),function(o){d.addClass(o.firstChild,"mceFirst");d.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(d.get(w.theme_advanced_toolbar_container)){d.get(w.theme_advanced_toolbar_container).appendChild(j)}else{d.insertAfter(j,m)}b.add(r.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){v._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return b.cancel(n)}});if(!r.getParam("accessibility_focus")){b.add(d.add(j,"a",{href:"#"},"<!-- IE -->"),"focus",function(){tinyMCE.get(r.id).focus()})}if(w.theme_advanced_toolbar_location=="external"){k.deltaHeight=0}v.deltaHeight=k.deltaHeight;k.targetNode=null;r.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(e.isWebKit){window.focus()}v.toolbarGroup.focus();return b.cancel(n)}else{if(n.keyCode===o){d.get(p.id+"_path_row").focus();return b.cancel(n)}}}});r.addShortcut("alt+0","","mceShortcuts",v);return{iframeContainer:l,editorContainer:r.id+"_parent",sizeContainer:u,deltaHeight:k.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:e.majorVersion+"."+e.minorVersion}},resizeBy:function(i,j){var k=d.get(this.editor.id+"_ifr");this.resizeTo(k.clientWidth+i,k.clientHeight+j)},resizeTo:function(i,m,k){var j=this.editor,l=this.settings,n=d.get(j.id+"_tbl"),o=d.get(j.id+"_ifr");i=Math.max(l.theme_advanced_resizing_min_width||100,i);m=Math.max(l.theme_advanced_resizing_min_height||100,m);i=Math.min(l.theme_advanced_resizing_max_width||65535,i);m=Math.min(l.theme_advanced_resizing_max_height||65535,m);d.setStyle(n,"height","");d.setStyle(o,"height",m);if(l.theme_advanced_resize_horizontal){d.setStyle(n,"width","");d.setStyle(o,"width",i);if(i<n.clientWidth){i=n.clientWidth;d.setStyle(o,"width",n.clientWidth)}}if(k&&l.theme_advanced_resizing_use_cookie){a.setHash("TinyMCE_"+j.id+"_size",{cw:i,ch:m})}},destroy:function(){var i=this.editor.id;b.clear(i+"_resize");b.clear(i+"_path_row");b.clear(i+"_external_close")},_simpleLayout:function(y,r,k,i){var x=this,u=x.editor,v=y.theme_advanced_toolbar_location,m=y.theme_advanced_statusbar_location,l,j,q,w;if(y.readonly){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});return j}if(v=="top"){x._addToolbars(r,k)}if(v=="external"){l=w=d.create("div",{style:"position:relative"});l=d.add(l,"div",{id:u.id+"_external","class":"mceExternalToolbar"});d.add(l,"a",{id:u.id+"_external_close",href:"javascript:;","class":"mceExternalClose"});l=d.add(l,"table",{id:u.id+"_tblext",cellSpacing:0,cellPadding:0});q=d.add(l,"tbody");if(i.firstChild.className=="mceOldBoxModel"){i.firstChild.appendChild(w)}else{i.insertBefore(w,i.firstChild)}x._addToolbars(q,k);u.onMouseUp.add(function(){var o=d.get(u.id+"_external");d.show(o);d.hide(g);var n=b.add(u.id+"_external_close","click",function(){d.hide(u.id+"_external");b.remove(u.id+"_external_close","click",n)});d.show(o);d.setStyle(o,"top",0-d.getRect(u.id+"_tblext").h-1);d.hide(o);d.show(o);o.style.filter="";g=u.id+"_external";o=null})}if(m=="top"){x._addStatusBar(r,k)}if(!y.theme_advanced_toolbar_container){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"})}if(v=="bottom"){x._addToolbars(r,k)}if(m=="bottom"){x._addStatusBar(r,k)}return j},_rowLayout:function(w,m,k){var v=this,p=v.editor,u,x,i=p.controlManager,l,j,r,q;u=w.theme_advanced_containers_default_class||"";x=w.theme_advanced_containers_default_align||"center";f(c(w.theme_advanced_containers||""),function(s,o){var n=w["theme_advanced_container_"+s]||"";switch(s.toLowerCase()){case"mceeditor":l=d.add(m,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});break;case"mceelementpath":v._addStatusBar(m,k);break;default:q=(w["theme_advanced_container_"+s+"_align"]||x).toLowerCase();q="mce"+v._ufirst(q);l=d.add(d.add(m,"tr"),"td",{"class":"mceToolbar "+(w["theme_advanced_container_"+s+"_class"]||u)+" "+q||x});r=i.createToolbar("toolbar"+o);v._addControls(n,r);d.setHTML(l,r.renderHTML());k.deltaHeight-=w.theme_advanced_row_height}});return j},_addControls:function(j,i){var k=this,l=k.settings,m,n=k.editor.controlManager;if(l.theme_advanced_disable&&!k._disabled){m={};f(c(l.theme_advanced_disable),function(o){m[o]=1});k._disabled=m}else{m=k._disabled}f(c(j),function(p){var o;if(m&&m[p]){return}if(p=="tablecontrols"){f(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(q){q=k.createControl(q,n);if(q){i.add(q)}});return}o=k.createControl(p,n);if(o){i.add(o)}})},_addToolbars:function(x,k){var A=this,p,m,r=A.editor,B=A.settings,z,j=r.controlManager,u,l,q=[],y,w;w=j.createToolbarGroup("toolbargroup",{name:r.getLang("advanced.toolbar"),tab_focus_toolbar:r.getParam("theme_advanced_tab_focus_toolbar")});A.toolbarGroup=w;y=B.theme_advanced_toolbar_align.toLowerCase();y="mce"+A._ufirst(y);l=d.add(d.add(x,"tr",{role:"presentation"}),"td",{"class":"mceToolbar "+y,role:"presentation"});for(p=1;(z=B["theme_advanced_buttons"+p]);p++){m=j.createToolbar("toolbar"+p,{"class":"mceToolbarRow"+p});if(B["theme_advanced_buttons"+p+"_add"]){z+=","+B["theme_advanced_buttons"+p+"_add"]}if(B["theme_advanced_buttons"+p+"_add_before"]){z=B["theme_advanced_buttons"+p+"_add_before"]+","+z}A._addControls(z,m);w.add(m);k.deltaHeight-=B.theme_advanced_row_height}q.push(w.renderHTML());q.push(d.createHTML("a",{href:"#",accesskey:"z",title:r.getLang("advanced.toolbar_focus"),onfocus:"tinyMCE.getInstanceById('"+r.id+"').focus();"},"<!-- IE -->"));d.setHTML(l,q.join(""))},_addStatusBar:function(m,j){var k,v=this,p=v.editor,w=v.settings,i,q,u,l;k=d.add(m,"tr");k=l=d.add(k,"td",{"class":"mceStatusbar"});k=d.add(k,"div",{id:p.id+"_path_row",role:"group","aria-labelledby":p.id+"_path_voice"});if(w.theme_advanced_path){d.add(k,"span",{id:p.id+"_path_voice"},p.translate("advanced.path"));d.add(k,"span",{},": ")}else{d.add(k,"span",{},"&#160;")}if(w.theme_advanced_resizing){d.add(l,"a",{id:p.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(w.theme_advanced_resizing_use_cookie){p.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+p.id+"_size"),r=d.get(p.id+"_tbl");if(!n){return}v.resizeTo(n.cw,n.ch)})}p.onPostRender.add(function(){b.add(p.id+"_resize","click",function(n){n.preventDefault()});b.add(p.id+"_resize","mousedown",function(D){var t,r,s,o,C,z,A,F,n,E,x;function y(G){G.preventDefault();n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E)}function B(G){b.remove(d.doc,"mousemove",t);b.remove(p.getDoc(),"mousemove",r);b.remove(d.doc,"mouseup",s);b.remove(p.getDoc(),"mouseup",o);n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E,true)}D.preventDefault();C=D.screenX;z=D.screenY;x=d.get(v.editor.id+"_ifr");A=n=x.clientWidth;F=E=x.clientHeight;t=b.add(d.doc,"mousemove",y);r=b.add(p.getDoc(),"mousemove",y);s=b.add(d.doc,"mouseup",B);o=b.add(p.getDoc(),"mouseup",B)})})}j.deltaHeight-=21;k=m=null},_updateUndoStatus:function(j){var i=j.controlManager,k=j.undoManager;i.setDisabled("undo",!k.hasUndo()&&!k.typing);i.setDisabled("redo",!k.hasRedo())},_nodeChanged:function(m,r,D,q,E){var y=this,C,F=0,x,G,z=y.settings,w,k,u,B,l,j,i;e.each(y.stateControls,function(n){r.setActive(n,m.queryCommandState(y.controls[n][1]))});function o(p){var s,n=E.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s<n.length;s++){if(t(n[s])){return n[s]}}}r.setActive("visualaid",m.hasVisual);y._updateUndoStatus(m);r.setDisabled("outdent",!m.queryCommandState("Outdent"));C=o("A");if(G=r.get("link")){if(!C||!C.name){G.setDisabled(!C&&q);G.setActive(!!C)}}if(G=r.get("unlink")){G.setDisabled(!C&&q);G.setActive(!!C&&!C.name)}if(G=r.get("anchor")){G.setActive(!q&&!!C&&C.name)}C=o("IMG");if(G=r.get("image")){G.setActive(!q&&!!C&&D.className.indexOf("mceItem")==-1)}if(G=r.get("styleselect")){y._importClasses();j=[];f(G.items,function(n){j.push(n.value)});i=m.formatter.matchAll(j);G.select(i[0])}if(G=r.get("formatselect")){C=o(d.isBlock);if(C){G.select(C.nodeName.toLowerCase())}}o(function(p){if(p.nodeName==="SPAN"){if(!w&&p.className){w=p.className}}if(m.dom.is(p,z.theme_advanced_font_selector)){if(!k&&p.style.fontSize){k=p.style.fontSize}if(!u&&p.style.fontFamily){u=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!B&&p.style.color){B=p.style.color}if(!l&&p.style.backgroundColor){l=p.style.backgroundColor}}return false});if(G=r.get("fontselect")){G.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==u})}if(G=r.get("fontsizeselect")){if(z.theme_advanced_runtime_fontsize&&!k&&!w){k=m.dom.getStyle(D,"fontSize",true)}G.select(function(n){if(n.fontSize&&n.fontSize===k){return true}if(n["class"]&&n["class"]===w){return true}})}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_path&&z.theme_advanced_statusbar_location){C=d.get(m.id+"_path")||d.add(m.id+"_path_row","span",{id:m.id+"_path"});if(y.statusKeyboardNavigation){y.statusKeyboardNavigation.destroy();y.statusKeyboardNavigation=null}d.setHTML(C,"");o(function(H){var p=H.nodeName.toLowerCase(),s,v,t="";if(H.nodeType!=1||p==="br"||H.getAttribute("data-mce-bogus")||d.hasClass(H,"mceItemHidden")||d.hasClass(H,"mceItemRemoved")){return}if(e.isIE&&H.scopeName!=="HTML"){p=H.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(x=d.getAttrib(H,"src")){t+="src: "+x+" "}break;case"a":if(x=d.getAttrib(H,"name")){t+="name: "+x+" ";p+="#"+x}if(x=d.getAttrib(H,"href")){t+="href: "+x+" "}break;case"font":if(x=d.getAttrib(H,"face")){t+="font: "+x+" "}if(x=d.getAttrib(H,"size")){t+="size: "+x+" "}if(x=d.getAttrib(H,"color")){t+="color: "+x+" "}break;case"span":if(x=d.getAttrib(H,"style")){t+="style: "+x+" "}break}if(x=d.getAttrib(H,"id")){t+="id: "+x+" "}if(x=H.className){x=x.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(x){t+="class: "+x+" ";if(d.isBlock(H)||p=="img"||p=="span"){p+="."+x}}}p=p.replace(/(html:)/g,"");p={name:p,node:H,title:t};y.onResolveName.dispatch(y,p);t=p.title;p=p.name;v=d.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(F++)},p);if(C.hasChildNodes()){C.insertBefore(d.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),C.firstChild);C.insertBefore(v,C.firstChild)}else{C.appendChild(v)}},m.getBody());if(d.select("a",C).length>0){y.statusKeyboardNavigation=new e.ui.KeyboardNavigation({root:m.id+"_path_row",items:d.select("a",C),excludeFromTabOrder:true,onCancel:function(){m.focus()}},d)}}},_sel:function(i){this.editor.execCommand("mceSelectNodeDepth",false,i)},_mceInsertAnchor:function(k,j){var i=this.editor;i.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(i.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(i.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var i=this.editor;i.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(i.getLang("advanced.charmap_delta_width",0)),height:260+parseInt(i.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var i=this.editor;i.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var i=this.editor;i.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(k,j){var i=this.editor;j=j||{};i.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(i.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(i.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:j.color,func:j.func,theme_url:this.url})},_mceCodeEditor:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(i.getParam("theme_advanced_source_editor_width",720)),height:parseInt(i.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(j,k){var i=this.editor;if(i.dom.getAttrib(i.selection.getNode(),"class").indexOf("mceItem")!=-1){return}i.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(i.getLang("advanced.image_delta_width",0)),height:275+parseInt(i.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(i.getLang("advanced.link_delta_width",0)),height:200+parseInt(i.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var i=this.editor;i.windowManager.confirm("advanced.newdocument",function(j){if(j){i.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var i=this;this._mceColorPicker(0,{color:i.fgColor,func:function(j){i.fgColor=j;i.editor.execCommand("ForeColor",false,j)}})},_mceBackColor:function(){var i=this;this._mceColorPicker(0,{color:i.bgColor,func:function(j){i.bgColor=j;i.editor.execCommand("HiliteColor",false,j)}})},_ufirst:function(i){return i.substring(0,1).toUpperCase()+i.substring(1)}});e.ThemeManager.add("advanced",e.themes.AdvancedTheme)}(tinymce));
1
+ (function(h){var i=h.DOM,g=h.dom.Event,c=h.extend,f=h.each,a=h.util.Cookie,e,d=h.explode;function b(p,m){var k,l,o=p.dom,j="",n,r;previewStyles=p.settings.preview_styles;if(previewStyles===false){return""}if(!previewStyles){previewStyles="font-family font-size font-weight text-decoration text-transform color background-color"}function q(s){return s.replace(/%(\w+)/g,"")}k=m.block||m.inline||"span";l=o.create(k);f(m.styles,function(t,s){t=q(t);if(t){o.setStyle(l,s,t)}});f(m.attributes,function(t,s){t=q(t);if(t){o.setAttrib(l,s,t)}});f(m.classes,function(s){s=q(s);if(!o.hasClass(l,s)){o.addClass(l,s)}});o.setStyles(l,{position:"absolute",left:-65535});p.getBody().appendChild(l);n=o.getStyle(p.getBody(),"fontSize",true);n=/px$/.test(n)?parseInt(n,10):0;f(previewStyles.split(" "),function(s){var t=o.getStyle(l,s,true);if(s=="background-color"&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(t)){t=o.getStyle(p.getBody(),s,true);if(o.toHex(t).toLowerCase()=="#ffffff"){return}}if(s=="font-size"){if(/em|%$/.test(t)){if(n===0){return}t=parseFloat(t,10)/(/%$/.test(t)?100:1);t=(t*n)+"px"}}j+=s+":"+t+";"});o.remove(l);return j}h.ThemeManager.requireLangPack("advanced");h.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(k,l){var m=this,n,j,p;m.editor=k;m.url=l;m.onResolveName=new h.util.Dispatcher(this);n=k.settings;k.forcedHighContrastMode=k.settings.detect_highcontrast&&m._isHighContrast();k.settings.skin=k.forcedHighContrastMode?"highcontrast":k.settings.skin;if(!n.theme_advanced_buttons1){n=c({theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap"},n)}m.settings=n=c({theme_advanced_path:true,theme_advanced_toolbar_location:"top",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"left",theme_advanced_statusbar_location:"bottom",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:k.settings.readonly},n);if(!n.font_size_style_values){n.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(h.is(n.theme_advanced_font_sizes,"string")){n.font_size_style_values=h.explode(n.font_size_style_values);n.font_size_classes=h.explode(n.font_size_classes||"");p={};k.settings.theme_advanced_font_sizes=n.theme_advanced_font_sizes;f(k.getParam("theme_advanced_font_sizes","","hash"),function(r,q){var o;if(q==r&&r>=1&&r<=7){q=r+" ("+m.sizes[r-1]+"pt)";o=n.font_size_classes[r-1];r=n.font_size_style_values[r-1]||(m.sizes[r-1]+"pt")}if(/^\s*\./.test(r)){o=r.replace(/\./g,"")}p[q]=o?{"class":o}:{fontSize:r}});n.theme_advanced_font_sizes=p}if((j=n.theme_advanced_path_location)&&j!="none"){n.theme_advanced_statusbar_location=n.theme_advanced_path_location}if(n.theme_advanced_statusbar_location=="none"){n.theme_advanced_statusbar_location=0}if(k.settings.content_css!==false){k.contentCSS.push(k.baseURI.toAbsolute(l+"/skins/"+k.settings.skin+"/content.css"))}k.onInit.add(function(){if(!k.settings.readonly){k.onNodeChange.add(m._nodeChanged,m);k.onKeyUp.add(m._updateUndoStatus,m);k.onMouseUp.add(m._updateUndoStatus,m);k.dom.bind(k.dom.getRoot(),"dragend",function(){m._updateUndoStatus(k)})}});k.onSetProgressState.add(function(r,o,s){var t,u=r.id,q;if(o){m.progressTimer=setTimeout(function(){t=r.getContainer();t=t.insertBefore(i.create("DIV",{style:"position:relative"}),t.firstChild);q=i.get(r.id+"_tbl");i.add(t,"div",{id:u+"_blocker","class":"mceBlocker",style:{width:q.clientWidth+2,height:q.clientHeight+2}});i.add(t,"div",{id:u+"_progress","class":"mceProgress",style:{left:q.clientWidth/2,top:q.clientHeight/2}})},s||0)}else{i.remove(u+"_blocker");i.remove(u+"_progress");clearTimeout(m.progressTimer)}});i.loadCSS(n.editor_css?k.documentBaseURI.toAbsolute(n.editor_css):l+"/skins/"+k.settings.skin+"/ui.css");if(n.skin_variant){i.loadCSS(l+"/skins/"+k.settings.skin+"/ui_"+n.skin_variant+".css")}},_isHighContrast:function(){var j,k=i.add(i.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});j=(i.getStyle(k,"background-color",true)+"").toLowerCase().replace(/ /g,"");i.remove(k);return j!="rgb(171,239,86)"&&j!="#abef56"},createControl:function(m,j){var k,l;if(l=j.createControl(m)){return l}switch(m){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((k=this.controls[m])){return j.createButton(m,{title:"advanced."+k[0],cmd:k[1],ui:k[2],value:k[3]})}},execCommand:function(l,k,m){var j=this["_"+l];if(j){j.call(this,k,m);return true}return false},_importClasses:function(l){var j=this.editor,k=j.controlManager.get("styleselect");if(k.getLength()==0){f(j.dom.getClasses(),function(q,m){var p="style_"+m,n;n={inline:"span",attributes:{"class":q["class"]},selector:"*"};j.formatter.register(p,n);k.add(q["class"],p,{style:function(){return b(j,n)}})})}},_createStyleSelect:function(o){var l=this,j=l.editor,k=j.controlManager,m;m=k.createListBox("styleselect",{title:"advanced.style_select",onselect:function(q){var r,n=[],p;f(m.items,function(s){n.push(s.value)});j.focus();j.undoManager.add();r=j.formatter.matchAll(n);h.each(r,function(s){if(!q||s==q){if(s){j.formatter.remove(s)}p=true}});if(!p){j.formatter.apply(q)}j.undoManager.add();j.nodeChanged();return false}});j.onPreInit.add(function(){var p=0,n=j.getParam("style_formats");if(n){f(n,function(q){var r,s=0;f(q,function(){s++});if(s>1){r=q.name=q.name||"style_"+(p++);j.formatter.register(r,q);m.add(q.title,r,{style:function(){return b(j,q)}})}else{m.add(q.title)}})}else{f(j.getParam("theme_advanced_styles","","hash"),function(t,s){var r,q;if(t){r="style_"+(p++);q={inline:"span",classes:t,selector:"*"};j.formatter.register(r,q);m.add(l.editor.translate(s),r,{style:function(){return b(j,q)}})}})}});if(m.getLength()==0){m.onPostRender.add(function(p,q){if(!m.NativeListBox){g.add(q.id+"_text","focus",l._importClasses,l);g.add(q.id+"_text","mousedown",l._importClasses,l);g.add(q.id+"_open","focus",l._importClasses,l);g.add(q.id+"_open","mousedown",l._importClasses,l)}else{g.add(q.id,"focus",l._importClasses,l)}})}return m},_createFontSelect:function(){var l,k=this,j=k.editor;l=j.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(m){var n=l.items[l.selectedIndex];if(!m&&n){j.execCommand("FontName",false,n.value);return}j.execCommand("FontName",false,m);l.select(function(o){return m==o});if(n&&n.value==m){l.select(null)}return false}});if(l){f(j.getParam("theme_advanced_fonts",k.settings.theme_advanced_fonts,"hash"),function(n,m){l.add(j.translate(m),n,{style:n.indexOf("dings")==-1?"font-family:"+n:""})})}return l},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(o){var p=n.items[n.selectedIndex];if(!o&&p){p=p.value;if(p["class"]){k.formatter.toggle("fontsize_class",{value:p["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,p.fontSize)}return}if(o["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}n.select(function(q){return o==q});if(p&&(p.value.fontSize==o.fontSize||p.value["class"]&&p.value["class"]==o["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(p,o){var q=p.fontSize;if(q>=1&&q<=7){q=m.sizes[parseInt(q)-1]+"pt"}n.add(o,p,{style:"font-size:"+q,"class":"mceFontSize"+(l++)+(" "+(p["class"]||""))})})}return n},_createBlockFormats:function(){var l,j={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},k=this;l=k.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(m){k.editor.execCommand("FormatBlock",false,m);return false}});if(l){f(k.editor.getParam("theme_advanced_blockformats",k.settings.theme_advanced_blockformats,"hash"),function(n,m){l.add(k.editor.translate(m!=n?m:j[n]),n,{"class":"mce_formatPreview mce_"+n,style:function(){return b(k.editor,{block:n})}})})}return l},_createForeColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_text_colors){m.colors=j}if(l.theme_advanced_default_foreground_color){m.default_color=l.theme_advanced_default_foreground_color}m.title="advanced.forecolor_desc";m.cmd="ForeColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("forecolor",m);return n},_createBackColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_background_colors){m.colors=j}if(l.theme_advanced_default_background_color){m.default_color=l.theme_advanced_default_background_color}m.title="advanced.backcolor_desc";m.cmd="HiliteColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("backcolor",m);return n},renderUI:function(l){var q,m,r,w=this,u=w.editor,x=w.settings,v,k,j;if(u.settings){u.settings.aria_label=x.aria_label+u.getLang("advanced.help_shortcut")}q=k=i.create("span",{role:"application","aria-labelledby":u.id+"_voice",id:u.id+"_parent","class":"mceEditor "+u.settings.skin+"Skin"+(x.skin_variant?" "+u.settings.skin+"Skin"+w._ufirst(x.skin_variant):"")+(u.settings.directionality=="rtl"?" mceRtl":"")});i.add(q,"span",{"class":"mceVoiceLabel",style:"display:none;",id:u.id+"_voice"},x.aria_label);if(!i.boxModel){q=i.add(q,"div",{"class":"mceOldBoxModel"})}q=v=i.add(q,"table",{role:"presentation",id:u.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});q=r=i.add(q,"tbody");switch((x.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":m=w._rowLayout(x,r,l);break;case"customlayout":m=u.execCallback("theme_advanced_custom_layout",x,r,l,k);break;default:m=w._simpleLayout(x,r,l,k)}q=l.targetNode;j=v.rows;i.addClass(j[0],"mceFirst");i.addClass(j[j.length-1],"mceLast");f(i.select("tr",r),function(o){i.addClass(o.firstChild,"mceFirst");i.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(i.get(x.theme_advanced_toolbar_container)){i.get(x.theme_advanced_toolbar_container).appendChild(k)}else{i.insertAfter(k,q)}g.add(u.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){w._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return false}});if(!u.getParam("accessibility_focus")){g.add(i.add(k,"a",{href:"#"},"<!-- IE -->"),"focus",function(){tinyMCE.get(u.id).focus()})}if(x.theme_advanced_toolbar_location=="external"){l.deltaHeight=0}w.deltaHeight=l.deltaHeight;l.targetNode=null;u.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(h.isWebKit){window.focus()}w.toolbarGroup.focus();return g.cancel(n)}else{if(n.keyCode===o){i.get(p.id+"_path_row").focus();return g.cancel(n)}}}});u.addShortcut("alt+0","","mceShortcuts",w);return{iframeContainer:m,editorContainer:u.id+"_parent",sizeContainer:v,deltaHeight:l.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:h.majorVersion+"."+h.minorVersion}},resizeBy:function(j,k){var l=i.get(this.editor.id+"_ifr");this.resizeTo(l.clientWidth+j,l.clientHeight+k)},resizeTo:function(j,n,l){var k=this.editor,m=this.settings,o=i.get(k.id+"_tbl"),p=i.get(k.id+"_ifr");j=Math.max(m.theme_advanced_resizing_min_width||100,j);n=Math.max(m.theme_advanced_resizing_min_height||100,n);j=Math.min(m.theme_advanced_resizing_max_width||65535,j);n=Math.min(m.theme_advanced_resizing_max_height||65535,n);i.setStyle(o,"height","");i.setStyle(p,"height",n);if(m.theme_advanced_resize_horizontal){i.setStyle(o,"width","");i.setStyle(p,"width",j);if(j<o.clientWidth){j=o.clientWidth;i.setStyle(p,"width",o.clientWidth)}}if(l&&m.theme_advanced_resizing_use_cookie){a.setHash("TinyMCE_"+k.id+"_size",{cw:j,ch:n})}},destroy:function(){var j=this.editor.id;g.clear(j+"_resize");g.clear(j+"_path_row");g.clear(j+"_external_close")},_simpleLayout:function(z,u,l,j){var y=this,v=y.editor,w=z.theme_advanced_toolbar_location,q=z.theme_advanced_statusbar_location,m,k,r,x;if(z.readonly){m=i.add(u,"tr");m=k=i.add(m,"td",{"class":"mceIframeContainer"});return k}if(w=="top"){y._addToolbars(u,l)}if(w=="external"){m=x=i.create("div",{style:"position:relative"});m=i.add(m,"div",{id:v.id+"_external","class":"mceExternalToolbar"});i.add(m,"a",{id:v.id+"_external_close",href:"javascript:;","class":"mceExternalClose"});m=i.add(m,"table",{id:v.id+"_tblext",cellSpacing:0,cellPadding:0});r=i.add(m,"tbody");if(j.firstChild.className=="mceOldBoxModel"){j.firstChild.appendChild(x)}else{j.insertBefore(x,j.firstChild)}y._addToolbars(r,l);v.onMouseUp.add(function(){var o=i.get(v.id+"_external");i.show(o);i.hide(e);var n=g.add(v.id+"_external_close","click",function(){i.hide(v.id+"_external");g.remove(v.id+"_external_close","click",n);return false});i.show(o);i.setStyle(o,"top",0-i.getRect(v.id+"_tblext").h-1);i.hide(o);i.show(o);o.style.filter="";e=v.id+"_external";o=null})}if(q=="top"){y._addStatusBar(u,l)}if(!z.theme_advanced_toolbar_container){m=i.add(u,"tr");m=k=i.add(m,"td",{"class":"mceIframeContainer"})}if(w=="bottom"){y._addToolbars(u,l)}if(q=="bottom"){y._addStatusBar(u,l)}return k},_rowLayout:function(x,p,l){var w=this,q=w.editor,v,y,j=q.controlManager,m,k,u,r;v=x.theme_advanced_containers_default_class||"";y=x.theme_advanced_containers_default_align||"center";f(d(x.theme_advanced_containers||""),function(s,o){var n=x["theme_advanced_container_"+s]||"";switch(s.toLowerCase()){case"mceeditor":m=i.add(p,"tr");m=k=i.add(m,"td",{"class":"mceIframeContainer"});break;case"mceelementpath":w._addStatusBar(p,l);break;default:r=(x["theme_advanced_container_"+s+"_align"]||y).toLowerCase();r="mce"+w._ufirst(r);m=i.add(i.add(p,"tr"),"td",{"class":"mceToolbar "+(x["theme_advanced_container_"+s+"_class"]||v)+" "+r||y});u=j.createToolbar("toolbar"+o);w._addControls(n,u);i.setHTML(m,u.renderHTML());l.deltaHeight-=x.theme_advanced_row_height}});return k},_addControls:function(k,j){var l=this,m=l.settings,n,o=l.editor.controlManager;if(m.theme_advanced_disable&&!l._disabled){n={};f(d(m.theme_advanced_disable),function(p){n[p]=1});l._disabled=n}else{n=l._disabled}f(d(k),function(q){var p;if(n&&n[q]){return}if(q=="tablecontrols"){f(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(r){r=l.createControl(r,o);if(r){j.add(r)}});return}p=l.createControl(q,o);if(p){j.add(p)}})},_addToolbars:function(y,k){var B=this,q,p,u=B.editor,C=B.settings,A,j=u.controlManager,w,l,r=[],z,x,m=false;x=j.createToolbarGroup("toolbargroup",{name:u.getLang("advanced.toolbar"),tab_focus_toolbar:u.getParam("theme_advanced_tab_focus_toolbar")});B.toolbarGroup=x;z=C.theme_advanced_toolbar_align.toLowerCase();z="mce"+B._ufirst(z);l=i.add(i.add(y,"tr",{role:"toolbar"}),"td",{"class":"mceToolbar "+z,role:"toolbar"});for(q=1;(A=C["theme_advanced_buttons"+q]);q++){m=true;p=j.createToolbar("toolbar"+q,{"class":"mceToolbarRow"+q});if(C["theme_advanced_buttons"+q+"_add"]){A+=","+C["theme_advanced_buttons"+q+"_add"]}if(C["theme_advanced_buttons"+q+"_add_before"]){A=C["theme_advanced_buttons"+q+"_add_before"]+","+A}B._addControls(A,p);x.add(p);k.deltaHeight-=C.theme_advanced_row_height}if(!m){k.deltaHeight-=C.theme_advanced_row_height}r.push(x.renderHTML());r.push(i.createHTML("a",{href:"#",accesskey:"z",title:u.getLang("advanced.toolbar_focus"),onfocus:"tinyMCE.getInstanceById('"+u.id+"').focus();"},"<!-- IE -->"));i.setHTML(l,r.join(""))},_addStatusBar:function(p,k){var l,w=this,q=w.editor,x=w.settings,j,u,v,m;l=i.add(p,"tr");l=m=i.add(l,"td",{"class":"mceStatusbar"});l=i.add(l,"div",{id:q.id+"_path_row",role:"group","aria-labelledby":q.id+"_path_voice"});if(x.theme_advanced_path){i.add(l,"span",{id:q.id+"_path_voice"},q.translate("advanced.path"));i.add(l,"span",{},": ")}else{i.add(l,"span",{},"&#160;")}if(x.theme_advanced_resizing){i.add(m,"a",{id:q.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(x.theme_advanced_resizing_use_cookie){q.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+q.id+"_size"),r=i.get(q.id+"_tbl");if(!n){return}w.resizeTo(n.cw,n.ch)})}q.onPostRender.add(function(){g.add(q.id+"_resize","click",function(n){n.preventDefault()});g.add(q.id+"_resize","mousedown",function(E){var t,r,s,o,D,A,B,G,n,F,y;function z(H){H.preventDefault();n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F)}function C(H){g.remove(i.doc,"mousemove",t);g.remove(q.getDoc(),"mousemove",r);g.remove(i.doc,"mouseup",s);g.remove(q.getDoc(),"mouseup",o);n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F,true);q.nodeChanged()}E.preventDefault();D=E.screenX;A=E.screenY;y=i.get(w.editor.id+"_ifr");B=n=y.clientWidth;G=F=y.clientHeight;t=g.add(i.doc,"mousemove",z);r=g.add(q.getDoc(),"mousemove",z);s=g.add(i.doc,"mouseup",C);o=g.add(q.getDoc(),"mouseup",C)})})}k.deltaHeight-=21;l=p=null},_updateUndoStatus:function(k){var j=k.controlManager,l=k.undoManager;j.setDisabled("undo",!l.hasUndo()&&!l.typing);j.setDisabled("redo",!l.hasRedo())},_nodeChanged:function(o,u,E,r,F){var z=this,D,G=0,y,H,A=z.settings,x,l,w,C,m,k,j;h.each(z.stateControls,function(n){u.setActive(n,o.queryCommandState(z.controls[n][1]))});function q(p){var s,n=F.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s<n.length;s++){if(t(n[s])){return n[s]}}}u.setActive("visualaid",o.hasVisual);z._updateUndoStatus(o);u.setDisabled("outdent",!o.queryCommandState("Outdent"));D=q("A");if(H=u.get("link")){H.setDisabled((!D&&r)||(D&&!D.href));H.setActive(!!D&&(!D.name&&!D.id))}if(H=u.get("unlink")){H.setDisabled(!D&&r);H.setActive(!!D&&!D.name&&!D.id)}if(H=u.get("anchor")){H.setActive(!r&&!!D&&(D.name||(D.id&&!D.href)))}D=q("IMG");if(H=u.get("image")){H.setActive(!r&&!!D&&E.className.indexOf("mceItem")==-1)}if(H=u.get("styleselect")){z._importClasses();k=[];f(H.items,function(n){k.push(n.value)});j=o.formatter.matchAll(k);H.select(j[0]);h.each(j,function(p,n){if(n>0){H.mark(p)}})}if(H=u.get("formatselect")){D=q(o.dom.isBlock);if(D){H.select(D.nodeName.toLowerCase())}}q(function(p){if(p.nodeName==="SPAN"){if(!x&&p.className){x=p.className}}if(o.dom.is(p,A.theme_advanced_font_selector)){if(!l&&p.style.fontSize){l=p.style.fontSize}if(!w&&p.style.fontFamily){w=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!C&&p.style.color){C=p.style.color}if(!m&&p.style.backgroundColor){m=p.style.backgroundColor}}return false});if(H=u.get("fontselect")){H.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==w})}if(H=u.get("fontsizeselect")){if(A.theme_advanced_runtime_fontsize&&!l&&!x){l=o.dom.getStyle(E,"fontSize",true)}H.select(function(n){if(n.fontSize&&n.fontSize===l){return true}if(n["class"]&&n["class"]===x){return true}})}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_path&&A.theme_advanced_statusbar_location){D=i.get(o.id+"_path")||i.add(o.id+"_path_row","span",{id:o.id+"_path"});if(z.statusKeyboardNavigation){z.statusKeyboardNavigation.destroy();z.statusKeyboardNavigation=null}i.setHTML(D,"");q(function(I){var p=I.nodeName.toLowerCase(),s,v,t="";if(I.nodeType!=1||p==="br"||I.getAttribute("data-mce-bogus")||i.hasClass(I,"mceItemHidden")||i.hasClass(I,"mceItemRemoved")){return}if(h.isIE&&I.scopeName!=="HTML"&&I.scopeName){p=I.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(y=i.getAttrib(I,"src")){t+="src: "+y+" "}break;case"a":if(y=i.getAttrib(I,"name")){t+="name: "+y+" ";p+="#"+y}if(y=i.getAttrib(I,"href")){t+="href: "+y+" "}break;case"font":if(y=i.getAttrib(I,"face")){t+="font: "+y+" "}if(y=i.getAttrib(I,"size")){t+="size: "+y+" "}if(y=i.getAttrib(I,"color")){t+="color: "+y+" "}break;case"span":if(y=i.getAttrib(I,"style")){t+="style: "+y+" "}break}if(y=i.getAttrib(I,"id")){t+="id: "+y+" "}if(y=I.className){y=y.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(y){t+="class: "+y+" ";if(o.dom.isBlock(I)||p=="img"||p=="span"){p+="."+y}}}p=p.replace(/(html:)/g,"");p={name:p,node:I,title:t};z.onResolveName.dispatch(z,p);t=p.title;p=p.name;v=i.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(G++)},p);if(D.hasChildNodes()){D.insertBefore(i.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),D.firstChild);D.insertBefore(v,D.firstChild)}else{D.appendChild(v)}},o.getBody());if(i.select("a",D).length>0){z.statusKeyboardNavigation=new h.ui.KeyboardNavigation({root:o.id+"_path_row",items:i.select("a",D),excludeFromTabOrder:true,onCancel:function(){o.focus()}},i)}}},_sel:function(j){this.editor.execCommand("mceSelectNodeDepth",false,j)},_mceInsertAnchor:function(l,k){var j=this.editor;j.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(j.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(j.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var j=this.editor;j.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(j.getLang("advanced.charmap_delta_width",0)),height:265+parseInt(j.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var j=this.editor;j.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var j=this.editor;j.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(l,k){var j=this.editor;k=k||{};j.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(j.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(j.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:k.color,func:k.func,theme_url:this.url})},_mceCodeEditor:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(j.getParam("theme_advanced_source_editor_width",720)),height:parseInt(j.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(k,l){var j=this.editor;if(j.dom.getAttrib(j.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}j.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(j.getLang("advanced.image_delta_width",0)),height:275+parseInt(j.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(j.getLang("advanced.link_delta_width",0)),height:200+parseInt(j.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var j=this.editor;j.windowManager.confirm("advanced.newdocument",function(k){if(k){j.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var j=this;this._mceColorPicker(0,{color:j.fgColor,func:function(k){j.fgColor=k;j.editor.execCommand("ForeColor",false,k)}})},_mceBackColor:function(){var j=this;this._mceColorPicker(0,{color:j.bgColor,func:function(k){j.bgColor=k;j.editor.execCommand("HiliteColor",false,k)}})},_ufirst:function(j){return j.substring(0,1).toUpperCase()+j.substring(1)}});h.ThemeManager.add("advanced",h.themes.AdvancedTheme)}(tinymce));
tiny_mce/themes/advanced/editor_template_src.js CHANGED
@@ -11,6 +11,95 @@
11
  (function(tinymce) {
12
  var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode;
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  // Tell it to load theme specific language pack(s)
15
  tinymce.ThemeManager.requireLangPack('advanced');
16
 
@@ -61,23 +150,31 @@
61
 
62
  init : function(ed, url) {
63
  var t = this, s, v, o;
64
-
65
  t.editor = ed;
66
  t.url = url;
67
  t.onResolveName = new tinymce.util.Dispatcher(this);
 
68
 
69
  ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast();
70
  ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin;
71
 
 
 
 
 
 
 
 
 
 
72
  // Default settings
73
  t.settings = s = extend({
74
  theme_advanced_path : true,
75
- theme_advanced_toolbar_location : 'bottom',
76
- theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",
77
- theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",
78
- theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap",
79
  theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",
80
- theme_advanced_toolbar_align : "center",
 
81
  theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",
82
  theme_advanced_more_colors : 1,
83
  theme_advanced_row_height : 23,
@@ -87,7 +184,7 @@
87
  theme_advanced_font_selector : "span",
88
  theme_advanced_show_current_color: 0,
89
  readonly : ed.settings.readonly
90
- }, ed.settings);
91
 
92
  // Setup default font_size_style_values
93
  if (!s.font_size_style_values)
@@ -219,15 +316,21 @@
219
 
220
  if (ctrl.getLength() == 0) {
221
  each(ed.dom.getClasses(), function(o, idx) {
222
- var name = 'style_' + idx;
223
 
224
- ed.formatter.register(name, {
225
  inline : 'span',
226
  attributes : {'class' : o['class']},
227
  selector : '*'
228
- });
 
 
229
 
230
- ctrl.add(o['class'], name);
 
 
 
 
231
  });
232
  }
233
  },
@@ -239,7 +342,7 @@
239
  ctrl = ctrlMan.createListBox('styleselect', {
240
  title : 'advanced.style_select',
241
  onselect : function(name) {
242
- var matches, formatNames = [];
243
 
244
  each(ctrl.items, function(item) {
245
  formatNames.push(item.value);
@@ -248,12 +351,18 @@
248
  ed.focus();
249
  ed.undoManager.add();
250
 
251
- // Toggle off the current format
252
  matches = ed.formatter.matchAll(formatNames);
253
- if (!name || matches[0] == name) {
254
- if (matches[0])
255
- ed.formatter.remove(matches[0]);
256
- } else
 
 
 
 
 
 
257
  ed.formatter.apply(name);
258
 
259
  ed.undoManager.add();
@@ -264,7 +373,7 @@
264
  });
265
 
266
  // Handle specified format
267
- ed.onInit.add(function() {
268
  var counter = 0, formats = ed.getParam('style_formats');
269
 
270
  if (formats) {
@@ -276,24 +385,32 @@
276
  if (keys > 1) {
277
  name = fmt.name = fmt.name || 'style_' + (counter++);
278
  ed.formatter.register(name, fmt);
279
- ctrl.add(fmt.title, name);
 
 
 
 
280
  } else
281
  ctrl.add(fmt.title);
282
  });
283
  } else {
284
  each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) {
285
- var name;
286
 
287
  if (val) {
288
  name = 'style_' + (counter++);
289
-
290
- ed.formatter.register(name, {
291
  inline : 'span',
292
  classes : val,
293
  selector : '*'
294
- });
295
 
296
- ctrl.add(t.editor.translate(key), name);
 
 
 
 
 
297
  }
298
  });
299
  }
@@ -386,7 +503,7 @@
386
  return v == sv;
387
  });
388
 
389
- if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] == v['class'])) {
390
  c.select(null);
391
  }
392
 
@@ -433,7 +550,9 @@
433
 
434
  if (c) {
435
  each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) {
436
- c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v});
 
 
437
  });
438
  }
439
 
@@ -507,7 +626,7 @@
507
 
508
  // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for.
509
  // Maybe actually inherit it from the original textara?
510
- n = p = DOM.create('span', {role : 'application', 'aria-labelledby' : ed.id + '_voice', id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '')});
511
  DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label);
512
 
513
  if (!DOM.boxModel)
@@ -552,15 +671,14 @@
552
 
553
  if (e.nodeName == 'A') {
554
  t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1'));
555
-
556
- return Event.cancel(e);
557
  }
558
  });
559
  /*
560
  if (DOM.get(ed.id + '_path_row')) {
561
  Event.add(ed.id + '_tbl', 'mouseover', function(e) {
562
  var re;
563
-
564
  e = e.target;
565
 
566
  if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {
@@ -713,6 +831,7 @@
713
  var f = Event.add(ed.id + '_external_close', 'click', function() {
714
  DOM.hide(ed.id + '_external');
715
  Event.remove(ed.id + '_external_close', 'click', f);
 
716
  });
717
 
718
  DOM.show(e);
@@ -825,7 +944,7 @@
825
  },
826
 
827
  _addToolbars : function(c, o) {
828
- var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup;
829
 
830
  toolbarGroup = cf.createToolbarGroup('toolbargroup', {
831
  'name': ed.getLang('advanced.toolbar'),
@@ -837,10 +956,11 @@
837
  a = s.theme_advanced_toolbar_align.toLowerCase();
838
  a = 'mce' + t._ufirst(a);
839
 
840
- n = DOM.add(DOM.add(c, 'tr', {role: 'presentation'}), 'td', {'class' : 'mceToolbar ' + a, "role":"presentation"});
841
 
842
  // Create toolbar and add the controls
843
  for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {
 
844
  tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});
845
 
846
  if (s['theme_advanced_buttons' + i + '_add'])
@@ -854,6 +974,9 @@
854
 
855
  o.deltaHeight -= s.theme_advanced_row_height;
856
  }
 
 
 
857
  h.push(toolbarGroup.renderHTML());
858
  h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
859
  DOM.setHTML(n, h.join(''));
@@ -863,7 +986,7 @@
863
  var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;
864
 
865
  n = DOM.add(tb, 'tr');
866
- n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});
867
  n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'});
868
  if (s.theme_advanced_path) {
869
  DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path'));
@@ -871,7 +994,7 @@
871
  } else {
872
  DOM.add(n, 'span', {}, '&#160;');
873
  }
874
-
875
 
876
  if (s.theme_advanced_resizing) {
877
  DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"});
@@ -916,6 +1039,8 @@
916
  width = startWidth + (e.screenX - startX);
917
  height = startHeight + (e.screenY - startY);
918
  t.resizeTo(width, height, true);
 
 
919
  };
920
 
921
  e.preventDefault();
@@ -975,19 +1100,17 @@
975
 
976
  p = getParent('A');
977
  if (c = cm.get('link')) {
978
- if (!p || !p.name) {
979
- c.setDisabled(!p && co);
980
- c.setActive(!!p);
981
- }
982
  }
983
 
984
  if (c = cm.get('unlink')) {
985
  c.setDisabled(!p && co);
986
- c.setActive(!!p && !p.name);
987
  }
988
 
989
  if (c = cm.get('anchor')) {
990
- c.setActive(!co && !!p && p.name);
991
  }
992
 
993
  p = getParent('IMG');
@@ -1004,10 +1127,15 @@
1004
 
1005
  matches = ed.formatter.matchAll(formatNames);
1006
  c.select(matches[0]);
 
 
 
 
 
1007
  }
1008
 
1009
  if (c = cm.get('formatselect')) {
1010
- p = getParent(DOM.isBlock);
1011
 
1012
  if (p)
1013
  c.select(p.nodeName.toLowerCase());
@@ -1026,7 +1154,7 @@
1026
 
1027
  if (!fn && n.style.fontFamily)
1028
  fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase();
1029
-
1030
  if (!fc && n.style.color)
1031
  fc = n.style.color;
1032
 
@@ -1057,7 +1185,7 @@
1057
  return true;
1058
  });
1059
  }
1060
-
1061
  if (s.theme_advanced_show_current_color) {
1062
  function updateColor(controlId, color) {
1063
  if (c = cm.get(controlId)) {
@@ -1105,7 +1233,7 @@
1105
  return;
1106
 
1107
  // Handle prefix
1108
- if (tinymce.isIE && n.scopeName !== 'HTML')
1109
  na = n.scopeName + ':' + na;
1110
 
1111
  // Remove internal prefix
@@ -1161,12 +1289,12 @@
1161
  ti += 'id: ' + v + ' ';
1162
 
1163
  if (v = n.className) {
1164
- v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '')
1165
 
1166
  if (v) {
1167
  ti += 'class: ' + v + ' ';
1168
 
1169
- if (DOM.isBlock(n) || na == 'img' || na == 'span')
1170
  na += '.' + v;
1171
  }
1172
  }
@@ -1225,7 +1353,7 @@
1225
  ed.windowManager.open({
1226
  url : this.url + '/charmap.htm',
1227
  width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),
1228
- height : 260 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),
1229
  inline : true
1230
  }, {
1231
  theme_url : this.url
@@ -1294,7 +1422,7 @@
1294
  var ed = this.editor;
1295
 
1296
  // Internal image object like a flash placeholder
1297
- if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1)
1298
  return;
1299
 
1300
  ed.windowManager.open({
11
  (function(tinymce) {
12
  var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode;
13
 
14
+ // Generates a preview for a format
15
+ function getPreviewCss(ed, fmt) {
16
+ var name, previewElm, dom = ed.dom, previewCss = '', parentFontSize, previewStylesName;
17
+
18
+ previewStyles = ed.settings.preview_styles;
19
+
20
+ // No preview forced
21
+ if (previewStyles === false)
22
+ return '';
23
+
24
+ // Default preview
25
+ if (!previewStyles)
26
+ previewStyles = 'font-family font-size font-weight text-decoration text-transform color background-color';
27
+
28
+ // Removes any variables since these can't be previewed
29
+ function removeVars(val) {
30
+ return val.replace(/%(\w+)/g, '');
31
+ };
32
+
33
+ // Create block/inline element to use for preview
34
+ name = fmt.block || fmt.inline || 'span';
35
+ previewElm = dom.create(name);
36
+
37
+ // Add format styles to preview element
38
+ each(fmt.styles, function(value, name) {
39
+ value = removeVars(value);
40
+
41
+ if (value)
42
+ dom.setStyle(previewElm, name, value);
43
+ });
44
+
45
+ // Add attributes to preview element
46
+ each(fmt.attributes, function(value, name) {
47
+ value = removeVars(value);
48
+
49
+ if (value)
50
+ dom.setAttrib(previewElm, name, value);
51
+ });
52
+
53
+ // Add classes to preview element
54
+ each(fmt.classes, function(value) {
55
+ value = removeVars(value);
56
+
57
+ if (!dom.hasClass(previewElm, value))
58
+ dom.addClass(previewElm, value);
59
+ });
60
+
61
+ // Add the previewElm outside the visual area
62
+ dom.setStyles(previewElm, {position: 'absolute', left: -0xFFFF});
63
+ ed.getBody().appendChild(previewElm);
64
+
65
+ // Get parent container font size so we can compute px values out of em/% for older IE:s
66
+ parentFontSize = dom.getStyle(ed.getBody(), 'fontSize', true);
67
+ parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
68
+
69
+ each(previewStyles.split(' '), function(name) {
70
+ var value = dom.getStyle(previewElm, name, true);
71
+
72
+ // If background is transparent then check if the body has a background color we can use
73
+ if (name == 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
74
+ value = dom.getStyle(ed.getBody(), name, true);
75
+
76
+ // Ignore white since it's the default color, not the nicest fix
77
+ if (dom.toHex(value).toLowerCase() == '#ffffff') {
78
+ return;
79
+ }
80
+ }
81
+
82
+ // Old IE won't calculate the font size so we need to do that manually
83
+ if (name == 'font-size') {
84
+ if (/em|%$/.test(value)) {
85
+ if (parentFontSize === 0) {
86
+ return;
87
+ }
88
+
89
+ // Convert font size from em/% to px
90
+ value = parseFloat(value, 10) / (/%$/.test(value) ? 100 : 1);
91
+ value = (value * parentFontSize) + 'px';
92
+ }
93
+ }
94
+
95
+ previewCss += name + ':' + value + ';';
96
+ });
97
+
98
+ dom.remove(previewElm);
99
+
100
+ return previewCss;
101
+ };
102
+
103
  // Tell it to load theme specific language pack(s)
104
  tinymce.ThemeManager.requireLangPack('advanced');
105
 
150
 
151
  init : function(ed, url) {
152
  var t = this, s, v, o;
153
+
154
  t.editor = ed;
155
  t.url = url;
156
  t.onResolveName = new tinymce.util.Dispatcher(this);
157
+ s = ed.settings;
158
 
159
  ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast();
160
  ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin;
161
 
162
+ // Setup default buttons
163
+ if (!s.theme_advanced_buttons1) {
164
+ s = extend({
165
+ theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",
166
+ theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",
167
+ theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap"
168
+ }, s);
169
+ }
170
+
171
  // Default settings
172
  t.settings = s = extend({
173
  theme_advanced_path : true,
174
+ theme_advanced_toolbar_location : 'top',
 
 
 
175
  theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",
176
+ theme_advanced_toolbar_align : "left",
177
+ theme_advanced_statusbar_location : "bottom",
178
  theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",
179
  theme_advanced_more_colors : 1,
180
  theme_advanced_row_height : 23,
184
  theme_advanced_font_selector : "span",
185
  theme_advanced_show_current_color: 0,
186
  readonly : ed.settings.readonly
187
+ }, s);
188
 
189
  // Setup default font_size_style_values
190
  if (!s.font_size_style_values)
316
 
317
  if (ctrl.getLength() == 0) {
318
  each(ed.dom.getClasses(), function(o, idx) {
319
+ var name = 'style_' + idx, fmt;
320
 
321
+ fmt = {
322
  inline : 'span',
323
  attributes : {'class' : o['class']},
324
  selector : '*'
325
+ };
326
+
327
+ ed.formatter.register(name, fmt);
328
 
329
+ ctrl.add(o['class'], name, {
330
+ style: function() {
331
+ return getPreviewCss(ed, fmt);
332
+ }
333
+ });
334
  });
335
  }
336
  },
342
  ctrl = ctrlMan.createListBox('styleselect', {
343
  title : 'advanced.style_select',
344
  onselect : function(name) {
345
+ var matches, formatNames = [], removedFormat;
346
 
347
  each(ctrl.items, function(item) {
348
  formatNames.push(item.value);
351
  ed.focus();
352
  ed.undoManager.add();
353
 
354
+ // Toggle off the current format(s)
355
  matches = ed.formatter.matchAll(formatNames);
356
+ tinymce.each(matches, function(match) {
357
+ if (!name || match == name) {
358
+ if (match)
359
+ ed.formatter.remove(match);
360
+
361
+ removedFormat = true;
362
+ }
363
+ });
364
+
365
+ if (!removedFormat)
366
  ed.formatter.apply(name);
367
 
368
  ed.undoManager.add();
373
  });
374
 
375
  // Handle specified format
376
+ ed.onPreInit.add(function() {
377
  var counter = 0, formats = ed.getParam('style_formats');
378
 
379
  if (formats) {
385
  if (keys > 1) {
386
  name = fmt.name = fmt.name || 'style_' + (counter++);
387
  ed.formatter.register(name, fmt);
388
+ ctrl.add(fmt.title, name, {
389
+ style: function() {
390
+ return getPreviewCss(ed, fmt);
391
+ }
392
+ });
393
  } else
394
  ctrl.add(fmt.title);
395
  });
396
  } else {
397
  each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) {
398
+ var name, fmt;
399
 
400
  if (val) {
401
  name = 'style_' + (counter++);
402
+ fmt = {
 
403
  inline : 'span',
404
  classes : val,
405
  selector : '*'
406
+ };
407
 
408
+ ed.formatter.register(name, fmt);
409
+ ctrl.add(t.editor.translate(key), name, {
410
+ style: function() {
411
+ return getPreviewCss(ed, fmt);
412
+ }
413
+ });
414
  }
415
  });
416
  }
503
  return v == sv;
504
  });
505
 
506
+ if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] && cur.value['class'] == v['class'])) {
507
  c.select(null);
508
  }
509
 
550
 
551
  if (c) {
552
  each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) {
553
+ c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v, style: function() {
554
+ return getPreviewCss(t.editor, {block: v});
555
+ }});
556
  });
557
  }
558
 
626
 
627
  // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for.
628
  // Maybe actually inherit it from the original textara?
629
+ n = p = DOM.create('span', {role : 'application', 'aria-labelledby' : ed.id + '_voice', id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '') + (ed.settings.directionality == "rtl" ? ' mceRtl' : '')});
630
  DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label);
631
 
632
  if (!DOM.boxModel)
671
 
672
  if (e.nodeName == 'A') {
673
  t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1'));
674
+ return false;
 
675
  }
676
  });
677
  /*
678
  if (DOM.get(ed.id + '_path_row')) {
679
  Event.add(ed.id + '_tbl', 'mouseover', function(e) {
680
  var re;
681
+
682
  e = e.target;
683
 
684
  if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {
831
  var f = Event.add(ed.id + '_external_close', 'click', function() {
832
  DOM.hide(ed.id + '_external');
833
  Event.remove(ed.id + '_external_close', 'click', f);
834
+ return false;
835
  });
836
 
837
  DOM.show(e);
944
  },
945
 
946
  _addToolbars : function(c, o) {
947
+ var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup, toolbarsExist = false;
948
 
949
  toolbarGroup = cf.createToolbarGroup('toolbargroup', {
950
  'name': ed.getLang('advanced.toolbar'),
956
  a = s.theme_advanced_toolbar_align.toLowerCase();
957
  a = 'mce' + t._ufirst(a);
958
 
959
+ n = DOM.add(DOM.add(c, 'tr', {role: 'toolbar'}), 'td', {'class' : 'mceToolbar ' + a, "role":"toolbar"});
960
 
961
  // Create toolbar and add the controls
962
  for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {
963
+ toolbarsExist = true;
964
  tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});
965
 
966
  if (s['theme_advanced_buttons' + i + '_add'])
974
 
975
  o.deltaHeight -= s.theme_advanced_row_height;
976
  }
977
+ // Handle case when there are no toolbar buttons and ensure editor height is adjusted accordingly
978
+ if (!toolbarsExist)
979
+ o.deltaHeight -= s.theme_advanced_row_height;
980
  h.push(toolbarGroup.renderHTML());
981
  h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
982
  DOM.setHTML(n, h.join(''));
986
  var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;
987
 
988
  n = DOM.add(tb, 'tr');
989
+ n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});
990
  n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'});
991
  if (s.theme_advanced_path) {
992
  DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path'));
994
  } else {
995
  DOM.add(n, 'span', {}, '&#160;');
996
  }
997
+
998
 
999
  if (s.theme_advanced_resizing) {
1000
  DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"});
1039
  width = startWidth + (e.screenX - startX);
1040
  height = startHeight + (e.screenY - startY);
1041
  t.resizeTo(width, height, true);
1042
+
1043
+ ed.nodeChanged();
1044
  };
1045
 
1046
  e.preventDefault();
1100
 
1101
  p = getParent('A');
1102
  if (c = cm.get('link')) {
1103
+ c.setDisabled((!p && co) || (p && !p.href));
1104
+ c.setActive(!!p && (!p.name && !p.id));
 
 
1105
  }
1106
 
1107
  if (c = cm.get('unlink')) {
1108
  c.setDisabled(!p && co);
1109
+ c.setActive(!!p && !p.name && !p.id);
1110
  }
1111
 
1112
  if (c = cm.get('anchor')) {
1113
+ c.setActive(!co && !!p && (p.name || (p.id && !p.href)));
1114
  }
1115
 
1116
  p = getParent('IMG');
1127
 
1128
  matches = ed.formatter.matchAll(formatNames);
1129
  c.select(matches[0]);
1130
+ tinymce.each(matches, function(match, index) {
1131
+ if (index > 0) {
1132
+ c.mark(match);
1133
+ }
1134
+ });
1135
  }
1136
 
1137
  if (c = cm.get('formatselect')) {
1138
+ p = getParent(ed.dom.isBlock);
1139
 
1140
  if (p)
1141
  c.select(p.nodeName.toLowerCase());
1154
 
1155
  if (!fn && n.style.fontFamily)
1156
  fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase();
1157
+
1158
  if (!fc && n.style.color)
1159
  fc = n.style.color;
1160
 
1185
  return true;
1186
  });
1187
  }
1188
+
1189
  if (s.theme_advanced_show_current_color) {
1190
  function updateColor(controlId, color) {
1191
  if (c = cm.get(controlId)) {
1233
  return;
1234
 
1235
  // Handle prefix
1236
+ if (tinymce.isIE && n.scopeName !== 'HTML' && n.scopeName)
1237
  na = n.scopeName + ':' + na;
1238
 
1239
  // Remove internal prefix
1289
  ti += 'id: ' + v + ' ';
1290
 
1291
  if (v = n.className) {
1292
+ v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '');
1293
 
1294
  if (v) {
1295
  ti += 'class: ' + v + ' ';
1296
 
1297
+ if (ed.dom.isBlock(n) || na == 'img' || na == 'span')
1298
  na += '.' + v;
1299
  }
1300
  }
1353
  ed.windowManager.open({
1354
  url : this.url + '/charmap.htm',
1355
  width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),
1356
+ height : 265 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),
1357
  inline : true
1358
  }, {
1359
  theme_url : this.url
1422
  var ed = this.editor;
1423
 
1424
  // Internal image object like a flash placeholder
1425
+ if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1)
1426
  return;
1427
 
1428
  ed.windowManager.open({
tiny_mce/themes/advanced/img/icons.gif CHANGED
Binary file
tiny_mce/themes/advanced/js/anchor.js CHANGED
@@ -6,7 +6,7 @@ var AnchorDialog = {
6
 
7
  this.editor = ed;
8
  elm = ed.dom.getParent(ed.selection.getNode(), 'A');
9
- v = ed.dom.getAttrib(elm, 'name');
10
 
11
  if (v) {
12
  this.action = 'update';
@@ -17,7 +17,7 @@ var AnchorDialog = {
17
  },
18
 
19
  update : function() {
20
- var ed = this.editor, elm, name = document.forms[0].anchorName.value;
21
 
22
  if (!name || !/^[a-z][a-z0-9\-\_:\.]*$/i.test(name)) {
23
  tinyMCEPopup.alert('advanced_dlg.anchor_invalid');
@@ -29,12 +29,25 @@ var AnchorDialog = {
29
  if (this.action != 'update')
30
  ed.selection.collapse(1);
31
 
 
 
 
 
 
 
 
32
  elm = ed.dom.getParent(ed.selection.getNode(), 'A');
33
  if (elm) {
34
- elm.setAttribute('name', name);
35
- elm.name = name;
36
- } else
37
- ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : name, 'class' : 'mceItemAnchor'}, ''));
 
 
 
 
 
 
38
 
39
  tinyMCEPopup.close();
40
  }
6
 
7
  this.editor = ed;
8
  elm = ed.dom.getParent(ed.selection.getNode(), 'A');
9
+ v = ed.dom.getAttrib(elm, 'name') || ed.dom.getAttrib(elm, 'id');
10
 
11
  if (v) {
12
  this.action = 'update';
17
  },
18
 
19
  update : function() {
20
+ var ed = this.editor, elm, name = document.forms[0].anchorName.value, attribName;
21
 
22
  if (!name || !/^[a-z][a-z0-9\-\_:\.]*$/i.test(name)) {
23
  tinyMCEPopup.alert('advanced_dlg.anchor_invalid');
29
  if (this.action != 'update')
30
  ed.selection.collapse(1);
31
 
32
+ var aRule = ed.schema.getElementRule('a');
33
+ if (!aRule || aRule.attributes.name) {
34
+ attribName = 'name';
35
+ } else {
36
+ attribName = 'id';
37
+ }
38
+
39
  elm = ed.dom.getParent(ed.selection.getNode(), 'A');
40
  if (elm) {
41
+ elm.setAttribute(attribName, name);
42
+ elm[attribName] = name;
43
+ ed.undoManager.add();
44
+ } else {
45
+ // create with zero-sized nbsp so that in Webkit where anchor is on last line by itself caret cannot be placed after it
46
+ var attrs = {'class' : 'mceItemAnchor'};
47
+ attrs[attribName] = name;
48
+ ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', attrs, '\uFEFF'));
49
+ ed.nodeChanged();
50
+ }
51
 
52
  tinyMCEPopup.close();
53
  }
tiny_mce/themes/advanced/js/color_picker.js CHANGED
@@ -1,329 +1,345 @@
1
- tinyMCEPopup.requireLangPack();
2
-
3
- var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false;
4
-
5
- var colors = [
6
- "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033",
7
- "#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099",
8
- "#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff",
9
- "#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033",
10
- "#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399",
11
- "#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff",
12
- "#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333",
13
- "#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399",
14
- "#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff",
15
- "#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633",
16
- "#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699",
17
- "#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff",
18
- "#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633",
19
- "#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999",
20
- "#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff",
21
- "#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933",
22
- "#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999",
23
- "#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff",
24
- "#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33",
25
- "#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99",
26
- "#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff",
27
- "#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33",
28
- "#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99",
29
- "#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff",
30
- "#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33",
31
- "#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99",
32
- "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff"
33
- ];
34
-
35
- var named = {
36
- '#F0F8FF':'Alice Blue','#FAEBD7':'Antique White','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige',
37
- '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'Blanched Almond','#0000FF':'Blue','#8A2BE2':'Blue Violet','#A52A2A':'Brown',
38
- '#DEB887':'Burly Wood','#5F9EA0':'Cadet Blue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'Cornflower Blue',
39
- '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'Dark Blue','#008B8B':'Dark Cyan','#B8860B':'Dark Golden Rod',
40
- '#A9A9A9':'Dark Gray','#A9A9A9':'Dark Grey','#006400':'Dark Green','#BDB76B':'Dark Khaki','#8B008B':'Dark Magenta','#556B2F':'Dark Olive Green',
41
- '#FF8C00':'Darkorange','#9932CC':'Dark Orchid','#8B0000':'Dark Red','#E9967A':'Dark Salmon','#8FBC8F':'Dark Sea Green','#483D8B':'Dark Slate Blue',
42
- '#2F4F4F':'Dark Slate Gray','#2F4F4F':'Dark Slate Grey','#00CED1':'Dark Turquoise','#9400D3':'Dark Violet','#FF1493':'Deep Pink','#00BFFF':'Deep Sky Blue',
43
- '#696969':'Dim Gray','#696969':'Dim Grey','#1E90FF':'Dodger Blue','#B22222':'Fire Brick','#FFFAF0':'Floral White','#228B22':'Forest Green',
44
- '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'Ghost White','#FFD700':'Gold','#DAA520':'Golden Rod','#808080':'Gray','#808080':'Grey',
45
- '#008000':'Green','#ADFF2F':'Green Yellow','#F0FFF0':'Honey Dew','#FF69B4':'Hot Pink','#CD5C5C':'Indian Red','#4B0082':'Indigo','#FFFFF0':'Ivory',
46
- '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'Lavender Blush','#7CFC00':'Lawn Green','#FFFACD':'Lemon Chiffon','#ADD8E6':'Light Blue',
47
- '#F08080':'Light Coral','#E0FFFF':'Light Cyan','#FAFAD2':'Light Golden Rod Yellow','#D3D3D3':'Light Gray','#D3D3D3':'Light Grey','#90EE90':'Light Green',
48
- '#FFB6C1':'Light Pink','#FFA07A':'Light Salmon','#20B2AA':'Light Sea Green','#87CEFA':'Light Sky Blue','#778899':'Light Slate Gray','#778899':'Light Slate Grey',
49
- '#B0C4DE':'Light Steel Blue','#FFFFE0':'Light Yellow','#00FF00':'Lime','#32CD32':'Lime Green','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon',
50
- '#66CDAA':'Medium Aqua Marine','#0000CD':'Medium Blue','#BA55D3':'Medium Orchid','#9370D8':'Medium Purple','#3CB371':'Medium Sea Green','#7B68EE':'Medium Slate Blue',
51
- '#00FA9A':'Medium Spring Green','#48D1CC':'Medium Turquoise','#C71585':'Medium Violet Red','#191970':'Midnight Blue','#F5FFFA':'Mint Cream','#FFE4E1':'Misty Rose','#FFE4B5':'Moccasin',
52
- '#FFDEAD':'Navajo White','#000080':'Navy','#FDF5E6':'Old Lace','#808000':'Olive','#6B8E23':'Olive Drab','#FFA500':'Orange','#FF4500':'Orange Red','#DA70D6':'Orchid',
53
- '#EEE8AA':'Pale Golden Rod','#98FB98':'Pale Green','#AFEEEE':'Pale Turquoise','#D87093':'Pale Violet Red','#FFEFD5':'Papaya Whip','#FFDAB9':'Peach Puff',
54
- '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'Powder Blue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'Rosy Brown','#4169E1':'Royal Blue',
55
- '#8B4513':'Saddle Brown','#FA8072':'Salmon','#F4A460':'Sandy Brown','#2E8B57':'Sea Green','#FFF5EE':'Sea Shell','#A0522D':'Sienna','#C0C0C0':'Silver',
56
- '#87CEEB':'Sky Blue','#6A5ACD':'Slate Blue','#708090':'Slate Gray','#708090':'Slate Grey','#FFFAFA':'Snow','#00FF7F':'Spring Green',
57
- '#4682B4':'Steel Blue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet',
58
- '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'White Smoke','#FFFF00':'Yellow','#9ACD32':'Yellow Green'
59
- };
60
-
61
- var namedLookup = {};
62
-
63
- function init() {
64
- var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color')), key, value;
65
-
66
- tinyMCEPopup.resizeToInnerSize();
67
-
68
- generatePicker();
69
- generateWebColors();
70
- generateNamedColors();
71
-
72
- if (inputColor) {
73
- changeFinalColor(inputColor);
74
-
75
- col = convertHexToRGB(inputColor);
76
-
77
- if (col)
78
- updateLight(col.r, col.g, col.b);
79
- }
80
-
81
- for (key in named) {
82
- value = named[key];
83
- namedLookup[value.replace(/\s+/, '').toLowerCase()] = key.replace(/#/, '').toLowerCase();
84
- }
85
- }
86
-
87
- function toHexColor(color) {
88
- var matches, red, green, blue, toInt = parseInt;
89
-
90
- function hex(value) {
91
- value = parseInt(value).toString(16);
92
-
93
- return value.length > 1 ? value : '0' + value; // Padd with leading zero
94
- };
95
-
96
- color = color.replace(/[\s#]+/g, '').toLowerCase();
97
- color = namedLookup[color] || color;
98
- matches = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)|([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})|([a-f0-9])([a-f0-9])([a-f0-9])$/.exec(color);
99
-
100
- if (matches) {
101
- if (matches[1]) {
102
- red = toInt(matches[1]);
103
- green = toInt(matches[2]);
104
- blue = toInt(matches[3]);
105
- } else if (matches[4]) {
106
- red = toInt(matches[4], 16);
107
- green = toInt(matches[5], 16);
108
- blue = toInt(matches[6], 16);
109
- } else if (matches[7]) {
110
- red = toInt(matches[7] + matches[7], 16);
111
- green = toInt(matches[8] + matches[8], 16);
112
- blue = toInt(matches[9] + matches[9], 16);
113
- }
114
-
115
- return '#' + hex(red) + hex(green) + hex(blue);
116
- }
117
-
118
- return '';
119
- }
120
-
121
- function insertAction() {
122
- var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func');
123
-
124
- tinyMCEPopup.restoreSelection();
125
-
126
- if (f)
127
- f(toHexColor(color));
128
-
129
- tinyMCEPopup.close();
130
- }
131
-
132
- function showColor(color, name) {
133
- if (name)
134
- document.getElementById("colorname").innerHTML = name;
135
-
136
- document.getElementById("preview").style.backgroundColor = color;
137
- document.getElementById("color").value = color.toUpperCase();
138
- }
139
-
140
- function convertRGBToHex(col) {
141
- var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
142
-
143
- if (!col)
144
- return col;
145
-
146
- var rgb = col.replace(re, "$1,$2,$3").split(',');
147
- if (rgb.length == 3) {
148
- r = parseInt(rgb[0]).toString(16);
149
- g = parseInt(rgb[1]).toString(16);
150
- b = parseInt(rgb[2]).toString(16);
151
-
152
- r = r.length == 1 ? '0' + r : r;
153
- g = g.length == 1 ? '0' + g : g;
154
- b = b.length == 1 ? '0' + b : b;
155
-
156
- return "#" + r + g + b;
157
- }
158
-
159
- return col;
160
- }
161
-
162
- function convertHexToRGB(col) {
163
- if (col.indexOf('#') != -1) {
164
- col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
165
-
166
- r = parseInt(col.substring(0, 2), 16);
167
- g = parseInt(col.substring(2, 4), 16);
168
- b = parseInt(col.substring(4, 6), 16);
169
-
170
- return {r : r, g : g, b : b};
171
- }
172
-
173
- return null;
174
- }
175
-
176
- function generatePicker() {
177
- var el = document.getElementById('light'), h = '', i;
178
-
179
- for (i = 0; i < detail; i++){
180
- h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"'
181
- + ' onclick="changeFinalColor(this.style.backgroundColor)"'
182
- + ' onmousedown="isMouseDown = true; return false;"'
183
- + ' onmouseup="isMouseDown = false;"'
184
- + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"'
185
- + ' onmouseover="isMouseOver = true;"'
186
- + ' onmouseout="isMouseOver = false;"'
187
- + '></div>';
188
- }
189
-
190
- el.innerHTML = h;
191
- }
192
-
193
- function generateWebColors() {
194
- var el = document.getElementById('webcolors'), h = '', i;
195
-
196
- if (el.className == 'generated')
197
- return;
198
-
199
- // TODO: VoiceOver doesn't seem to support legend as a label referenced by labelledby.
200
- h += '<div role="listbox" aria-labelledby="webcolors_title" tabindex="0"><table role="presentation" border="0" cellspacing="1" cellpadding="0">'
201
- + '<tr>';
202
-
203
- for (i=0; i<colors.length; i++) {
204
- h += '<td bgcolor="' + colors[i] + '" width="10" height="10">'
205
- + '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="web_colors_' + i + '" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');" style="display:block;width:10px;height:10px;overflow:hidden;">';
206
- if (tinyMCEPopup.editor.forcedHighContrastMode) {
207
- h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>';
208
- }
209
- h += '<span class="mceVoiceLabel" style="display:none;" id="web_colors_' + i + '">' + colors[i].toUpperCase() + '</span>';
210
- h += '</a></td>';
211
- if ((i+1) % 18 == 0)
212
- h += '</tr><tr>';
213
- }
214
-
215
- h += '</table></div>';
216
-
217
- el.innerHTML = h;
218
- el.className = 'generated';
219
-
220
- paintCanvas(el);
221
- enableKeyboardNavigation(el.firstChild);
222
- }
223
-
224
- function paintCanvas(el) {
225
- tinyMCEPopup.getWin().tinymce.each(tinyMCEPopup.dom.select('canvas.mceColorSwatch', el), function(canvas) {
226
- var context;
227
- if (canvas.getContext && (context = canvas.getContext("2d"))) {
228
- context.fillStyle = canvas.getAttribute('data-color');
229
- context.fillRect(0, 0, 10, 10);
230
- }
231
- });
232
- }
233
- function generateNamedColors() {
234
- var el = document.getElementById('namedcolors'), h = '', n, v, i = 0;
235
-
236
- if (el.className == 'generated')
237
- return;
238
-
239
- for (n in named) {
240
- v = named[n];
241
- h += '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="named_colors_' + i + '" onfocus="showColor(\'' + n + '\',\'' + v + '\');" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '">';
242
- if (tinyMCEPopup.editor.forcedHighContrastMode) {
243
- h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>';
244
- }
245
- h += '<span class="mceVoiceLabel" style="display:none;" id="named_colors_' + i + '">' + v + '</span>';
246
- h += '</a>';
247
- i++;
248
- }
249
-
250
- el.innerHTML = h;
251
- el.className = 'generated';
252
-
253
- paintCanvas(el);
254
- enableKeyboardNavigation(el);
255
- }
256
-
257
- function enableKeyboardNavigation(el) {
258
- tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', {
259
- root: el,
260
- items: tinyMCEPopup.dom.select('a', el)
261
- }, tinyMCEPopup.dom);
262
- }
263
-
264
- function dechex(n) {
265
- return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16);
266
- }
267
-
268
- function computeColor(e) {
269
- var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB, pos = tinyMCEPopup.dom.getPos(e.target);
270
-
271
- x = e.offsetX ? e.offsetX : (e.target ? e.clientX - pos.x : 0);
272
- y = e.offsetY ? e.offsetY : (e.target ? e.clientY - pos.y : 0);
273
-
274
- partWidth = document.getElementById('colors').width / 6;
275
- partDetail = detail / 2;
276
- imHeight = document.getElementById('colors').height;
277
-
278
- r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255;
279
- g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255 + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth);
280
- b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth);
281
-
282
- coef = (imHeight - y) / imHeight;
283
- r = 128 + (r - 128) * coef;
284
- g = 128 + (g - 128) * coef;
285
- b = 128 + (b - 128) * coef;
286
-
287
- changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b));
288
- updateLight(r, g, b);
289
- }
290
-
291
- function updateLight(r, g, b) {
292
- var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color;
293
-
294
- for (i=0; i<detail; i++) {
295
- if ((i>=0) && (i<partDetail)) {
296
- finalCoef = i / partDetail;
297
- finalR = dechex(255 - (255 - r) * finalCoef);
298
- finalG = dechex(255 - (255 - g) * finalCoef);
299
- finalB = dechex(255 - (255 - b) * finalCoef);
300
- } else {
301
- finalCoef = 2 - i / partDetail;
302
- finalR = dechex(r * finalCoef);
303
- finalG = dechex(g * finalCoef);
304
- finalB = dechex(b * finalCoef);
305
- }
306
-
307
- color = finalR + finalG + finalB;
308
-
309
- setCol('gs' + i, '#'+color);
310
- }
311
- }
312
-
313
- function changeFinalColor(color) {
314
- if (color.indexOf('#') == -1)
315
- color = convertRGBToHex(color);
316
-
317
- setCol('preview', color);
318
- document.getElementById('color').value = color;
319
- }
320
-
321
- function setCol(e, c) {
322
- try {
323
- document.getElementById(e).style.backgroundColor = c;
324
- } catch (ex) {
325
- // Ignore IE warning
326
- }
327
- }
328
-
329
- tinyMCEPopup.onInit.add(init);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ tinyMCEPopup.requireLangPack();
2
+
3
+ var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false;
4
+
5
+ var colors = [
6
+ "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033",
7
+ "#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099",
8
+ "#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff",
9
+ "#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033",
10
+ "#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399",
11
+ "#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff",
12
+ "#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333",
13
+ "#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399",
14
+ "#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff",
15
+ "#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633",
16
+ "#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699",
17
+ "#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff",
18
+ "#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633",
19
+ "#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999",
20
+ "#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff",
21
+ "#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933",
22
+ "#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999",
23
+ "#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff",
24
+ "#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33",
25
+ "#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99",
26
+ "#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff",
27
+ "#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33",
28
+ "#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99",
29
+ "#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff",
30
+ "#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33",
31
+ "#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99",
32
+ "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff"
33
+ ];
34
+
35
+ var named = {
36
+ '#F0F8FF':'Alice Blue','#FAEBD7':'Antique White','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige',
37
+ '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'Blanched Almond','#0000FF':'Blue','#8A2BE2':'Blue Violet','#A52A2A':'Brown',
38
+ '#DEB887':'Burly Wood','#5F9EA0':'Cadet Blue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'Cornflower Blue',
39
+ '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'Dark Blue','#008B8B':'Dark Cyan','#B8860B':'Dark Golden Rod',
40
+ '#A9A9A9':'Dark Gray','#A9A9A9':'Dark Grey','#006400':'Dark Green','#BDB76B':'Dark Khaki','#8B008B':'Dark Magenta','#556B2F':'Dark Olive Green',
41
+ '#FF8C00':'Darkorange','#9932CC':'Dark Orchid','#8B0000':'Dark Red','#E9967A':'Dark Salmon','#8FBC8F':'Dark Sea Green','#483D8B':'Dark Slate Blue',
42
+ '#2F4F4F':'Dark Slate Gray','#2F4F4F':'Dark Slate Grey','#00CED1':'Dark Turquoise','#9400D3':'Dark Violet','#FF1493':'Deep Pink','#00BFFF':'Deep Sky Blue',
43
+ '#696969':'Dim Gray','#696969':'Dim Grey','#1E90FF':'Dodger Blue','#B22222':'Fire Brick','#FFFAF0':'Floral White','#228B22':'Forest Green',
44
+ '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'Ghost White','#FFD700':'Gold','#DAA520':'Golden Rod','#808080':'Gray','#808080':'Grey',
45
+ '#008000':'Green','#ADFF2F':'Green Yellow','#F0FFF0':'Honey Dew','#FF69B4':'Hot Pink','#CD5C5C':'Indian Red','#4B0082':'Indigo','#FFFFF0':'Ivory',
46
+ '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'Lavender Blush','#7CFC00':'Lawn Green','#FFFACD':'Lemon Chiffon','#ADD8E6':'Light Blue',
47
+ '#F08080':'Light Coral','#E0FFFF':'Light Cyan','#FAFAD2':'Light Golden Rod Yellow','#D3D3D3':'Light Gray','#D3D3D3':'Light Grey','#90EE90':'Light Green',
48
+ '#FFB6C1':'Light Pink','#FFA07A':'Light Salmon','#20B2AA':'Light Sea Green','#87CEFA':'Light Sky Blue','#778899':'Light Slate Gray','#778899':'Light Slate Grey',
49
+ '#B0C4DE':'Light Steel Blue','#FFFFE0':'Light Yellow','#00FF00':'Lime','#32CD32':'Lime Green','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon',
50
+ '#66CDAA':'Medium Aqua Marine','#0000CD':'Medium Blue','#BA55D3':'Medium Orchid','#9370D8':'Medium Purple','#3CB371':'Medium Sea Green','#7B68EE':'Medium Slate Blue',
51
+ '#00FA9A':'Medium Spring Green','#48D1CC':'Medium Turquoise','#C71585':'Medium Violet Red','#191970':'Midnight Blue','#F5FFFA':'Mint Cream','#FFE4E1':'Misty Rose','#FFE4B5':'Moccasin',
52
+ '#FFDEAD':'Navajo White','#000080':'Navy','#FDF5E6':'Old Lace','#808000':'Olive','#6B8E23':'Olive Drab','#FFA500':'Orange','#FF4500':'Orange Red','#DA70D6':'Orchid',
53
+ '#EEE8AA':'Pale Golden Rod','#98FB98':'Pale Green','#AFEEEE':'Pale Turquoise','#D87093':'Pale Violet Red','#FFEFD5':'Papaya Whip','#FFDAB9':'Peach Puff',
54
+ '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'Powder Blue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'Rosy Brown','#4169E1':'Royal Blue',
55
+ '#8B4513':'Saddle Brown','#FA8072':'Salmon','#F4A460':'Sandy Brown','#2E8B57':'Sea Green','#FFF5EE':'Sea Shell','#A0522D':'Sienna','#C0C0C0':'Silver',
56
+ '#87CEEB':'Sky Blue','#6A5ACD':'Slate Blue','#708090':'Slate Gray','#708090':'Slate Grey','#FFFAFA':'Snow','#00FF7F':'Spring Green',
57
+ '#4682B4':'Steel Blue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet',
58
+ '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'White Smoke','#FFFF00':'Yellow','#9ACD32':'Yellow Green'
59
+ };
60
+
61
+ var namedLookup = {};
62
+
63
+ function init() {
64
+ var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color')), key, value;
65
+
66
+ tinyMCEPopup.resizeToInnerSize();
67
+
68
+ generatePicker();
69
+ generateWebColors();
70
+ generateNamedColors();
71
+
72
+ if (inputColor) {
73
+ changeFinalColor(inputColor);
74
+
75
+ col = convertHexToRGB(inputColor);
76
+
77
+ if (col)
78
+ updateLight(col.r, col.g, col.b);
79
+ }
80
+
81
+ for (key in named) {
82
+ value = named[key];
83
+ namedLookup[value.replace(/\s+/, '').toLowerCase()] = key.replace(/#/, '').toLowerCase();
84
+ }
85
+ }
86
+
87
+ function toHexColor(color) {
88
+ var matches, red, green, blue, toInt = parseInt;
89
+
90
+ function hex(value) {
91
+ value = parseInt(value).toString(16);
92
+
93
+ return value.length > 1 ? value : '0' + value; // Padd with leading zero
94
+ };
95
+
96
+ color = tinymce.trim(color);
97
+ color = color.replace(/^[#]/, '').toLowerCase(); // remove leading '#'
98
+ color = namedLookup[color] || color;
99
+
100
+ matches = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/.exec(color);
101
+
102
+ if (matches) {
103
+ red = toInt(matches[1]);
104
+ green = toInt(matches[2]);
105
+ blue = toInt(matches[3]);
106
+ } else {
107
+ matches = /^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/.exec(color);
108
+
109
+ if (matches) {
110
+ red = toInt(matches[1], 16);
111
+ green = toInt(matches[2], 16);
112
+ blue = toInt(matches[3], 16);
113
+ } else {
114
+ matches = /^([0-9a-f])([0-9a-f])([0-9a-f])$/.exec(color);
115
+
116
+ if (matches) {
117
+ red = toInt(matches[1] + matches[1], 16);
118
+ green = toInt(matches[2] + matches[2], 16);
119
+ blue = toInt(matches[3] + matches[3], 16);
120
+ } else {
121
+ return '';
122
+ }
123
+ }
124
+ }
125
+
126
+ return '#' + hex(red) + hex(green) + hex(blue);
127
+ }
128
+
129
+ function insertAction() {
130
+ var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func');
131
+
132
+ var hexColor = toHexColor(color);
133
+
134
+ if (hexColor === '') {
135
+ var text = tinyMCEPopup.editor.getLang('advanced_dlg.invalid_color_value');
136
+ tinyMCEPopup.alert(text + ': ' + color);
137
+ }
138
+ else {
139
+ tinyMCEPopup.restoreSelection();
140
+
141
+ if (f)
142
+ f(hexColor);
143
+
144
+ tinyMCEPopup.close();
145
+ }
146
+ }
147
+
148
+ function showColor(color, name) {
149
+ if (name)
150
+ document.getElementById("colorname").innerHTML = name;
151
+
152
+ document.getElementById("preview").style.backgroundColor = color;
153
+ document.getElementById("color").value = color.toUpperCase();
154
+ }
155
+
156
+ function convertRGBToHex(col) {
157
+ var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
158
+
159
+ if (!col)
160
+ return col;
161
+
162
+ var rgb = col.replace(re, "$1,$2,$3").split(',');
163
+ if (rgb.length == 3) {
164
+ r = parseInt(rgb[0]).toString(16);
165
+ g = parseInt(rgb[1]).toString(16);
166
+ b = parseInt(rgb[2]).toString(16);
167
+
168
+ r = r.length == 1 ? '0' + r : r;
169
+ g = g.length == 1 ? '0' + g : g;
170
+ b = b.length == 1 ? '0' + b : b;
171
+
172
+ return "#" + r + g + b;
173
+ }
174
+
175
+ return col;
176
+ }
177
+
178
+ function convertHexToRGB(col) {
179
+ if (col.indexOf('#') != -1) {
180
+ col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
181
+
182
+ r = parseInt(col.substring(0, 2), 16);
183
+ g = parseInt(col.substring(2, 4), 16);
184
+ b = parseInt(col.substring(4, 6), 16);
185
+
186
+ return {r : r, g : g, b : b};
187
+ }
188
+
189
+ return null;
190
+ }
191
+
192
+ function generatePicker() {
193
+ var el = document.getElementById('light'), h = '', i;
194
+
195
+ for (i = 0; i < detail; i++){
196
+ h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"'
197
+ + ' onclick="changeFinalColor(this.style.backgroundColor)"'
198
+ + ' onmousedown="isMouseDown = true; return false;"'
199
+ + ' onmouseup="isMouseDown = false;"'
200
+ + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"'
201
+ + ' onmouseover="isMouseOver = true;"'
202
+ + ' onmouseout="isMouseOver = false;"'
203
+ + '></div>';
204
+ }
205
+
206
+ el.innerHTML = h;
207
+ }
208
+
209
+ function generateWebColors() {
210
+ var el = document.getElementById('webcolors'), h = '', i;
211
+
212
+ if (el.className == 'generated')
213
+ return;
214
+
215
+ // TODO: VoiceOver doesn't seem to support legend as a label referenced by labelledby.
216
+ h += '<div role="listbox" aria-labelledby="webcolors_title" tabindex="0"><table role="presentation" border="0" cellspacing="1" cellpadding="0">'
217
+ + '<tr>';
218
+
219
+ for (i=0; i<colors.length; i++) {
220
+ h += '<td bgcolor="' + colors[i] + '" width="10" height="10">'
221
+ + '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="web_colors_' + i + '" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');" style="display:block;width:10px;height:10px;overflow:hidden;">';
222
+ if (tinyMCEPopup.editor.forcedHighContrastMode) {
223
+ h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>';
224
+ }
225
+ h += '<span class="mceVoiceLabel" style="display:none;" id="web_colors_' + i + '">' + colors[i].toUpperCase() + '</span>';
226
+ h += '</a></td>';
227
+ if ((i+1) % 18 == 0)
228
+ h += '</tr><tr>';
229
+ }
230
+
231
+ h += '</table></div>';
232
+
233
+ el.innerHTML = h;
234
+ el.className = 'generated';
235
+
236
+ paintCanvas(el);
237
+ enableKeyboardNavigation(el.firstChild);
238
+ }
239
+
240
+ function paintCanvas(el) {
241
+ tinyMCEPopup.getWin().tinymce.each(tinyMCEPopup.dom.select('canvas.mceColorSwatch', el), function(canvas) {
242
+ var context;
243
+ if (canvas.getContext && (context = canvas.getContext("2d"))) {
244
+ context.fillStyle = canvas.getAttribute('data-color');
245
+ context.fillRect(0, 0, 10, 10);
246
+ }
247
+ });
248
+ }
249
+ function generateNamedColors() {
250
+ var el = document.getElementById('namedcolors'), h = '', n, v, i = 0;
251
+
252
+ if (el.className == 'generated')
253
+ return;
254
+
255
+ for (n in named) {
256
+ v = named[n];
257
+ h += '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="named_colors_' + i + '" onfocus="showColor(\'' + n + '\',\'' + v + '\');" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '">';
258
+ if (tinyMCEPopup.editor.forcedHighContrastMode) {
259
+ h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>';
260
+ }
261
+ h += '<span class="mceVoiceLabel" style="display:none;" id="named_colors_' + i + '">' + v + '</span>';
262
+ h += '</a>';
263
+ i++;
264
+ }
265
+
266
+ el.innerHTML = h;
267
+ el.className = 'generated';
268
+
269
+ paintCanvas(el);
270
+ enableKeyboardNavigation(el);
271
+ }
272
+
273
+ function enableKeyboardNavigation(el) {
274
+ tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', {
275
+ root: el,
276
+ items: tinyMCEPopup.dom.select('a', el)
277
+ }, tinyMCEPopup.dom);
278
+ }
279
+
280
+ function dechex(n) {
281
+ return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16);
282
+ }
283
+
284
+ function computeColor(e) {
285
+ var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB, pos = tinyMCEPopup.dom.getPos(e.target);
286
+
287
+ x = e.offsetX ? e.offsetX : (e.target ? e.clientX - pos.x : 0);
288
+ y = e.offsetY ? e.offsetY : (e.target ? e.clientY - pos.y : 0);
289
+
290
+ partWidth = document.getElementById('colors').width / 6;
291
+ partDetail = detail / 2;
292
+ imHeight = document.getElementById('colors').height;
293
+
294
+ r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255;
295
+ g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255 + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth);
296
+ b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth);
297
+
298
+ coef = (imHeight - y) / imHeight;
299
+ r = 128 + (r - 128) * coef;
300
+ g = 128 + (g - 128) * coef;
301
+ b = 128 + (b - 128) * coef;
302
+
303
+ changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b));
304
+ updateLight(r, g, b);
305
+ }
306
+
307
+ function updateLight(r, g, b) {
308
+ var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color;
309
+
310
+ for (i=0; i<detail; i++) {
311
+ if ((i>=0) && (i<partDetail)) {
312
+ finalCoef = i / partDetail;
313
+ finalR = dechex(255 - (255 - r) * finalCoef);
314
+ finalG = dechex(255 - (255 - g) * finalCoef);
315
+ finalB = dechex(255 - (255 - b) * finalCoef);
316
+ } else {
317
+ finalCoef = 2 - i / partDetail;
318
+ finalR = dechex(r * finalCoef);
319
+ finalG = dechex(g * finalCoef);
320
+ finalB = dechex(b * finalCoef);
321
+ }
322
+
323
+ color = finalR + finalG + finalB;
324
+
325
+ setCol('gs' + i, '#'+color);
326
+ }
327
+ }
328
+
329
+ function changeFinalColor(color) {
330
+ if (color.indexOf('#') == -1)
331
+ color = convertRGBToHex(color);
332
+
333
+ setCol('preview', color);
334
+ document.getElementById('color').value = color;
335
+ }
336
+
337
+ function setCol(e, c) {
338
+ try {
339
+ document.getElementById(e).style.backgroundColor = c;
340
+ } catch (ex) {
341
+ // Ignore IE warning
342
+ }
343
+ }
344
+
345
+ tinyMCEPopup.onInit.add(init);
tiny_mce/themes/advanced/js/image.js CHANGED
@@ -104,10 +104,12 @@ var ImageDialog = {
104
  },
105
 
106
  updateStyle : function() {
107
- var dom = tinyMCEPopup.dom, st, v, f = document.forms[0];
108
 
109
  if (tinyMCEPopup.editor.settings.inline_styles) {
110
- st = tinyMCEPopup.dom.parseStyle(this.styleVal);
 
 
111
 
112
  // Handle align
113
  v = getSelectValue(f, 'align');
104
  },
105
 
106
  updateStyle : function() {
107
+ var dom = tinyMCEPopup.dom, st = {}, v, f = document.forms[0];
108
 
109
  if (tinyMCEPopup.editor.settings.inline_styles) {
110
+ tinymce.each(tinyMCEPopup.dom.parseStyle(this.styleVal), function(value, key) {
111
+ st[key] = value;
112
+ });
113
 
114
  // Handle align
115
  v = getSelectValue(f, 'align');
tiny_mce/themes/advanced/js/link.js CHANGED
@@ -68,10 +68,16 @@ var LinkDialog = {
68
  } else {
69
  ed.dom.setAttribs(e, {
70
  href : href,
71
- title : f.linktitle.value,
72
- target : f.target_list ? getSelectValue(f, "target_list") : null,
73
- 'class' : f.class_list ? getSelectValue(f, "class_list") : null
74
  });
 
 
 
 
 
 
 
 
75
  }
76
 
77
  // Don't move caret if selection was image
68
  } else {
69
  ed.dom.setAttribs(e, {
70
  href : href,
71
+ title : f.linktitle.value
 
 
72
  });
73
+
74
+ if (f.target_list) {
75
+ ed.dom.setAttrib(e, 'target', getSelectValue(f, "target_list"));
76
+ }
77
+
78
+ if (f.class_list) {
79
+ ed.dom.setAttrib(e, 'class', getSelectValue(f, "class_list"));
80
+ }
81
  }
82
 
83
  // Don't move caret if selection was image
tiny_mce/themes/advanced/js/source_editor.js CHANGED
@@ -16,7 +16,7 @@ function onLoadInit() {
16
  document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent({source_view : true});
17
 
18
  if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) {
19
- setWrap('soft');
20
  document.getElementById('wraped').checked = true;
21
  }
22
 
@@ -37,11 +37,33 @@ function setWrap(val) {
37
  }
38
  }
39
 
40
- function toggleWordWrap(elm) {
41
- if (elm.checked)
42
- setWrap('soft');
43
- else
 
 
 
 
 
44
  setWrap('off');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
 
47
  function resizeInputs() {
16
  document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent({source_view : true});
17
 
18
  if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) {
19
+ turnWrapOn();
20
  document.getElementById('wraped').checked = true;
21
  }
22
 
37
  }
38
  }
39
 
40
+ function setWhiteSpaceCss(value) {
41
+ var el = document.getElementById('htmlSource');
42
+ tinymce.DOM.setStyle(el, 'white-space', value);
43
+ }
44
+
45
+ function turnWrapOff() {
46
+ if (tinymce.isWebKit) {
47
+ setWhiteSpaceCss('pre');
48
+ } else {
49
  setWrap('off');
50
+ }
51
+ }
52
+
53
+ function turnWrapOn() {
54
+ if (tinymce.isWebKit) {
55
+ setWhiteSpaceCss('pre-wrap');
56
+ } else {
57
+ setWrap('soft');
58
+ }
59
+ }
60
+
61
+ function toggleWordWrap(elm) {
62
+ if (elm.checked) {
63
+ turnWrapOn();
64
+ } else {
65
+ turnWrapOff();
66
+ }
67
  }
68
 
69
  function resizeInputs() {
tiny_mce/themes/advanced/langs/en_dlg.js CHANGED
@@ -1 +1 @@
1
- tinyMCE.addI18n('en.advanced_dlg', {"link_list":"Link List","link_is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","link_is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?","link_titlefield":"Title","link_target_blank":"Open Link in a New Window","link_target_same":"Open Link in the Same Window","link_target":"Target","link_url":"Link URL","link_title":"Insert/Edit Link","image_align_right":"Right","image_align_left":"Left","image_align_textbottom":"Text Bottom","image_align_texttop":"Text Top","image_align_bottom":"Bottom","image_align_middle":"Middle","image_align_top":"Top","image_align_baseline":"Baseline","image_align":"Alignment","image_hspace":"Horizontal Space","image_vspace":"Vertical Space","image_dimensions":"Dimensions","image_alt":"Image Description","image_list":"Image List","image_border":"Border","image_src":"Image URL","image_title":"Insert/Edit Image","charmap_title":"Select Special Character", "charmap_usage":"Use left and right arrows to navigate.","colorpicker_name":"Name:","colorpicker_color":"Color:","colorpicker_named_title":"Named Colors","colorpicker_named_tab":"Named","colorpicker_palette_title":"Palette Colors","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Color Picker","colorpicker_picker_tab":"Picker","colorpicker_title":"Select a Color","code_wordwrap":"Word Wrap","code_title":"HTML Source Editor","anchor_name":"Anchor Name","anchor_title":"Insert/Edit Anchor","about_loaded":"Loaded Plugins","about_version":"Version","about_author":"Author","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"License","about_help":"Help","about_general":"About","about_title":"About TinyMCE","anchor_invalid":"Please specify a valid anchor name.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage","":""});
1
+ tinyMCE.addI18n('en.advanced_dlg', {"link_list":"Link List","link_is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","link_is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?","link_titlefield":"Title","link_target_blank":"Open Link in a New Window","link_target_same":"Open Link in the Same Window","link_target":"Target","link_url":"Link URL","link_title":"Insert/Edit Link","image_align_right":"Right","image_align_left":"Left","image_align_textbottom":"Text Bottom","image_align_texttop":"Text Top","image_align_bottom":"Bottom","image_align_middle":"Middle","image_align_top":"Top","image_align_baseline":"Baseline","image_align":"Alignment","image_hspace":"Horizontal Space","image_vspace":"Vertical Space","image_dimensions":"Dimensions","image_alt":"Image Description","image_list":"Image List","image_border":"Border","image_src":"Image URL","image_title":"Insert/Edit Image","charmap_title":"Select Special Character", "charmap_usage":"Use left and right arrows to navigate.","colorpicker_name":"Name:","colorpicker_color":"Color:","colorpicker_named_title":"Named Colors","colorpicker_named_tab":"Named","colorpicker_palette_title":"Palette Colors","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Color Picker","colorpicker_picker_tab":"Picker","colorpicker_title":"Select a Color","code_wordwrap":"Word Wrap","code_title":"HTML Source Editor","anchor_name":"Anchor Name","anchor_title":"Insert/Edit Anchor","about_loaded":"Loaded Plugins","about_version":"Version","about_author":"Author","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"License","about_help":"Help","about_general":"About","about_title":"About TinyMCE","anchor_invalid":"Please specify a valid anchor name.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage","invalid_color_value":"Invalid color value","":""});
tiny_mce/themes/advanced/skins/default/dialog.css CHANGED
@@ -105,11 +105,12 @@ h3 {font-size:14px;}
105
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
106
  #plugintable {width:96%; margin-top:10px;}
107
  #pluginscontainer {height:290px; overflow:auto;}
108
- #colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
 
 
109
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
110
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
111
  #colorpicker #light div {overflow:hidden;}
112
- #colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
113
  #colorpicker .panel_wrapper div.current {height:175px;}
114
  #colorpicker #namedcolors {width:150px;}
115
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
105
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
106
  #plugintable {width:96%; margin-top:10px;}
107
  #pluginscontainer {height:290px; overflow:auto;}
108
+ #colorpicker #preview {display:inline-block; padding-left:40px; height:14px; border:1px solid black; margin-left:5px; margin-right: 5px}
109
+ #colorpicker #previewblock {position: relative; top: -3px; padding-left:5px; padding-top: 0px; display:inline}
110
+ #colorpicker #preview_wrapper { text-align:center; padding-top:4px; white-space: nowrap}
111
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
112
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
113
  #colorpicker #light div {overflow:hidden;}
 
114
  #colorpicker .panel_wrapper div.current {height:175px;}
115
  #colorpicker #namedcolors {width:150px;}
116
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
tiny_mce/themes/advanced/skins/default/ui.css CHANGED
@@ -83,7 +83,7 @@
83
  .defaultSkin .mce_forecolor span.mceAction, .defaultSkin .mce_backcolor span.mceAction {overflow:hidden; height:16px}
84
 
85
  /* Menu */
86
- .defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8}
87
  .defaultSkin .mceNoIcons span.mceIcon {width:0;}
88
  .defaultSkin .mceNoIcons a .mceText {padding-left:10px}
89
  .defaultSkin .mceMenu table {background:#FFF}
@@ -109,6 +109,10 @@
109
  .defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50); background:#FFF}
110
  .defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
111
 
 
 
 
 
112
  /* Formats */
113
  .defaultSkin .mce_formatPreview a {font-size:10px}
114
  .defaultSkin .mce_p span.mceText {}
@@ -212,3 +216,4 @@
212
  .defaultSkin span.mce_pagebreak {background-position:0 -40px}
213
  .defaultSkin span.mce_restoredraft {background-position:-20px -40px}
214
  .defaultSkin span.mce_spellchecker {background-position:-540px -20px}
 
83
  .defaultSkin .mce_forecolor span.mceAction, .defaultSkin .mce_backcolor span.mceAction {overflow:hidden; height:16px}
84
 
85
  /* Menu */
86
+ .defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8; direction:ltr}
87
  .defaultSkin .mceNoIcons span.mceIcon {width:0;}
88
  .defaultSkin .mceNoIcons a .mceText {padding-left:10px}
89
  .defaultSkin .mceMenu table {background:#FFF}
109
  .defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50); background:#FFF}
110
  .defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
111
 
112
+ /* Rtl */
113
+ .mceRtl .mceListBox .mceText {text-align: right; padding: 0 4px 0 0}
114
+ .mceRtl .mceMenuItem .mceText {text-align: right}
115
+
116
  /* Formats */
117
  .defaultSkin .mce_formatPreview a {font-size:10px}
118
  .defaultSkin .mce_p span.mceText {}
216
  .defaultSkin span.mce_pagebreak {background-position:0 -40px}
217
  .defaultSkin span.mce_restoredraft {background-position:-20px -40px}
218
  .defaultSkin span.mce_spellchecker {background-position:-540px -20px}
219
+ .defaultSkin span.mce_visualblocks {background-position: -40px -40px}
tiny_mce/themes/advanced/skins/highcontrast/dialog.css CHANGED
@@ -1,7 +1,7 @@
1
  /* Generic */
2
  body {
3
  font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;
4
- background:#F0F0EE;
5
  color: black;
6
  padding:0;
7
  margin:8px 8px 0 8px;
@@ -94,11 +94,12 @@ h3 {font-size:14px;}
94
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
95
  #plugintable {width:96%; margin-top:10px;}
96
  #pluginscontainer {height:290px; overflow:auto;}
97
- #colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
 
 
98
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
99
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
100
  #colorpicker #light div {overflow:hidden;}
101
- #colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
102
  #colorpicker .panel_wrapper div.current {height:175px;}
103
  #colorpicker #namedcolors {width:150px;}
104
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
1
  /* Generic */
2
  body {
3
  font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;
4
+ background:#F0F0EE;
5
  color: black;
6
  padding:0;
7
  margin:8px 8px 0 8px;
94
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
95
  #plugintable {width:96%; margin-top:10px;}
96
  #pluginscontainer {height:290px; overflow:auto;}
97
+ #colorpicker #preview {display:inline-block; padding-left:40px; height:14px; border:1px solid black; margin-left:5px; margin-right: 5px}
98
+ #colorpicker #previewblock {position: relative; top: -3px; padding-left:5px; padding-top: 0px; display:inline}
99
+ #colorpicker #preview_wrapper { text-align:center; padding-top:4px; white-space: nowrap}
100
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
101
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
102
  #colorpicker #light div {overflow:hidden;}
 
103
  #colorpicker .panel_wrapper div.current {height:175px;}
104
  #colorpicker #namedcolors {width:150px;}
105
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
tiny_mce/themes/advanced/skins/highcontrast/ui.css CHANGED
@@ -58,7 +58,7 @@
58
 
59
  /* Menu */
60
  .highcontrastSkin .mceNoIcons span.mceIcon {width:0;}
61
- .highcontrastSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid; }
62
  .highcontrastSkin .mceMenu table {background:white; color: black}
63
  .highcontrastSkin .mceNoIcons a .mceText {padding-left:10px}
64
  .highcontrastSkin .mceMenu a, .highcontrastSkin .mceMenu span, .highcontrastSkin .mceMenu {display:block;background:white; color: black}
@@ -90,6 +90,10 @@
90
  .highcontrastSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF}
91
  .highcontrastSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
92
 
 
 
 
 
93
  /* Formats */
94
  .highcontrastSkin .mce_p span.mceText {}
95
  .highcontrastSkin .mce_address span.mceText {font-style:italic}
58
 
59
  /* Menu */
60
  .highcontrastSkin .mceNoIcons span.mceIcon {width:0;}
61
+ .highcontrastSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid; direction:ltr}
62
  .highcontrastSkin .mceMenu table {background:white; color: black}
63
  .highcontrastSkin .mceNoIcons a .mceText {padding-left:10px}
64
  .highcontrastSkin .mceMenu a, .highcontrastSkin .mceMenu span, .highcontrastSkin .mceMenu {display:block;background:white; color: black}
90
  .highcontrastSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF}
91
  .highcontrastSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
92
 
93
+ /* Rtl */
94
+ .mceRtl .mceListBox .mceText {text-align: right; padding: 0 4px 0 0}
95
+ .mceRtl .mceMenuItem .mceText {text-align: right}
96
+
97
  /* Formats */
98
  .highcontrastSkin .mce_p span.mceText {}
99
  .highcontrastSkin .mce_address span.mceText {font-style:italic}
tiny_mce/themes/advanced/skins/o2k7/dialog.css CHANGED
@@ -105,11 +105,12 @@ h3 {font-size:14px;}
105
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
106
  #plugintable {width:96%; margin-top:10px;}
107
  #pluginscontainer {height:290px; overflow:auto;}
108
- #colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
 
 
109
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
110
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
111
  #colorpicker #light div {overflow:hidden;}
112
- #colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
113
  #colorpicker .panel_wrapper div.current {height:175px;}
114
  #colorpicker #namedcolors {width:150px;}
115
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
105
  #plugintable, #about #plugintable td {border:1px solid #919B9C;}
106
  #plugintable {width:96%; margin-top:10px;}
107
  #pluginscontainer {height:290px; overflow:auto;}
108
+ #colorpicker #preview {display:inline-block; padding-left:40px; height:14px; border:1px solid black; margin-left:5px; margin-right: 5px}
109
+ #colorpicker #previewblock {position: relative; top: -3px; padding-left:5px; padding-top: 0px; display:inline}
110
+ #colorpicker #preview_wrapper { text-align:center; padding-top:4px; white-space: nowrap}
111
  #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
112
  #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
113
  #colorpicker #light div {overflow:hidden;}
 
114
  #colorpicker .panel_wrapper div.current {height:175px;}
115
  #colorpicker #namedcolors {width:150px;}
116
  #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
tiny_mce/themes/advanced/skins/o2k7/ui.css CHANGED
@@ -86,7 +86,7 @@
86
  .o2k7Skin .mce_forecolor span.mceAction, .o2k7Skin .mce_backcolor span.mceAction {height:15px;overflow:hidden}
87
 
88
  /* Menu */
89
- .o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD}
90
  .o2k7Skin .mceNoIcons span.mceIcon {width:0;}
91
  .o2k7Skin .mceNoIcons a .mceText {padding-left:10px}
92
  .o2k7Skin .mceMenu table {background:#FFF}
@@ -112,6 +112,10 @@
112
  .o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF}
113
  .o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
114
 
 
 
 
 
115
  /* Formats */
116
  .o2k7Skin .mce_formatPreview a {font-size:10px}
117
  .o2k7Skin .mce_p span.mceText {}
@@ -215,3 +219,4 @@
215
  .o2k7Skin span.mce_pagebreak {background-position:0 -40px}
216
  .o2k7Skin span.mce_restoredraft {background-position:-20px -40px}
217
  .o2k7Skin span.mce_spellchecker {background-position:-540px -20px}
 
86
  .o2k7Skin .mce_forecolor span.mceAction, .o2k7Skin .mce_backcolor span.mceAction {height:15px;overflow:hidden}
87
 
88
  /* Menu */
89
+ .o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD; direction:ltr}
90
  .o2k7Skin .mceNoIcons span.mceIcon {width:0;}
91
  .o2k7Skin .mceNoIcons a .mceText {padding-left:10px}
92
  .o2k7Skin .mceMenu table {background:#FFF}
112
  .o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF}
113
  .o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
114
 
115
+ /* Rtl */
116
+ .mceRtl .mceListBox .mceText {text-align: right; padding: 0 4px 0 0}
117
+ .mceRtl .mceMenuItem .mceText {text-align: right}
118
+
119
  /* Formats */
120
  .o2k7Skin .mce_formatPreview a {font-size:10px}
121
  .o2k7Skin .mce_p span.mceText {}
219
  .o2k7Skin span.mce_pagebreak {background-position:0 -40px}
220
  .o2k7Skin span.mce_restoredraft {background-position:-20px -40px}
221
  .o2k7Skin span.mce_spellchecker {background-position:-540px -20px}
222
+ .o2k7Skin span.mce_visualblocks {background-position: -40px -40px}
tiny_mce/themes/advanced/source_editor.htm CHANGED
@@ -4,7 +4,7 @@
4
  <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
5
  <script type="text/javascript" src="js/source_editor.js"></script>
6
  </head>
7
- <body onresize="resizeInputs();" style="display:none; overflow:hidden;">
8
  <form name="source" onsubmit="saveContent();return false;" action="#">
9
  <div style="float: left" class="title"><label for="htmlSource">{#advanced_dlg.code_title}</label></div>
10
 
4
  <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
5
  <script type="text/javascript" src="js/source_editor.js"></script>
6
  </head>
7
+ <body onresize="resizeInputs();" style="display:none; overflow:hidden;" spellcheck="false">
8
  <form name="source" onsubmit="saveContent();return false;" action="#">
9
  <div style="float: left" class="title"><label for="htmlSource">{#advanced_dlg.code_title}</label></div>
10
 
tiny_mce/tiny_mce.js CHANGED
@@ -1 +1 @@
1
- (function(d){var a=/^\s*|\s*$/g,e,c="B".replace(/A(.)|B/,"$1")==="$1";var b={majorVersion:"3",minorVersion:"4.7",releaseDate:"2011-11-03",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=d.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(d.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m<f.length;m++){if(r=f[m].href){if(/^https?:\/\/[^\/]+$/.test(r)){r+="/"}k=r?r.match(/.*\//)[0]:""}}function h(i){if(i.src&&/tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(i.src)){if(/_(src|dev)\.js/g.test(i.src)){s.suffix="_src"}if((j=i.src.indexOf("?"))!=-1){s.query=i.src.substring(j+1)}s.baseURL=i.src.substring(0,i.src.lastIndexOf("/"));if(k&&s.baseURL.indexOf("://")==-1&&s.baseURL.indexOf("/")!==0){s.baseURL=k+s.baseURL}return s.baseURL}return null}f=q.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}l=q.getElementsByTagName("head")[0];if(l){f=l.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}}return},is:function(g,f){if(!f){return g!==e}if(f=="array"&&(g.hasOwnProperty&&g instanceof Array)){return true}return typeof(g)==f},makeMap:function(f,j,h){var g;f=f||[];j=j||",";if(typeof(f)=="string"){f=f.split(j)}h=h||{};g=f.length;while(g--){h[f[g]]={}}return h},each:function(i,f,h){var j,g;if(!i){return 0}h=h||i;if(i.length!==e){for(j=0,g=i.length;j<g;j++){if(f.call(h,i[j],j,i)===false){return 0}}}else{for(j in i){if(i.hasOwnProperty(j)){if(f.call(h,i[j],j,i)===false){return 0}}}}return 1},map:function(g,h){var i=[];b.each(g,function(f){i.push(h(f))});return i},grep:function(g,h){var i=[];b.each(g,function(f){if(!h||h(f)){i.push(f)}});return i},inArray:function(g,h){var j,f;if(g){for(j=0,f=g.length;j<f;j++){if(g[j]===h){return j}}}return -1},extend:function(k,j){var h,g,f=arguments;for(h=1,g=f.length;h<g;h++){j=f[h];b.each(j,function(i,l){if(i!==e){k[l]=i}})}return k},trim:function(f){return(f?""+f:"").replace(a,"")},create:function(o,f,j){var n=this,g,i,k,l,h,m=0;o=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(o);k=o[3].match(/(^|\.)(\w+)$/i)[2];i=n.createNS(o[3].replace(/\.\w+$/,""),j);if(i[k]){return}if(o[2]=="static"){i[k]=f;if(this.onCreate){this.onCreate(o[2],o[3],i[k])}return}if(!f[k]){f[k]=function(){};m=1}i[k]=f[k];n.extend(i[k].prototype,f);if(o[5]){g=n.resolve(o[5]).prototype;l=o[5].match(/\.(\w+)$/i)[1];h=i[k];if(m){i[k]=function(){return g[l].apply(this,arguments)}}else{i[k]=function(){this.parent=g[l];return h.apply(this,arguments)}}i[k].prototype[k]=i[k];n.each(g,function(p,q){i[k].prototype[q]=g[q]});n.each(f,function(p,q){if(g[q]){i[k].prototype[q]=function(){this.parent=g[q];return p.apply(this,arguments)}}else{if(q!=k){i[k].prototype[q]=p}}})}n.each(f["static"],function(p,q){i[k][q]=p});if(this.onCreate){this.onCreate(o[2],o[3],i[k].prototype)}},walk:function(i,h,j,g){g=g||this;if(i){if(j){i=i[j]}b.each(i,function(k,f){if(h.call(g,k,f,j)===false){return false}b.walk(k,h,j,g)})}},createNS:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0;g<j.length;g++){f=j[g];if(!h[f]){h[f]={}}h=h[f]}return h},resolve:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0,f=j.length;g<f;g++){h=h[j[g]];if(!h){break}}return h},addUnload:function(j,i){var h=this;j={func:j,scope:i||this};if(!h.unloads){function g(){var f=h.unloads,l,m;if(f){for(m in f){l=f[m];if(l&&l.func){l.func.call(l.scope,1)}}if(d.detachEvent){d.detachEvent("onbeforeunload",k);d.detachEvent("onunload",g)}else{if(d.removeEventListener){d.removeEventListener("unload",g,false)}}h.unloads=l=f=w=g=0;if(d.CollectGarbage){CollectGarbage()}}}function k(){var l=document;if(l.readyState=="interactive"){function f(){l.detachEvent("onstop",f);if(g){g()}l=0}if(l){l.attachEvent("onstop",f)}d.setTimeout(function(){if(l){l.detachEvent("onstop",f)}},0)}}if(d.attachEvent){d.attachEvent("onunload",g);d.attachEvent("onbeforeunload",k)}else{if(d.addEventListener){d.addEventListener("unload",g,false)}}h.unloads=[j]}else{h.unloads.push(j)}return j},removeUnload:function(i){var g=this.unloads,h=null;b.each(g,function(j,f){if(j&&j.func==i){g.splice(f,1);h=i;return false}});return h},explode:function(f,g){return f?b.map(f.split(g||","),b.trim):f},_addVer:function(g){var f;if(!this.query){return g}f=(g.indexOf("?")==-1?"?":"&")+this.query;if(g.indexOf("#")==-1){return g+f}return g.replace("#",f+"#")},_replace:function(h,f,g){if(c){return g.replace(h,function(){var l=f,j=arguments,k;for(k=0;k<j.length-2;k++){if(j[k]===e){l=l.replace(new RegExp("\\$"+k,"g"),"")}else{l=l.replace(new RegExp("\\$"+k,"g"),j[k])}}return l})}return g.replace(h,f)}};b._init();d.tinymce=d.tinyMCE=b})(window);tinymce.create("tinymce.util.Dispatcher",{scope:null,listeners:null,Dispatcher:function(a){this.scope=a||this;this.listeners=[]},add:function(a,b){this.listeners.push({cb:a,scope:b||this.scope});return a},addToTop:function(a,b){this.listeners.unshift({cb:a,scope:b||this.scope});return a},remove:function(a){var b=this.listeners,c=null;tinymce.each(b,function(e,d){if(a==e.cb){c=a;b.splice(d,1);return false}});return c},dispatch:function(){var f,d=arguments,e,b=this.listeners,g;for(e=0;e<b.length;e++){g=b[e];f=g.cb.apply(g.scope,d);if(f===false){break}}return f}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});if(c=g.base_uri){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host=="mce_host"){f.port=c.port}if(!f.host||f.host=="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var c=this,d;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:c});if((b.host!="mce_host"&&c.host!=b.host&&b.host)||c.port!=b.port||c.protocol!=b.protocol){return b.getURI()}d=c.toRelPath(c.path,b.path);if(b.query){d+="?"+b.query}if(b.anchor){d+="#"+b.anchor}return d},toAbsolute:function(b,c){var b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e<b;e++){if(e>=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length<c.length){for(e=0,b=c.length;e<b;e++){if(e>=g.length||g[e]!=c[e]){f=e+1;break}}}if(f==1){return h}for(e=0,b=g.length-(f-1);e<b;e++){d+="../"}for(e=f-1,b=c.length;e<b;e++){if(e!=f-1){d+="/"+c[e]}else{d+=c[e]}}return d},toAbsPath:function(e,f){var c,b=0,h=[],d,g;d=/\/$/.test(f)?"/":"";e=e.split("/");f=f.split("/");a(e,function(i){if(i){h.push(i)}});e=h;for(c=f.length-1,h=[];c>=0;c--){if(f[c].length==0||f[c]=="."){continue}if(f[c]==".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!=0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i<o.length;i++){v+=(i>0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(i in o){if(o.hasOwnProperty(i)){v+=typeof o[i]!="function"?(v.length>1?","+quote:quote)+i+quote+":"+serialize(o[i],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={DELETE:46,BACKSPACE:8,ENTER:13,TAB:9,SPACEBAR:32,UP:38,DOWN:40}})(tinymce);(function(k){var i=k.VK,j=i.BACKSPACE,h=i.DELETE;function c(m){var o=m.dom,n=m.selection;m.onKeyDown.add(function(q,u){var p,v,s,t,r;r=u.keyCode==h;if(r||u.keyCode==j){u.preventDefault();p=n.getRng();v=o.getParent(p.startContainer,o.isBlock);if(r){v=o.getNext(v,o.isBlock)}if(v){s=v.firstChild;while(s&&s.nodeType==3&&s.nodeValue.length==0){s=s.nextSibling}if(s&&s.nodeName==="SPAN"){t=s.cloneNode(false)}}q.getDoc().execCommand(r?"ForwardDelete":"Delete",false,null);v=o.getParent(p.startContainer,o.isBlock);k.each(o.select("span.Apple-style-span,font.Apple-style-span",v),function(x){var y=n.getBookmark();if(t){o.replace(t.cloneNode(false),x,true)}else{o.remove(x,true)}n.moveToBookmark(y)})}})}function d(m){m.onKeyUp.add(function(n,p){var o=p.keyCode;if(o==h||o==j){if(n.dom.isEmpty(n.getBody())){n.setContent("",{format:"raw"});n.nodeChanged();return}}})}function b(m){m.dom.bind(m.getDoc(),"focusin",function(){m.selection.setRng(m.selection.getRng())})}function e(m){m.onKeyDown.add(function(n,q){if(q.keyCode===j){if(n.selection.isCollapsed()&&n.selection.getRng(true).startOffset===0){var p=n.selection.getNode();var o=p.previousSibling;if(o&&o.nodeName&&o.nodeName.toLowerCase()==="hr"){n.dom.remove(o);k.dom.Event.cancel(q)}}}})}function g(m){if(!Range.prototype.getClientRects){m.onMouseDown.add(function(o,p){if(p.target.nodeName==="HTML"){var n=o.getBody();n.blur();setTimeout(function(){n.focus()},0)}})}}function f(m){m.onClick.add(function(n,o){o=o.target;if(/^(IMG|HR)$/.test(o.nodeName)){n.selection.getSel().setBaseAndExtent(o,0,o,1)}if(o.nodeName=="A"&&n.dom.hasClass(o,"mceItemAnchor")){n.selection.select(o)}n.nodeChanged()})}function l(m){var o,n;m.dom.bind(m.getDoc(),"selectionchange",function(){if(n){clearTimeout(n);n=0}n=window.setTimeout(function(){var p=m.selection.getRng();if(!o||!k.dom.RangeUtils.compareRanges(p,o)){m.nodeChanged();o=p}},50)})}function a(m){document.body.setAttribute("role","application")}k.create("tinymce.util.Quirks",{Quirks:function(m){if(k.isWebKit){c(m);d(m);b(m);f(m);if(k.isIDevice){l(m)}}if(k.isIE){e(m);d(m);a(m)}if(k.isGecko){e(m);g(m)}}})})(tinymce);(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;","&":"&amp;"};d={"&lt;":"<","&gt;":">","&amp;":"&","&quot;":'"',"&apos;":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n<m.length;n+=2){o=String.fromCharCode(parseInt(m[n],p));if(!g[o]){l="&"+m[n+1]+";";q[o]=l;q[l]=o}}return q}}a=e("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);j.html=j.html||{};j.html.Entities={encodeRaw:function(m,l){return m.replace(l?k:b,function(n){return g[n]||n})},encodeAllRaw:function(l){return(""+l).replace(f,function(m){return g[m]||m})},encodeNumeric:function(m,l){return m.replace(l?k:b,function(n){if(n.length>1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g<j.length;g++){a[j[g]]="\uFEFF"+g;a["\uFEFF"+g]=j[g]}function c(n,q,p,i){function o(r){r=parseInt(r).toString(16);return r.length>1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(r){var y={},p,n,v,q,u=d.url_converter,x=d.url_converter_scope||this;function o(C,F){var E,B,A,D;E=y[C+"-top"+F];if(!E){return}B=y[C+"-right"+F];if(E!=B){return}A=y[C+"-bottom"+F];if(B!=A){return}D=y[C+"-left"+F];if(A!=D){return}y[C+F]=D;delete y[C+"-top"+F];delete y[C+"-right"+F];delete y[C+"-bottom"+F];delete y[C+"-left"+F]}function t(B){var C=y[B],A;if(!C||C.indexOf(" ")<0){return}C=C.split(" ");A=C.length;while(A--){if(C[A]!==C[0]){return false}}y[B]=C[0];return true}function z(C,B,A,D){if(!t(B)){return}if(!t(A)){return}if(!t(D)){return}y[C]=y[B]+" "+y[A]+" "+y[D];delete y[B];delete y[A];delete y[D]}function s(A){q=true;return a[A]}function i(B,A){if(q){B=B.replace(/\uFEFF[0-9]/g,function(C){return a[C]})}if(!A){B=B.replace(/\\([\'\";:])/g,"$1")}return B}if(r){r=r.replace(/\\[\"\';:\uFEFF]/g,s).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(A){return A.replace(/[;:]/g,s)});while(p=b.exec(r)){n=p[1].replace(l,"").toLowerCase();v=p[2].replace(l,"");if(n&&v.length>0){if(n==="font-weight"&&v==="700"){v="bold"}else{if(n==="color"||n==="background-color"){v=v.toLowerCase()}}v=v.replace(k,c);v=v.replace(h,function(B,A,E,D,F,C){F=F||C;if(F){F=i(F);return"'"+F.replace(/\'/g,"\\'")+"'"}A=i(A||E||D);if(u){A=u.call(x,A,"style")}return"url('"+A.replace(/\'/g,"\\'")+"')"});y[n]=q?i(v,true):v}b.lastIndex=p.index+p[0].length}o("border","");o("border","-width");o("border","-color");o("border","-style");o("padding","");o("margin","");z("border","border-width","border-style","border-color");if(y.border==="medium none"){delete y.border}}return y},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u<s;u++){t=x[u];v=p[t];if(v!==e&&v.length>0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(m){var h={},j,l,g,f,c={},b,e,d=m.makeMap,k=m.each;function i(o,n){return o.split(n||",")}function a(r,q){var o,p={};function n(s){return s.replace(/[A-Z]+/g,function(t){return n(r[t])})}for(o in r){if(r.hasOwnProperty(o)){r[o]=n(r[o])}}n(q).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(v,t,s,u){s=i(s,"|");p[t]={attributes:d(s),attributesOrder:s,children:d(u,"|",{"#comment":{}})}});return p}l="h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,noscript,menu,isindex,samp,header,footer,article,section,hgroup";l=d(l,",",d(l.toUpperCase()));h=a({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]");j=d("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,autoplay,loop,controls");g=d("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source");f=m.extend(d("td,th,iframe,video,audio,object"),g);b=d("pre,script,style,textarea");e=d("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");m.html.Schema=function(r){var A=this,n={},o={},y=[],q,p;r=r||{};if(r.verify_html===false){r.valid_elements="*[*]"}if(r.valid_styles){q={};k(r.valid_styles,function(C,B){q[B]=m.explode(C)})}p=r.whitespace_elements?d(r.whitespace_elements):b;function z(B){return new RegExp("^"+B.replace(/([?+*])/g,".$1")+"$")}function t(I){var H,D,W,S,X,C,F,R,U,N,V,Z,L,G,T,B,P,E,Y,aa,M,Q,K=/^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,O=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,J=/[*?+]/;if(I){I=i(I);if(n["@"]){P=n["@"].attributes;E=n["@"].attributesOrder}for(H=0,D=I.length;H<D;H++){C=K.exec(I[H]);if(C){T=C[1];N=C[2];B=C[3];U=C[4];L={};G=[];F={attributes:L,attributesOrder:G};if(T==="#"){F.paddEmpty=true}if(T==="-"){F.removeEmpty=true}if(P){for(aa in P){L[aa]=P[aa]}G.push.apply(G,E)}if(U){U=i(U,"|");for(W=0,S=U.length;W<S;W++){C=O.exec(U[W]);if(C){R={};Z=C[1];V=C[2].replace(/::/g,":");T=C[3];Q=C[4];if(Z==="!"){F.attributesRequired=F.attributesRequired||[];F.attributesRequired.push(V);R.required=true}if(Z==="-"){delete L[V];G.splice(m.inArray(G,V),1);continue}if(T){if(T==="="){F.attributesDefault=F.attributesDefault||[];F.attributesDefault.push({name:V,value:Q});R.defaultValue=Q}if(T===":"){F.attributesForced=F.attributesForced||[];F.attributesForced.push({name:V,value:Q});R.forcedValue=Q}if(T==="<"){R.validValues=d(Q,"?")}}if(J.test(V)){F.attributePatterns=F.attributePatterns||[];R.pattern=z(V);F.attributePatterns.push(R)}else{if(!L[V]){G.push(V)}L[V]=R}}}}if(!P&&N=="@"){P=L;E=G}if(B){F.outputName=N;n[B]=F}if(J.test(N)){F.pattern=z(N);y.push(F)}else{n[N]=F}}}}}function v(B){n={};y=[];t(B);k(h,function(D,C){o[C]=D.children})}function s(C){var B=/^(~)?(.+)$/;if(C){k(i(C),function(G){var E=B.exec(G),F=E[1]==="~",H=F?"span":"div",D=E[2];o[D]=o[H];c[D]=H;if(!F){l[D]={}}k(o,function(I,J){if(I[H]){I[D]=I[H]}})})}}function u(C){var B=/^([+\-]?)(\w+)\[([^\]]+)\]$/;if(C){k(i(C),function(G){var F=B.exec(G),D,E;if(F){E=F[1];if(E){D=o[F[2]]}else{D=o[F[2]]={"#comment":{}}}D=o[F[2]];k(i(F[3],"|"),function(H){if(E==="-"){delete D[H]}else{D[H]={}}})}})}}function x(B){var D=n[B],C;if(D){return D}C=y.length;while(C--){D=y[C];if(D.pattern.test(B)){return D}}}if(!r.valid_elements){k(h,function(C,B){n[B]={attributes:C.attributes,attributesOrder:C.attributesOrder};o[B]=C.children});k(i("strong/b,em/i"),function(B){B=i(B,"/");n[B[1]].outputName=B[0]});n.img.attributesDefault=[{name:"alt",value:""}];k(i("ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr"),function(B){n[B].removeEmpty=true});k(i("p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption"),function(B){n[B].paddEmpty=true})}else{v(r.valid_elements)}s(r.custom_elements);u(r.valid_children);t(r.extended_valid_elements);u("+ol[ul|ol],+ul[ul|ol]");if(!x("span")){t("span[!data-mce-type|*]")}if(r.invalid_elements){m.each(m.explode(r.invalid_elements),function(B){if(n[B]){delete n[B]}})}A.children=o;A.styles=q;A.getBoolAttrs=function(){return j};A.getBlockElements=function(){return l};A.getShortEndedElements=function(){return g};A.getSelfClosingElements=function(){return e};A.getNonEmptyElements=function(){return f};A.getWhiteSpaceElements=function(){return p};A.isValidChild=function(B,D){var C=o[B];return !!(C&&C[D])};A.getElementRule=x;A.getCustomElements=function(){return c};A.addValidElements=t;A.setValidElements=v;A.addCustomElements=s;A.addValidChildren=u};m.html.Schema.boolAttrMap=j;m.html.Schema.blockElementsMap=l})(tinymce);(function(a){a.html.SaxParser=function(c,e){var b=this,d=function(){};c=c||{};b.schema=e=e||new a.html.Schema();if(c.fix_self_closing!==false){c.fix_self_closing=true}a.each("comment cdata text start end pi doctype".split(" "),function(f){if(f){b[f]=c[f]||d}});b.parse=function(D){var n=this,g,F=0,H,A,z=[],M,P,B,q,y,r,L,G,N,u,m,k,s,Q,o,O,E,R,K,f,I,l,C,J,h,v=0,j=a.html.Entities.decode,x,p;function t(S){var U,T;U=z.length;while(U--){if(z[U].name===S){break}}if(U>=0){for(T=z.length-1;T>=U;T--){S=z[T];if(S.valid){n.end(S.name)}}z.length=U}}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([^\\s\\/<>]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/)>))","g");C=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;J={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};L=e.getShortEndedElements();I=e.getSelfClosingElements();G=e.getBoolAttrs();u=c.validate;r=c.remove_internals;x=c.fix_self_closing;p=a.isIE;o=/^:/;while(g=l.exec(D)){if(F<g.index){n.text(j(D.substr(F,g.index-F)))}if(H=g[6]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}t(H)}else{if(H=g[7]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}N=H in L;if(x&&I[H]&&z.length>0&&z[z.length-1].name===H){t(H)}if(!u||(m=e.getElementRule(H))){k=true;if(u){O=m.attributes;E=m.attributePatterns}if(Q=g[8]){y=Q.indexOf("data-mce-type")!==-1;if(y&&r){k=false}M=[];M.map={};Q.replace(C,function(T,S,X,W,V){var Y,U;S=S.toLowerCase();X=S in G?S:j(X||W||V||"");if(u&&!y&&S.indexOf("data-")!==0){Y=O[S];if(!Y&&E){U=E.length;while(U--){Y=E[U];if(Y.pattern.test(S)){break}}if(U===-1){Y=null}}if(!Y){return}if(Y.validValues&&!(X in Y.validValues)){return}}M.map[S]=X;M.push({name:S,value:X})})}else{M=[];M.map={}}if(u&&!y){R=m.attributesRequired;K=m.attributesDefault;f=m.attributesForced;if(f){P=f.length;while(P--){s=f[P];q=s.name;h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}if(K){P=K.length;while(P--){s=K[P];q=s.name;if(!(q in M.map)){h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}}if(R){P=R.length;while(P--){if(R[P] in M.map){break}}if(P===-1){k=false}}if(M.map["data-mce-bogus"]){k=false}}if(k){n.start(H,M,N)}}else{k=false}if(A=J[H]){A.lastIndex=F=g.index+g[0].length;if(g=A.exec(D)){if(k){B=D.substr(F,g.index-F)}F=g.index+g[0].length}else{B=D.substr(F);F=D.length}if(k&&B.length>0){n.text(B,true)}if(k){n.end(H)}l.lastIndex=F;continue}if(!N){if(!Q||Q.indexOf("/")!=Q.length-1){z.push({name:H,valid:k})}else{if(k){n.end(H)}}}}else{if(H=g[1]){n.comment(H)}else{if(H=g[2]){n.cdata(H)}else{if(H=g[3]){n.doctype(H)}else{if(H=g[4]){n.pi(H,g[5])}}}}}}F=g.index+g[0].length}if(F<D.length){n.text(j(D.substr(F)))}for(P=z.length-1;P>=0;P--){H=z[P];if(H.valid){n.end(H.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h<f;h++){j=m[h];if(j.name!=="id"){k[k.length]={name:j.name,value:j.value};k.map[j.name]=j.value}}n.attributes=k}n.value=g.value;n.shortEnded=g.shortEnded;return n},wrap:function(g){var f=this;f.parent.insert(g,f);g.append(f);return f},unwrap:function(){var f=this,h,g;for(h=f.firstChild;h;){g=h.next;f.insert(h,f,true);h=g}f.remove()},remove:function(){var f=this,h=f.parent,g=f.next,i=f.prev;if(h){if(h.firstChild===f){h.firstChild=g;if(g){g.prev=null}}else{i.next=g}if(h.lastChild===f){h.lastChild=i;if(i){i.next=null}}else{g.prev=i}f.parent=f.next=f.prev=null}return f},append:function(h){var f=this,g;if(h.parent){h.remove()}g=f.lastChild;if(g){g.next=h;h.prev=g;f.lastChild=h}else{f.lastChild=f.firstChild=h}h.parent=f;return h},insert:function(h,f,i){var g;if(h.parent){h.remove()}g=f.parent||this;if(i){if(f===g.firstChild){g.firstChild=h}else{f.prev.next=h}h.prev=f.prev;h.next=f;f.prev=h}else{if(f===g.lastChild){g.lastChild=h}else{f.next.prev=h}h.next=f.next;h.prev=f;f.next=h}h.parent=g;return h},getAll:function(g){var f=this,h,i=[];for(h=f.firstChild;h;h=a(h,f)){if(h.name===g){i.push(h)}}return i},empty:function(){var g=this,f,h,j;if(g.firstChild){f=[];for(j=g.firstChild;j;j=a(j,g)){f.push(j)}h=f.length;while(h--){j=f[h];j.parent=j.firstChild=j.lastChild=j.next=j.prev=null}}g.firstChild=g.lastChild=null;return g},isEmpty:function(k){var f=this,j=f.firstChild,h,g;if(j){do{if(j.type===1){if(j.attributes.map["data-mce-bogus"]){continue}if(k[j.name]){return false}h=j.attributes.length;while(h--){g=j.attributes[h].name;if(g==="name"||g.indexOf("data-")===0){return false}}}if((j.type===3&&!c.test(j.value))){return false}}while(j=a(j,f))}return true},walk:function(f){return a(this,null,f)}});d.extend(b,{create:function(g,f){var i,h;i=new b(g,e[g]||1);if(f){for(h in f){i.attr(h,f[h])}}return i}});d.html.Node=b})(tinymce);(function(b){var a=b.html.Node;b.html.DomParser=function(g,h){var f=this,e={},d=[],i={},c={};g=g||{};g.validate="validate" in g?g.validate:true;g.root_name=g.root_name||"body";f.schema=h=h||new b.html.Schema();function j(m){var o,p,x,v,z,n,q,l,t,u,k,s,y,r;s=b.makeMap("tr,td,th,tbody,thead,tfoot,table");k=h.getNonEmptyElements();for(o=0;o<m.length;o++){p=m[o];if(!p.parent){continue}v=[p];for(x=p.parent;x&&!h.isValidChild(x.name,p.name)&&!s[x.name];x=x.parent){v.push(x)}if(x&&v.length>1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t<v.length-1;t++){if(h.isValidChild(n.name,v[t].name)){q=f.filterNode(v[t].clone());n.append(q)}else{q=n}for(l=v[t].firstChild;l&&l!=v[t+1];){r=l.next;q.append(l);l=r}n=q}if(!z.isEmpty(k)){x.insert(z,v[0],true);x.insert(p,z)}else{x.insert(p,v[0],true)}x=v[0];if(x.isEmpty(k)||x.firstChild===x.lastChild&&x.firstChild.name==="br"){x.empty().remove()}}else{if(p.parent){if(p.name==="li"){y=p.prev;if(y&&(y.name==="ul"||y.name==="ul")){y.append(p);continue}y=p.next;if(y&&(y.name==="ul"||y.name==="ul")){y.insert(p,y.firstChild,true);continue}p.wrap(f.filterNode(new a("ul",1)));continue}if(h.isValidChild(p.parent.name,"div")&&h.isValidChild("div",p.name)){p.wrap(f.filterNode(new a("div",1)))}else{if(p.name==="style"||p.name==="script"){p.empty().remove()}else{p.unwrap()}}}}}}f.filterNode=function(m){var l,k,n;if(k in e){n=i[k];if(n){n.push(m)}else{i[k]=[m]}}l=d.length;while(l--){k=d[l].name;if(k in m.attributes.map){n=c[k];if(n){n.push(m)}else{c[k]=[m]}}}return m};f.addNodeFilter=function(k,l){b.each(b.explode(k),function(m){var n=e[m];if(!n){e[m]=n=[]}n.push(l)})};f.addAttributeFilter=function(k,l){b.each(b.explode(k),function(m){var n;for(n=0;n<d.length;n++){if(d[n].name===m){d[n].callbacks.push(l);return}}d.push({name:m,callbacks:[l]})})};f.parse=function(v,m){var n,H,A,z,C,B,x,r,E,K,y,o,D,J=[],t,k,s,p,u,q;m=m||{};i={};c={};o=b.extend(b.makeMap("script,style,head,html,body,title,meta,param"),h.getBlockElements());u=h.getNonEmptyElements();p=h.children;y=g.validate;q="forced_root_block" in m?m.forced_root_block:g.forced_root_block;s=h.getWhiteSpaceElements();D=/^[ \t\r\n]+/;t=/[ \t\r\n]+$/;k=/[ \t\r\n]+/g;function F(){var L=H.firstChild,l,M;while(L){l=L.next;if(L.type==3||(L.type==1&&L.name!=="p"&&!o[L.name]&&!L.attr("data-mce-type"))){if(!M){M=I(q,1);H.insert(M,L);M.append(L)}else{M.append(L)}}else{M=null}L=l}}function I(l,L){var M=new a(l,L),N;if(l in e){N=i[l];if(N){N.push(M)}else{i[l]=[M]}}return M}function G(M){var N,l,L;for(N=M.prev;N&&N.type===3;){l=N.value.replace(t,"");if(l.length>0){N.value=l;N=N.prev}else{L=N.prev;N.remove();N=L}}}n=new b.html.SaxParser({validate:y,fix_self_closing:!y,cdata:function(l){A.append(I("#cdata",4)).value=l},text:function(M,l){var L;if(!s[A.name]){M=M.replace(k," ");if(A.lastChild&&o[A.lastChild.name]){M=M.replace(D,"")}}if(M.length!==0){L=I("#text",3);L.raw=!!l;A.append(L).value=M}},comment:function(l){A.append(I("#comment",8)).value=l},pi:function(l,L){A.append(I(l,7)).value=L;G(A)},doctype:function(L){var l;l=A.append(I("#doctype",10));l.value=L;G(A)},start:function(l,T,M){var R,O,N,L,P,U,S,Q;N=y?h.getElementRule(l):{};if(N){R=I(N.outputName||l,1);R.attributes=T;R.shortEnded=M;A.append(R);Q=p[A.name];if(Q&&p[R.name]&&!Q[R.name]){J.push(R)}O=d.length;while(O--){P=d[O].name;if(P in T.map){E=c[P];if(E){E.push(R)}else{c[P]=[R]}}}if(o[l]){G(R)}if(!M){A=R}}},end:function(l){var P,M,O,L,N;M=y?h.getElementRule(l):{};if(M){if(o[l]){if(!s[A.name]){for(P=A.firstChild;P&&P.type===3;){O=P.value.replace(D,"");if(O.length>0){P.value=O;P=P.next}else{L=P.next;P.remove();P=L}}for(P=A.lastChild;P&&P.type===3;){O=P.value.replace(t,"");if(O.length>0){P.value=O;P=P.prev}else{L=P.prev;P.remove();P=L}}}P=A.prev;if(P&&P.type===3){O=P.value.replace(D,"");if(O.length>0){P.value=O}else{P.remove()}}}if(M.removeEmpty||M.paddEmpty){if(A.isEmpty(u)){if(M.paddEmpty){A.empty().append(new a("#text","3")).value="\u00a0"}else{if(!A.attributes.map.name){N=A.parent;A.empty().remove();A=N;return}}}}A=A.parent}}},h);H=A=new a(m.context||g.root_name,11);n.parse(v);if(y&&J.length){if(!m.context){j(J)}else{m.invalid=true}}if(q&&H.name=="body"){F()}if(!m.invalid){for(K in i){E=e[K];z=i[K];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(C=0,B=E.length;C<B;C++){E[C](z,K,m)}}for(C=0,B=d.length;C<B;C++){E=d[C];if(E.name in c){z=c[E.name];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(x=0,r=E.callbacks.length;x<r;x++){E.callbacks[x](z,E.name,m)}}}}return H};if(g.remove_trailing_brs){f.addNodeFilter("br",function(n,m){var r,q=n.length,o,u=h.getBlockElements(),k=h.getNonEmptyElements(),s,p,t;u.body=1;for(r=0;r<q;r++){o=n[r];s=o.parent;if(u[o.parent.name]&&o===s.lastChild){p=o.prev;while(p){t=p.name;if(t!=="span"||p.attr("data-mce-type")!=="bookmark"){if(t!=="br"){break}if(t==="br"){o=null;break}}p=p.prev}if(o){o.remove();if(s.isEmpty(k)){elementRule=h.getElementRule(s.name);if(elementRule){if(elementRule.removeEmpty){s.remove()}else{if(elementRule.paddEmpty){s.empty().append(new b.html.Node("#text",3)).value="\u00a0"}}}}}}}})}}})(tinymce);tinymce.html.Writer=function(e){var c=[],a,b,d,f,g;e=e||{};a=e.indent;b=tinymce.makeMap(e.indent_before||"");d=tinymce.makeMap(e.indent_after||"");f=tinymce.html.Entities.getEncodeFunc(e.entity_encoding||"raw",e.entities);g=e.element_format=="html";return{start:function(m,k,p){var n,j,h,o;if(a&&b[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n<j;n++){h=k[n];c.push(" ",h.name,'="',f(h.value,true),'"')}}if(!p||g){c[c.length]=">"}else{c[c.length]=" />"}if(p&&a&&d[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("</",h,">");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("<![CDATA[",h,"]]>")},comment:function(h){c.push("<!--",h,"-->")},pi:function(h,i){if(i){c.push("<?",h," ",i,"?>")}else{c.push("<?",h,"?>")}if(a){c.push("\n")}},doctype:function(h){c.push("<!DOCTYPE",h,">",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n<m;n++){r=q.attributesOrder[n];if(r in s.map){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}for(n=0,m=s.length;n<m;n++){r=s[n].name;if(!(r in u.map)){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}s=u}e.start(k.name,s,o);if(!o){if((k=k.firstChild)){do{f(k)}while(k=k.next)}e.end(j)}}else{t(k)}}if(h.type==1&&!c.inner){f(h)}else{g[11](h)}return e.getContent()}}})(tinymce);(function(h){var f=h.each,e=h.is,d=h.isWebKit,b=h.isIE,c=h.html.Entities,a=/^([a-z0-9],?)+$/i,g=h.html.Schema.blockElementsMap,i=/^[ \t\r\n]*$/;h.create("tinymce.dom.DOMUtils",{doc:null,root:null,files:null,pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},DOMUtils:function(o,m){var l=this,j,k;l.doc=o;l.win=window;l.files={};l.cssFlicker=false;l.counter=0;l.stdMode=!h.isIE||o.documentMode>=8;l.boxModel=!h.isIE||o.compatMode=="CSS1Compat"||l.stdMode;l.hasOuterHTML="outerHTML" in o.createElement("a");l.settings=m=h.extend({keep_values:false,hex_colors:1},m);l.schema=m.schema;l.styles=new h.html.Styles({url_converter:m.url_converter,url_converter_scope:m.url_converter_scope},m.schema);if(h.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(n){l.cssFlicker=true}}if(b&&m.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(p){o.createElement(p)});for(k in m.schema.getCustomElements()){o.createElement(k)}}h.addUnload(l.destroy,l)},getRoot:function(){var j=this,k=j.settings;return(k&&j.get(k.root_element))||j.doc.body},getViewPort:function(k){var l,j;k=!k?this.win:k;l=k.document;j=this.boxModel?l.documentElement:l.body;return{x:k.pageXOffset||j.scrollLeft,y:k.pageYOffset||j.scrollTop,w:k.innerWidth||j.clientWidth,h:k.innerHeight||j.clientHeight}},getRect:function(m){var l,j=this,k;m=j.get(m);l=j.getPos(m);k=j.getSize(m);return{x:l.x,y:l.y,w:k.w,h:k.h}},getSize:function(m){var k=this,j,l;m=k.get(m);j=k.getStyle(m,"width");l=k.getStyle(m,"height");if(j.indexOf("px")===-1){j=0}if(l.indexOf("px")===-1){l=0}return{w:parseInt(j)||m.offsetWidth||m.clientWidth,h:parseInt(l)||m.offsetHeight||m.clientHeight}},getParent:function(l,k,j){return this.getParents(l,k,j,false)},getParents:function(u,p,l,s){var k=this,j,m=k.settings,q=[];u=k.get(u);s=s===undefined;if(m.strict_root){l=l||k.getRoot()}if(e(p,"string")){j=p;if(p==="*"){p=function(o){return o.nodeType==1}}else{p=function(o){return k.is(o,j)}}}while(u){if(u==l||!u.nodeType||u.nodeType===9){break}if(!p||p(u)){if(s){q.push(u)}else{return u}}u=u.parentNode}return s?q:null},get:function(j){var k;if(j&&this.doc&&typeof(j)=="string"){k=j;j=this.doc.getElementById(j);if(j&&j.id!==k){return this.doc.getElementsByName(k)[1]}}return j},getNext:function(k,j){return this._findSib(k,j,"nextSibling")},getPrev:function(k,j){return this._findSib(k,j,"previousSibling")},select:function(l,k){var j=this;return h.dom.Sizzle(l,j.get(k)||j.get(j.settings.root_element)||j.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(a.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return h.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(m,q,j,l,o){var k=this;return this.run(m,function(s){var r,n;r=e(q,"string")?k.doc.createElement(q):q;k.setAttribs(r,j);if(l){if(l.nodeType){r.appendChild(l)}else{k.setHTML(r,l)}}return !o?s.appendChild(r):r})},create:function(l,j,k){return this.add(this.doc.createElement(l),l,j,k,1)},createHTML:function(r,j,p){var q="",m=this,l;q+="<"+r;for(l in j){if(j.hasOwnProperty(l)){q+=" "+l+'="'+m.encode(j[l])+'"'}}if(typeof(p)!="undefined"){return q+">"+p+"</"+r+">"}return q+" />"},remove:function(j,k){return this.run(j,function(m){var n,l=m.parentNode;if(!l){return null}if(k){while(n=m.firstChild){if(!h.isIE||n.nodeType!==3||n.nodeValue){l.insertBefore(n,m)}else{m.removeChild(n)}}}return l.removeChild(m)})},setStyle:function(m,j,k){var l=this;return l.run(m,function(p){var o,n;o=p.style;j=j.replace(/-(\D)/g,function(r,q){return q.toUpperCase()});if(l.pixelStyles.test(j)&&(h.is(k,"number")||/^[\-0-9\.]+$/.test(k))){k+="px"}switch(j){case"opacity":if(b){o.filter=k===""?"":"alpha(opacity="+(k*100)+")";if(!m.currentStyle||!m.currentStyle.hasLayout){o.display="inline-block"}}o[j]=o["-moz-opacity"]=o["-khtml-opacity"]=k||"";break;case"float":b?o.styleFloat=k:o.cssFloat=k;break;default:o[j]=k||""}if(l.settings.update_styles){l.setAttrib(p,"data-mce-style")}})},getStyle:function(m,j,l){m=this.get(m);if(!m){return}if(this.doc.defaultView&&l){j=j.replace(/[A-Z]/g,function(n){return"-"+n});try{return this.doc.defaultView.getComputedStyle(m,null).getPropertyValue(j)}catch(k){return null}}j=j.replace(/-(\D)/g,function(o,n){return n.toUpperCase()});if(j=="float"){j=b?"styleFloat":"cssFloat"}if(m.currentStyle&&l){return m.currentStyle[j]}return m.style?m.style[j]:undefined},setStyles:function(m,n){var k=this,l=k.settings,j;j=l.update_styles;l.update_styles=0;f(n,function(o,p){k.setStyle(m,p,o)});l.update_styles=j;if(l.update_styles){k.setAttrib(m,l.cssText)}},removeAllAttribs:function(j){return this.run(j,function(m){var l,k=m.attributes;for(l=k.length-1;l>=0;l--){m.removeAttributeNode(k.item(l))}})},setAttrib:function(l,m,j){var k=this;if(!l||!m){return}if(k.settings.strict){m=m.toLowerCase()}return this.run(l,function(o){var n=k.settings;if(j!==null){switch(m){case"style":if(!e(j,"string")){f(j,function(p,q){k.setStyle(o,q,p)});return}if(n.keep_values){if(j&&!k._isRes(j)){o.setAttribute("data-mce-style",j,2)}else{o.removeAttribute("data-mce-style",2)}}o.style.cssText=j;break;case"class":o.className=j||"";break;case"src":case"href":if(n.keep_values){if(n.url_converter){j=n.url_converter.call(n.url_converter_scope||k,j,m,o)}k.setAttrib(o,"data-mce-"+m,j,2)}break;case"shape":o.setAttribute("data-mce-style",j);break}}if(e(j)&&j!==null&&j.length!==0){o.setAttribute(m,""+j,2)}else{o.removeAttribute(m,2)}})},setAttribs:function(k,l){var j=this;return this.run(k,function(m){f(l,function(o,p){j.setAttrib(m,p,o)})})},getAttrib:function(o,p,l){var j,k=this,m;o=k.get(o);if(!o||o.nodeType!==1){return l===m?false:l}if(!e(l)){l=""}if(/^(src|href|style|coords|shape)$/.test(p)){j=o.getAttribute("data-mce-"+p);if(j){return j}}if(b&&k.props[p]){j=o[k.props[p]];j=j&&j.nodeValue?j.nodeValue:j}if(!j){j=o.getAttribute(p,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(p)){if(o[k.props[p]]===true&&j===""){return p}return j?p:""}if(o.nodeName==="FORM"&&o.getAttributeNode(p)){return o.getAttributeNode(p).nodeValue}if(p==="style"){j=j||o.style.cssText;if(j){j=k.serializeStyle(k.parseStyle(j),o.nodeName);if(k.settings.keep_values&&!k._isRes(j)){o.setAttribute("data-mce-style",j)}}}if(d&&p==="class"&&j){j=j.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(p){case"rowspan":case"colspan":if(j===1){j=""}break;case"size":if(j==="+0"||j===20||j===0){j=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(j===0){j=""}break;case"hspace":if(j===-1){j=""}break;case"maxlength":case"tabindex":if(j===32768||j===2147483647||j==="32768"){j=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(j===65535){return p}return l;case"shape":j=j.toLowerCase();break;default:if(p.indexOf("on")===0&&j){j=h._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+j)}}}return(j!==m&&j!==null&&j!=="")?""+j:l},getPos:function(s,m){var k=this,j=0,q=0,o,p=k.doc,l;s=k.get(s);m=m||p.body;if(s){if(s.getBoundingClientRect){s=s.getBoundingClientRect();o=k.boxModel?p.documentElement:p.body;j=s.left+(p.documentElement.scrollLeft||p.body.scrollLeft)-o.clientTop;q=s.top+(p.documentElement.scrollTop||p.body.scrollTop)-o.clientLeft;return{x:j,y:q}}l=s;while(l&&l!=m&&l.nodeType){j+=l.offsetLeft||0;q+=l.offsetTop||0;l=l.offsetParent}l=s.parentNode;while(l&&l!=m&&l.nodeType){j-=l.scrollLeft||0;q-=l.scrollTop||0;l=l.parentNode}}return{x:j,y:q}},parseStyle:function(j){return this.styles.parse(j)},serializeStyle:function(k,j){return this.styles.serialize(k,j)},loadCSS:function(j){var l=this,m=l.doc,k;if(!j){j=""}k=l.select("head")[0];f(j.split(","),function(n){var o;if(l.files[n]){return}l.files[n]=true;o=l.create("link",{rel:"stylesheet",href:h._addVer(n)});if(b&&m.documentMode&&m.recalc){o.onload=function(){if(m.recalc){m.recalc()}o.onload=null}}k.appendChild(o)})},addClass:function(j,k){return this.run(j,function(l){var m;if(!k){return 0}if(this.hasClass(l,k)){return l.className}m=this.removeClass(l,k);return l.className=(m!=""?(m+" "):"")+k})},removeClass:function(l,m){var j=this,k;return j.run(l,function(o){var n;if(j.hasClass(o,m)){if(!k){k=new RegExp("(^|\\s+)"+m+"(\\s+|$)","g")}n=o.className.replace(k," ");n=h.trim(n!=" "?n:"");o.className=n;if(!n){o.removeAttribute("class");o.removeAttribute("className")}return n}return o.className})},hasClass:function(k,j){k=this.get(k);if(!k||!j){return false}return(" "+k.className+" ").indexOf(" "+j+" ")!==-1},show:function(j){return this.setStyle(j,"display","block")},hide:function(j){return this.setStyle(j,"display","none")},isHidden:function(j){j=this.get(j);return !j||j.style.display=="none"||this.getStyle(j,"display")=="none"},uniqueId:function(j){return(!j?"mce_":j)+(this.counter++)},setHTML:function(l,k){var j=this;return j.run(l,function(n){if(b){while(n.firstChild){n.removeChild(n.firstChild)}try{n.innerHTML="<br />"+k;n.removeChild(n.firstChild)}catch(m){n=j.create("div");n.innerHTML="<br />"+k;f(n.childNodes,function(p,o){if(o){n.appendChild(p)}})}}else{n.innerHTML=k}return k})},getOuterHTML:function(l){var k,j=this;l=j.get(l);if(!l){return null}if(l.nodeType===1&&j.hasOuterHTML){return l.outerHTML}k=(l.ownerDocument||j.doc).createElement("body");k.appendChild(l.cloneNode(true));return k.innerHTML},setOuterHTML:function(m,k,n){var j=this;function l(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){j.insertAfter(s.cloneNode(true),p);s=s.previousSibling}j.remove(p)}return this.run(m,function(p){p=j.get(p);if(p.nodeType==1){n=n||p.ownerDocument||j.doc;if(b){try{if(b&&p.nodeType==1){p.outerHTML=k}else{l(p,k,n)}}catch(o){l(p,k,n)}}else{l(p,k,n)}}})},decode:c.decode,encode:c.encodeAllRaw,insertAfter:function(j,k){k=this.get(k);return this.run(j,function(m){var l,n;l=k.parentNode;n=k.nextSibling;if(n){l.insertBefore(m,n)}else{l.appendChild(m)}return m})},isBlock:function(k){var j=k.nodeType;if(j){return !!(j===1&&g[k.nodeName])}return !!g[k]},replace:function(p,m,j){var l=this;if(e(m,"array")){p=p.cloneNode(true)}return l.run(m,function(k){if(j){f(h.grep(k.childNodes),function(n){p.appendChild(n)})}return k.parentNode.replaceChild(p,k)})},rename:function(m,j){var l=this,k;if(m.nodeName!=j.toUpperCase()){k=l.create(j);f(l.getAttribs(m),function(n){l.setAttrib(k,n.nodeName,l.getAttrib(m,n.nodeName))});l.replace(k,m,1)}return k||m},findCommonAncestor:function(l,j){var m=l,k;while(m){k=j;while(k&&m!=k){k=k.parentNode}if(m==k){break}m=m.parentNode}if(!m&&l.ownerDocument){return l.ownerDocument.documentElement}return m},toHex:function(j){var l=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(j);function k(m){m=parseInt(m).toString(16);return m.length>1?m:"0"+m}if(l){j="#"+k(l[1])+k(l[2])+k(l[3]);return j}return j},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(r){f(r.imports,function(s){q(s)});f(r.cssRules||r.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){f(s.selectorText.split(","),function(t){t=t.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(t)||!/\.[\w\-]+$/.test(t)){return}l=t;t=h._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",t);if(p&&!(t=p(t,l))){return}if(!o[t]){j.push({"class":t});o[t]=1}})}break;case 3:q(s.styleSheet);break}})}try{f(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(m,l,k){var j=this,n;if(j.doc&&typeof(m)==="string"){m=j.get(m)}if(!m){return false}k=k||this;if(!m.nodeType&&(m.length||m.length===0)){n=[];f(m,function(p,o){if(p){if(typeof(p)=="string"){p=j.doc.getElementById(p)}n.push(l.call(k,p,o))}});return n}return l.call(k,m)},getAttribs:function(k){var j;k=this.get(k);if(!k){return[]}if(b){j=[];if(k.nodeName=="OBJECT"){return k.attributes}if(k.nodeName==="OPTION"&&this.getAttrib(k,"selected")){j.push({specified:1,nodeName:"selected"})}k.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(l){j.push({specified:1,nodeName:l})});return j}return k.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p;m=m.firstChild;if(m){j=new h.dom.TreeWalker(m);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){p=m.parentNode;if(l==="br"&&r.isBlock(p)&&p.firstChild===m&&p.lastChild===m){continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if((q===3&&!i.test(m.nodeValue))){return false}}while(m=j.next())}return true},destroy:function(k){var j=this;if(j.events){j.events.destroy()}j.win=j.doc=j.root=j.events=null;if(!k){h.removeUnload(j.destroy)}},createRng:function(){var j=this.doc;return j.createRange?j.createRange():new h.dom.Range(this)},nodeIndex:function(n,o){var j=0,l,m,k;if(n){for(l=n.nodeType,n=n.previousSibling,m=n;n;n=n.previousSibling){k=n.nodeType;if(o&&k==3){if(k==l||!n.nodeValue.length){continue}}j++;l=k}}return j},split:function(n,m,q){var s=this,j=s.createRng(),o,l,p;function k(v){var t,r=v.childNodes,u=v.nodeType;if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=r.length-1;t>=0;t--){k(r[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){if(!s.isBlock(v.parentNode)||h.trim(v.nodeValue).length>0){return}}else{if(u==1){r=v.childNodes;if(r.length==1&&r[0]&&r[0].nodeType==1&&r[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(r[0],v)}if(r.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}s.remove(v)}return v}if(n&&m){j.setStart(n.parentNode,s.nodeIndex(n));j.setEnd(m.parentNode,s.nodeIndex(m));o=j.extractContents();j=s.createRng();j.setStart(m.parentNode,s.nodeIndex(m)+1);j.setEnd(n.parentNode,s.nodeIndex(n)+1);l=j.extractContents();p=n.parentNode;p.insertBefore(k(o),n);if(q){p.replaceChild(q,m)}else{p.insertBefore(m,n)}p.insertBefore(k(l),n);s.remove(n);return q||m}},bind:function(n,j,m,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.add(n,j,m,l||this)},unbind:function(m,j,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.remove(m,j,l)},_findSib:function(m,j,k){var l=this,n=j;if(m){if(e(n,"string")){n=function(o){return l.is(o,j)}}for(m=m[k];m;m=m[k]){if(n(m)){return m}}}return null},_isRes:function(j){return/^(top|left|bottom|right|width|height)/i.test(j)||/;\s*(top|left|bottom|right|width|height)/i.test(j)}});h.DOM=new h.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var N=this,e=c.doc,S=0,E=1,j=2,D=true,R=false,U="startOffset",h="startContainer",P="endContainer",z="endOffset",k=tinymce.extend,n=c.nodeIndex;k(N,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:D,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:I,setEndBefore:J,setEndAfter:u,collapse:A,selectNode:x,selectNodeContents:F,compareBoundaryPoints:v,deleteContents:p,extractContents:H,cloneContents:d,insertNode:C,surroundContents:M,cloneRange:K});function q(V,t){B(D,V,t)}function s(V,t){B(R,V,t)}function g(t){q(t.parentNode,n(t))}function I(t){q(t.parentNode,n(t)+1)}function J(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function A(t){if(t){N[P]=N[h];N[z]=N[U]}else{N[h]=N[P];N[U]=N[z]}N.collapsed=D}function x(t){g(t);u(t)}function F(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Y,t){var ab=N[h],W=N[U],aa=N[P],V=N[z],Z=t.startContainer,ad=t.startOffset,X=t.endContainer,ac=t.endOffset;if(Y===0){return G(ab,W,Z,ad)}if(Y===1){return G(aa,V,Z,ad)}if(Y===2){return G(aa,V,X,ac)}if(Y===3){return G(ab,W,X,ac)}}function p(){m(j)}function H(){return m(S)}function d(){return m(E)}function C(Y){var V=this[h],t=this[U],X,W;if((V.nodeType===3||V.nodeType===4)&&V.nodeValue){if(!t){V.parentNode.insertBefore(Y,V)}else{if(t>=V.nodeValue.length){c.insertAfter(Y,V)}else{X=V.splitText(t);V.parentNode.insertBefore(Y,X)}}}else{if(V.childNodes.length>0){W=V.childNodes[t]}if(W){V.insertBefore(Y,W)}else{V.appendChild(Y)}}}function M(V){var t=N.extractContents();N.insertNode(V);V.appendChild(t);N.selectNode(V)}function K(){return k(new b(c),{startContainer:N[h],startOffset:N[U],endContainer:N[P],endOffset:N[z],collapsed:N.collapsed,commonAncestorContainer:N.commonAncestorContainer})}function O(t,V){var W;if(t.nodeType==3){return t}if(V<0){return t}W=t.firstChild;while(W&&V>0){--V;W=W.nextSibling}if(W){return W}return t}function l(){return(N[h]==N[P]&&N[U]==N[z])}function G(X,Z,V,Y){var aa,W,t,ab,ad,ac;if(X==V){if(Z==Y){return 0}if(Z<Y){return -1}return 1}aa=V;while(aa&&aa.parentNode!=X){aa=aa.parentNode}if(aa){W=0;t=X.firstChild;while(t!=aa&&W<Z){W++;t=t.nextSibling}if(Z<=W){return -1}return 1}aa=X;while(aa&&aa.parentNode!=V){aa=aa.parentNode}if(aa){W=0;t=V.firstChild;while(t!=aa&&W<Y){W++;t=t.nextSibling}if(W<Y){return -1}return 1}ab=c.findCommonAncestor(X,V);ad=X;while(ad&&ad.parentNode!=ab){ad=ad.parentNode}if(!ad){ad=ab}ac=V;while(ac&&ac.parentNode!=ab){ac=ac.parentNode}if(!ac){ac=ab}if(ad==ac){return 0}t=ab.firstChild;while(t){if(t==ad){return -1}if(t==ac){return 1}t=t.nextSibling}}function B(V,Y,X){var t,W;if(V){N[h]=Y;N[U]=X}else{N[P]=Y;N[z]=X}t=N[P];while(t.parentNode){t=t.parentNode}W=N[h];while(W.parentNode){W=W.parentNode}if(W==t){if(G(N[h],N[U],N[P],N[z])>0){N.collapse(V)}}else{N.collapse(V)}N.collapsed=l();N.commonAncestorContainer=c.findCommonAncestor(N[h],N[P])}function m(ab){var aa,X=0,ad=0,V,Z,W,Y,t,ac;if(N[h]==N[P]){return f(ab)}for(aa=N[P],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[h]){return r(aa,ab)}++X}for(aa=N[h],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[P]){return T(aa,ab)}++ad}Z=ad-X;W=N[h];while(Z>0){W=W.parentNode;Z--}Y=N[P];while(Z<0){Y=Y.parentNode;Z++}for(t=W.parentNode,ac=Y.parentNode;t!=ac;t=t.parentNode,ac=ac.parentNode){W=t;Y=ac}return o(W,Y,ab)}function f(Z){var ab,Y,X,aa,t,W,V;if(Z!=j){ab=e.createDocumentFragment()}if(N[U]==N[z]){return ab}if(N[h].nodeType==3){Y=N[h].nodeValue;X=Y.substring(N[U],N[z]);if(Z!=E){N[h].deleteData(N[U],N[z]-N[U]);N.collapse(D)}if(Z==j){return}ab.appendChild(e.createTextNode(X));return ab}aa=O(N[h],N[U]);t=N[z]-N[U];while(t>0){W=aa.nextSibling;V=y(aa,Z);if(ab){ab.appendChild(V)}--t;aa=W}if(Z!=E){N.collapse(D)}return ab}function r(ab,Y){var aa,Z,V,t,X,W;if(Y!=j){aa=e.createDocumentFragment()}Z=i(ab,Y);if(aa){aa.appendChild(Z)}V=n(ab);t=V-N[U];if(t<=0){if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}Z=ab.previousSibling;while(t>0){X=Z.previousSibling;W=y(Z,Y);if(aa){aa.insertBefore(W,aa.firstChild)}--t;Z=X}if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}function T(Z,Y){var ab,V,aa,t,X,W;if(Y!=j){ab=e.createDocumentFragment()}aa=Q(Z,Y);if(ab){ab.appendChild(aa)}V=n(Z);++V;t=N[z]-V;aa=Z.nextSibling;while(t>0){X=aa.nextSibling;W=y(aa,Y);if(ab){ab.appendChild(W)}--t;aa=X}if(Y!=E){N.setStartAfter(Z);N.collapse(D)}return ab}function o(Z,t,ac){var W,ae,Y,aa,ab,V,ad,X;if(ac!=j){ae=e.createDocumentFragment()}W=Q(Z,ac);if(ae){ae.appendChild(W)}Y=Z.parentNode;aa=n(Z);ab=n(t);++aa;V=ab-aa;ad=Z.nextSibling;while(V>0){X=ad.nextSibling;W=y(ad,ac);if(ae){ae.appendChild(W)}ad=X;--V}W=i(t,ac);if(ae){ae.appendChild(W)}if(ac!=E){N.setStartAfter(Z);N.collapse(D)}return ae}function i(aa,ab){var W=O(N[P],N[z]-1),ac,Z,Y,t,V,X=W!=N[P];if(W==aa){return L(W,X,R,ab)}ac=W.parentNode;Z=L(ac,R,R,ab);while(ac){while(W){Y=W.previousSibling;t=L(W,X,R,ab);if(ab!=j){Z.insertBefore(t,Z.firstChild)}X=D;W=Y}if(ac==aa){return Z}W=ac.previousSibling;ac=ac.parentNode;V=L(ac,R,R,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function Q(aa,ab){var X=O(N[h],N[U]),Y=X!=N[h],ac,Z,W,t,V;if(X==aa){return L(X,Y,D,ab)}ac=X.parentNode;Z=L(ac,R,D,ab);while(ac){while(X){W=X.nextSibling;t=L(X,Y,D,ab);if(ab!=j){Z.appendChild(t)}Y=D;X=W}if(ac==aa){return Z}X=ac.nextSibling;ac=ac.parentNode;V=L(ac,R,D,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function L(t,Y,ab,ac){var X,W,Z,V,aa;if(Y){return y(t,ac)}if(t.nodeType==3){X=t.nodeValue;if(ab){V=N[U];W=X.substring(V);Z=X.substring(0,V)}else{V=N[z];W=X.substring(0,V);Z=X.substring(V)}if(ac!=E){t.nodeValue=Z}if(ac==j){return}aa=t.cloneNode(R);aa.nodeValue=W;return aa}if(ac==j){return}return t.cloneNode(R)}function y(V,t){if(t!=j){return t==E?V.cloneNode(D):V}V.parentNode.removeChild(V)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}k.setEndPoint(j?"EndToStart":"EndToEnd",i);if(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)>0){k=i.duplicate();k.collapse(j);o=-1;while(s==k.parentElement()){if(k.move("character",-1)==0){break}o++}}o=o||k.text.replace("\r\n"," ").length}else{k.collapse(true);k.setEndPoint(j?"StartToStart":"StartToEnd",i);o=k.text.replace("\r\n"," ").length}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var u,t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{t=r.createTextNode("\uFEFF");u.appendChild(t);x.moveToElementText(t.parentNode);x.collapse(c)}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1&&p==q-1){if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var p=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,j=0,d=Object.prototype.toString,o=false,i=true;[0,0].sort(function(){i=false;return 0});var b=function(v,e,z,A){z=z||[];e=e||document;var C=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!v||typeof v!=="string"){return z}var x=[],s,E,H,r,u=true,t=b.isXML(e),B=v,D,G,F,y;do{p.exec("");s=p.exec(B);if(s){B=s[3];x.push(s[1]);if(s[2]){r=s[3];break}}}while(s);if(x.length>1&&k.exec(v)){if(x.length===2&&f.relative[x[0]]){E=h(x[0]+x[1],e)}else{E=f.relative[x[0]]?[e]:b(x.shift(),e);while(x.length){v=x.shift();if(f.relative[v]){v+=x.shift()}E=h(v,E)}}}else{if(!A&&x.length>1&&e.nodeType===9&&!t&&f.match.ID.test(x[0])&&!f.match.ID.test(x[x.length-1])){D=b.find(x.shift(),e,t);e=D.expr?b.filter(D.expr,D.set)[0]:D.set[0]}if(e){D=A?{expr:x.pop(),set:a(A)}:b.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&e.parentNode?e.parentNode:e,t);E=D.expr?b.filter(D.expr,D.set):D.set;if(x.length>0){H=a(E)}else{u=false}while(x.length){G=x.pop();F=G;if(!f.relative[G]){G=""}else{F=x.pop()}if(F==null){F=e}f.relative[G](H,F,t)}}else{H=x=[]}}if(!H){H=E}if(!H){b.error(G||v)}if(d.call(H)==="[object Array]"){if(!u){z.push.apply(z,H)}else{if(e&&e.nodeType===1){for(y=0;H[y]!=null;y++){if(H[y]&&(H[y]===true||H[y].nodeType===1&&b.contains(e,H[y]))){z.push(E[y])}}}else{for(y=0;H[y]!=null;y++){if(H[y]&&H[y].nodeType===1){z.push(E[y])}}}}}else{a(H,z)}if(r){b(r,C,z,A);b.uniqueSort(z)}return z};b.uniqueSort=function(r){if(c){o=i;r.sort(c);if(o){for(var e=1;e<r.length;e++){if(r[e]===r[e-1]){r.splice(e--,1)}}}}return r};b.matches=function(e,r){return b(e,null,null,r)};b.find=function(y,e,z){var x;if(!y){return[]}for(var t=0,s=f.order.length;t<s;t++){var v=f.order[t],u;if((u=f.leftMatch[v].exec(y))){var r=u[1];u.splice(1,1);if(r.substr(r.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");x=f.find[v](u,e,z);if(x!=null){y=y.replace(f.match[v],"");break}}}}if(!x){x=e.getElementsByTagName("*")}return{set:x,expr:y}};b.filter=function(C,B,F,u){var s=C,H=[],z=B,x,e,y=B&&B[0]&&b.isXML(B[0]);while(C&&B.length){for(var A in f.filter){if((x=f.leftMatch[A].exec(C))!=null&&x[2]){var r=f.filter[A],G,E,t=x[1];e=false;x.splice(1,1);if(t.substr(t.length-1)==="\\"){continue}if(z===H){H=[]}if(f.preFilter[A]){x=f.preFilter[A](x,z,F,H,u,y);if(!x){e=G=true}else{if(x===true){continue}}}if(x){for(var v=0;(E=z[v])!=null;v++){if(E){G=r(E,x,v,z);var D=u^!!G;if(F&&G!=null){if(D){e=true}else{z[v]=false}}else{if(D){H.push(E);e=true}}}}}if(G!==undefined){if(!F){z=H}C=C.replace(f.match[A],"");if(!e){return[]}break}}}if(C===s){if(e==null){b.error(C)}else{break}}s=C}return z};b.error=function(e){throw"Syntax error, unrecognized expression: "+e};var f=b.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(x,r){var t=typeof r==="string",v=t&&!/\W/.test(r),y=t&&!v;if(v){r=r.toLowerCase()}for(var s=0,e=x.length,u;s<e;s++){if((u=x[s])){while((u=u.previousSibling)&&u.nodeType!==1){}x[s]=y||u&&u.nodeName.toLowerCase()===r?u||false:u===r}}if(y){b.filter(r,x,true)}},">":function(x,r){var u=typeof r==="string",v,s=0,e=x.length;if(u&&!/\W/.test(r)){r=r.toLowerCase();for(;s<e;s++){v=x[s];if(v){var t=v.parentNode;x[s]=t.nodeName.toLowerCase()===r?t:false}}}else{for(;s<e;s++){v=x[s];if(v){x[s]=u?v.parentNode:v.parentNode===r}}if(u){b.filter(r,x,true)}}},"":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("parentNode",r,s,t,u,v)},"~":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("previousSibling",r,s,t,u,v)}},find:{ID:function(r,s,t){if(typeof s.getElementById!=="undefined"&&!t){var e=s.getElementById(r[1]);return e?[e]:[]}},NAME:function(s,v){if(typeof v.getElementsByName!=="undefined"){var r=[],u=v.getElementsByName(s[1]);for(var t=0,e=u.length;t<e;t++){if(u[t].getAttribute("name")===s[1]){r.push(u[t])}}return r.length===0?null:r}},TAG:function(e,r){return r.getElementsByTagName(e[1])}},preFilter:{CLASS:function(t,r,s,e,x,y){t=" "+t[1].replace(/\\/g,"")+" ";if(y){return t}for(var u=0,v;(v=r[u])!=null;u++){if(v){if(x^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(t)>=0)){if(!s){e.push(v)}}else{if(s){r[u]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(r,e){return r[1].toLowerCase()},CHILD:function(e){if(e[1]==="nth"){var r=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(r[1]+(r[2]||1))-0;e[3]=r[3]-0}e[0]=j++;return e},ATTR:function(u,r,s,e,v,x){var t=u[1].replace(/\\/g,"");if(!x&&f.attrMap[t]){u[1]=f.attrMap[t]}if(u[2]==="~="){u[4]=" "+u[4]+" "}return u},PSEUDO:function(u,r,s,e,v){if(u[1]==="not"){if((p.exec(u[3])||"").length>1||/^\w/.test(u[3])){u[3]=b(u[3],null,null,r)}else{var t=b.filter(u[3],r,s,true^v);if(!s){e.push.apply(e,t)}return false}}else{if(f.match.POS.test(u[0])||f.match.CHILD.test(u[0])){return true}}return u},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(s,r,e){return !!b(e[3],s).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toLowerCase()==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)}},setFilters:{first:function(r,e){return e===0},last:function(s,r,e,t){return r===t.length-1},even:function(r,e){return e%2===0},odd:function(r,e){return e%2===1},lt:function(s,r,e){return r<e[3]-0},gt:function(s,r,e){return r>e[3]-0},nth:function(s,r,e){return e[3]-0===r},eq:function(s,r,e){return e[3]-0===r}},filter:{PSEUDO:function(s,y,x,z){var e=y[1],r=f.filters[e];if(r){return r(s,x,y,z)}else{if(e==="contains"){return(s.textContent||s.innerText||b.getText([s])||"").indexOf(y[3])>=0}else{if(e==="not"){var t=y[3];for(var v=0,u=t.length;v<u;v++){if(t[v]===s){return false}}return true}else{b.error("Syntax error, unrecognized expression: "+e)}}}},CHILD:function(e,t){var x=t[1],r=e;switch(x){case"only":case"first":while((r=r.previousSibling)){if(r.nodeType===1){return false}}if(x==="first"){return true}r=e;case"last":while((r=r.nextSibling)){if(r.nodeType===1){return false}}return true;case"nth":var s=t[2],A=t[3];if(s===1&&A===0){return true}var v=t[0],z=e.parentNode;if(z&&(z.sizcache!==v||!e.nodeIndex)){var u=0;for(r=z.firstChild;r;r=r.nextSibling){if(r.nodeType===1){r.nodeIndex=++u}}z.sizcache=v}var y=e.nodeIndex-A;if(s===0){return y===0}else{return(y%s===0&&y/s>=0)}}},ID:function(r,e){return r.nodeType===1&&r.getAttribute("id")===e},TAG:function(r,e){return(e==="*"&&r.nodeType===1)||r.nodeName.toLowerCase()===e},CLASS:function(r,e){return(" "+(r.className||r.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(v,t){var s=t[1],e=f.attrHandle[s]?f.attrHandle[s](v):v[s]!=null?v[s]:v.getAttribute(s),x=e+"",u=t[2],r=t[4];return e==null?u==="!=":u==="="?x===r:u==="*="?x.indexOf(r)>=0:u==="~="?(" "+x+" ").indexOf(r)>=0:!r?x&&e!==false:u==="!="?x!==r:u==="^="?x.indexOf(r)===0:u==="$="?x.substr(x.length-r.length)===r:u==="|="?x===r||x.substr(0,r.length+1)===r+"-":false},POS:function(u,r,s,v){var e=r[2],t=f.setFilters[e];if(t){return t(u,s,r,v)}}}};var k=f.match.POS,g=function(r,e){return"\\"+(e-0+1)};for(var m in f.match){f.match[m]=new RegExp(f.match[m].source+(/(?![^\[]*\])(?![^\(]*\))/.source));f.leftMatch[m]=new RegExp(/(^(?:.|\r|\n)*?)/.source+f.match[m].source.replace(/\\(\d+)/g,g))}var a=function(r,e){r=Array.prototype.slice.call(r,0);if(e){e.push.apply(e,r);return e}return r};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(l){a=function(u,t){var r=t||[],s=0;if(d.call(u)==="[object Array]"){Array.prototype.push.apply(r,u)}else{if(typeof u.length==="number"){for(var e=u.length;s<e;s++){r.push(u[s])}}else{for(;u[s];s++){r.push(u[s])}}}return r}}var c;if(document.documentElement.compareDocumentPosition){c=function(r,e){if(!r.compareDocumentPosition||!e.compareDocumentPosition){if(r==e){o=true}return r.compareDocumentPosition?-1:1}var s=r.compareDocumentPosition(e)&4?-1:r===e?0:1;if(s===0){o=true}return s}}else{if("sourceIndex" in document.documentElement){c=function(r,e){if(!r.sourceIndex||!e.sourceIndex){if(r==e){o=true}return r.sourceIndex?-1:1}var s=r.sourceIndex-e.sourceIndex;if(s===0){o=true}return s}}else{if(document.createRange){c=function(t,r){if(!t.ownerDocument||!r.ownerDocument){if(t==r){o=true}return t.ownerDocument?-1:1}var s=t.ownerDocument.createRange(),e=r.ownerDocument.createRange();s.setStart(t,0);s.setEnd(t,0);e.setStart(r,0);e.setEnd(r,0);var u=s.compareBoundaryPoints(Range.START_TO_END,e);if(u===0){o=true}return u}}}}b.getText=function(e){var r="",t;for(var s=0;e[s];s++){t=e[s];if(t.nodeType===3||t.nodeType===4){r+=t.nodeValue}else{if(t.nodeType!==8){r+=b.getText(t.childNodes)}}}return r};(function(){var r=document.createElement("div"),s="script"+(new Date()).getTime();r.innerHTML="<a name='"+s+"'/>";var e=document.documentElement;e.insertBefore(r,e.firstChild);if(document.getElementById(s)){f.find.ID=function(u,v,x){if(typeof v.getElementById!=="undefined"&&!x){var t=v.getElementById(u[1]);return t?t.id===u[1]||typeof t.getAttributeNode!=="undefined"&&t.getAttributeNode("id").nodeValue===u[1]?[t]:undefined:[]}};f.filter.ID=function(v,t){var u=typeof v.getAttributeNode!=="undefined"&&v.getAttributeNode("id");return v.nodeType===1&&u&&u.nodeValue===t}}e.removeChild(r);e=r=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){f.find.TAG=function(r,v){var u=v.getElementsByTagName(r[1]);if(r[1]==="*"){var t=[];for(var s=0;u[s];s++){if(u[s].nodeType===1){t.push(u[s])}}u=t}return u}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){f.attrHandle.href=function(r){return r.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=b,s=document.createElement("div");s.innerHTML="<p class='TEST'></p>";if(s.querySelectorAll&&s.querySelectorAll(".TEST").length===0){return}b=function(x,v,t,u){v=v||document;if(!u&&v.nodeType===9&&!b.isXML(v)){try{return a(v.querySelectorAll(x),t)}catch(y){}}return e(x,v,t,u)};for(var r in e){b[r]=e[r]}s=null})()}(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}f.order.splice(1,0,"CLASS");f.find.CLASS=function(r,s,t){if(typeof s.getElementsByClassName!=="undefined"&&!t){return s.getElementsByClassName(r[1])}};e=null})();function n(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1&&!z){e.sizcache=v;e.sizset=t}if(e.nodeName.toLowerCase()===x){u=e;break}e=e[r]}A[t]=u}}}function q(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1){if(!z){e.sizcache=v;e.sizset=t}if(typeof x!=="string"){if(e===x){u=true;break}}else{if(b.filter(x,[e]).length>0){u=e;break}}}e=e[r]}A[t]=u}}}b.contains=document.compareDocumentPosition?function(r,e){return !!(r.compareDocumentPosition(e)&16)}:function(r,e){return r!==e&&(r.contains?r.contains(e):true)};b.isXML=function(e){var r=(e?e.ownerDocument||e:0).documentElement;return r?r.nodeName!=="HTML":false};var h=function(e,y){var t=[],u="",v,s=y.nodeType?[y]:y;while((v=f.match.PSEUDO.exec(e))){u+=v[0];e=e.replace(f.match.PSEUDO,"")}e=f.relative[e]?e+"*":e;for(var x=0,r=s.length;x<r;x++){b(e,s[x],t)}return b.filter(u,t)};window.tinymce.dom.Sizzle=b})();(function(d){var f=d.each,c=d.DOM,b=d.isIE,e=d.isWebKit,a;d.create("tinymce.dom.EventUtils",{EventUtils:function(){this.inits=[];this.events=[]},add:function(m,p,l,j){var g,h=this,i=h.events,k;if(p instanceof Array){k=[];f(p,function(o){k.push(h.add(m,o,l,j))});return k}if(m&&m.hasOwnProperty&&m instanceof Array){k=[];f(m,function(n){n=c.get(n);k.push(h.add(n,p,l,j))});return k}m=c.get(m);if(!m){return}g=function(n){if(h.disabled){return}n=n||window.event;if(n&&b){if(!n.target){n.target=n.srcElement}d.extend(n,h._stoppers)}if(!j){return l(n)}return l.call(j,n)};if(p=="unload"){d.unloads.unshift({func:g});return g}if(p=="init"){if(h.domLoaded){g()}else{h.inits.push(g)}return g}i.push({obj:m,name:p,func:l,cfunc:g,scope:j});h._add(m,p,g);return l},remove:function(l,m,k){var h=this,g=h.events,i=false,j;if(l&&l.hasOwnProperty&&l instanceof Array){j=[];f(l,function(n){n=c.get(n);j.push(h.remove(n,m,k))});return j}l=c.get(l);f(g,function(o,n){if(o.obj==l&&o.name==m&&(!k||(o.func==k||o.cfunc==k))){g.splice(n,1);h._remove(l,m,o.cfunc);i=true;return false}});return i},clear:function(l){var j=this,g=j.events,h,k;if(l){l=c.get(l);for(h=g.length-1;h>=0;h--){k=g[h];if(k.obj===l){j._remove(k.obj,k.name,k.cfunc);k.obj=k.cfunc=null;g.splice(h,1)}}}},cancel:function(g){if(!g){return false}this.stop(g);return this.prevent(g)},stop:function(g){if(g.stopPropagation){g.stopPropagation()}else{g.cancelBubble=true}return false},prevent:function(g){if(g.preventDefault){g.preventDefault()}else{g.returnValue=false}return false},destroy:function(){var g=this;f(g.events,function(j,h){g._remove(j.obj,j.name,j.cfunc);j.obj=j.cfunc=null});g.events=[];g=null},_add:function(h,i,g){if(h.attachEvent){h.attachEvent("on"+i,g)}else{if(h.addEventListener){h.addEventListener(i,g,false)}else{h["on"+i]=g}}},_remove:function(i,j,h){if(i){try{if(i.detachEvent){i.detachEvent("on"+j,h)}else{if(i.removeEventListener){i.removeEventListener(j,h,false)}else{i["on"+j]=null}}}catch(g){}}},_pageInit:function(h){var g=this;if(g.domLoaded){return}g.domLoaded=true;f(g.inits,function(i){i()});g.inits=[]},_wait:function(i){var g=this,h=i.document;if(i.tinyMCE_GZ&&tinyMCE_GZ.loaded){g.domLoaded=1;return}if(h.attachEvent){h.attachEvent("onreadystatechange",function(){if(h.readyState==="complete"){h.detachEvent("onreadystatechange",arguments.callee);g._pageInit(i)}});if(h.documentElement.doScroll&&i==i.top){(function(){if(g.domLoaded){return}try{h.documentElement.doScroll("left")}catch(j){setTimeout(arguments.callee,0);return}g._pageInit(i)})()}}else{if(h.addEventListener){g._add(i,"DOMContentLoaded",function(){g._pageInit(i)})}}g._add(i,"load",function(){g._pageInit(i)})},_stoppers:{preventDefault:function(){this.returnValue=false},stopPropagation:function(){this.cancelBubble=true}}});a=d.dom.Event=new d.dom.EventUtils();a._wait(window);d.addUnload(function(){a.destroy()})})(tinymce);(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j<arguments.length;j++){h.push(arguments[j])}h=e[g].apply(e,h);b.update(g);return h}});a.extend(b,{on:function(i,h,g){return a.dom.Event.add(b.id,i,h,g)},getXY:function(){return{x:parseInt(b.getStyle("left")),y:parseInt(b.getStyle("top"))}},getSize:function(){var g=e.get(b.id);return{w:parseInt(b.getStyle("width")||g.clientWidth),h:parseInt(b.getStyle("height")||g.clientHeight)}},moveTo:function(g,h){b.setStyles({left:g,top:h})},moveBy:function(g,i){var h=b.getXY();b.moveTo(h.x+g,h.y+i)},resizeTo:function(g,i){b.setStyles({width:g,height:i})},resizeBy:function(g,j){var i=b.getSize();b.resizeTo(i.w+g,i.h+j)},update:function(h){var g;if(a.isIE6&&d.blocker){h=h||"";if(h.indexOf("get")===0||h.indexOf("has")===0||h.indexOf("is")===0){return}if(h=="remove"){e.remove(b.blocker);return}if(!b.blocker){b.blocker=e.uniqueId();g=e.add(d.container||e.getRoot(),"iframe",{id:b.blocker,style:"position:absolute;",frameBorder:0,src:'javascript:""'});e.setStyle(g,"opacity",0)}else{g=e.get(b.blocker)}e.setStyles(g,{left:b.getStyle("left",1),top:b.getStyle("top",1),width:b.getStyle("width",1),height:b.getStyle("height",1),display:b.getStyle("display",1),zIndex:parseInt(b.getStyle("zIndex",1)||0)-1})}}})}})(tinymce);(function(c){function e(f){return f.replace(/[\n\r]+/g,"")}var b=c.is,a=c.isIE,d=c.each;c.create("tinymce.dom.Selection",{Selection:function(i,h,g){var f=this;f.dom=i;f.win=h;f.serializer=g;d(["onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent"],function(j){f[j]=new c.util.Dispatcher(f)});if(!f.win.getSelection){f.tridentSel=new c.dom.TridentSelection(f)}if(c.isIE&&i.boxModel){this._fixIESelection()}c.addUnload(f.destroy,f)},setCursorLocation:function(h,i){var f=this;var g=f.dom.createRng();g.setStart(h,i);g.setEnd(h,i);f.setRng(g);f.collapse(false)},getContent:function(g){var f=this,h=f.getRng(),l=f.dom.create("body"),j=f.getSel(),i,k,m;g=g||{};i=k="";g.get=true;g.format=g.format||"html";g.forced_root_block="";f.onBeforeGetContent.dispatch(f,g);if(g.format=="text"){return f.isCollapsed()?"":(h.text||(j.toString?j.toString():""))}if(h.cloneContents){m=h.cloneContents();if(m){l.appendChild(m)}}else{if(b(h.item)||b(h.htmlText)){l.innerHTML="<br>"+(h.item?h.item(0).outerHTML:h.htmlText);l.removeChild(l.firstChild)}else{l.innerHTML=h.toString()}}if(/^\s/.test(l.innerHTML)){i=" "}if(/\s+$/.test(l.innerHTML)){k=" "}g.getInner=true;g.content=f.isCollapsed()?"":i+f.serializer.serialize(l,g)+k;f.onGetContent.dispatch(f,g);return g.content},setContent:function(g,i){var n=this,f=n.getRng(),j,k=n.win.document,m,l;i=i||{format:"html"};i.set=true;g=i.content=g;if(!i.no_events){n.onBeforeSetContent.dispatch(n,i)}g=i.content;if(f.insertNode){g+='<span id="__caret">_</span>';if(f.startContainer==k&&f.endContainer==k){k.body.innerHTML=g}else{f.deleteContents();if(k.body.childNodes.length==0){k.body.innerHTML=g}else{if(f.createContextualFragment){f.insertNode(f.createContextualFragment(g))}else{m=k.createDocumentFragment();l=k.createElement("div");m.appendChild(l);l.outerHTML=g;f.insertNode(m)}}}j=n.dom.get("__caret");f=k.createRange();f.setStartBefore(j);f.setEndBefore(j);n.setRng(f);n.dom.remove("__caret");try{n.setRng(f)}catch(h){}}else{if(f.item){k.execCommand("Delete",false,null);f=n.getRng()}if(/^\s+/.test(g)){f.pasteHTML('<span id="__mce_tmp">_</span>'+g);n.dom.remove("__mce_tmp")}else{f.pasteHTML(g)}}if(!i.no_events){n.onSetContent.dispatch(n,i)}},getStart:function(){var g=this.getRng(),h,f,j,i;if(g.duplicate||g.item){if(g.item){return g.item(0)}j=g.duplicate();j.collapse(1);h=j.parentElement();f=i=g.parentElement();while(i=i.parentNode){if(i==h){h=f;break}}return h}else{h=g.startContainer;if(h.nodeType==1&&h.hasChildNodes()){h=h.childNodes[Math.min(h.childNodes.length-1,g.startOffset)]}if(h&&h.nodeType==3){return h.parentNode}return h}},getEnd:function(){var g=this,h=g.getRng(),i,f;if(h.duplicate||h.item){if(h.item){return h.item(0)}h=h.duplicate();h.collapse(0);i=h.parentElement();if(i&&i.nodeName=="BODY"){return i.lastChild||i}return i}else{i=h.endContainer;f=h.endOffset;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[f>0?f-1:f]}if(i&&i.nodeType==3){return i.parentNode}return i}},getBookmark:function(r,s){var v=this,m=v.dom,g,j,i,n,h,o,p,l="\uFEFF",u;function f(x,y){var t=0;d(m.select(x),function(A,z){if(A==y){t=z}});return t}if(r==2){function k(){var x=v.getRng(true),t=m.getRoot(),y={};function z(C,H){var B=C[H?"startContainer":"endContainer"],G=C[H?"startOffset":"endOffset"],A=[],D,F,E=0;if(B.nodeType==3){if(s){for(D=B.previousSibling;D&&D.nodeType==3;D=D.previousSibling){G+=D.nodeValue.length}}A.push(G)}else{F=B.childNodes;if(G>=F.length&&F.length){E=1;G=Math.max(0,F.length-1)}A.push(v.dom.nodeIndex(F[G],s)+E)}for(;B&&B!=t;B=B.parentNode){A.push(v.dom.nodeIndex(B,s))}return A}y.start=z(x,true);if(!v.isCollapsed()){y.end=z(x)}return y}if(v.tridentSel){return v.tridentSel.getBookmark(r)}return k()}if(r){return{rng:v.getRng()}}g=v.getRng();i=m.uniqueId();n=tinyMCE.activeEditor.selection.isCollapsed();u="overflow:hidden;line-height:0px";if(g.duplicate||g.item){if(!g.item){j=g.duplicate();try{g.collapse();g.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_start" style="'+u+'">'+l+"</span>");if(!n){j.collapse(false);g.moveToElementText(j.parentElement());if(g.compareEndPoints("StartToEnd",j)==0){j.move("character",-1)}j.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_end" style="'+u+'">'+l+"</span>")}}catch(q){return null}}else{o=g.item(0);h=o.nodeName;return{name:h,index:f(h,o)}}}else{o=v.getNode();h=o.nodeName;if(h=="IMG"){return{name:h,index:f(h,o)}}j=g.cloneRange();if(!n){j.collapse(false);j.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_end",style:u},l))}g.collapse(true);g.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_start",style:u},l))}v.moveToBookmark({id:i,keep:1});return{id:i}},moveToBookmark:function(n){var r=this,l=r.dom,i,h,f,q,j,s,o,p;if(n){if(n.start){f=l.createRng();q=l.getRoot();function g(z){var t=n[z?"start":"end"],v,x,y,u;if(t){y=t[0];for(x=q,v=t.length-1;v>=1;v--){u=x.childNodes;if(t[v]>u.length-1){return}x=u[t[v]]}if(x.nodeType===3){y=Math.min(t[0],x.nodeValue.length)}if(x.nodeType===1){y=Math.min(t[0],x.childNodes.length)}if(z){f.setStart(x,y)}else{f.setEnd(x,y)}}return true}if(r.tridentSel){return r.tridentSel.moveToBookmark(n)}if(g(true)&&g()){r.setRng(f)}}else{if(n.id){function k(A){var u=l.get(n.id+"_"+A),z,t,x,y,v=n.keep;if(u){z=u.parentNode;if(A=="start"){if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}j=s=z;o=p=t}else{if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}s=z;p=t}if(!v){y=u.previousSibling;x=u.nextSibling;d(c.grep(u.childNodes),function(B){if(B.nodeType==3){B.nodeValue=B.nodeValue.replace(/\uFEFF/g,"")}});while(u=l.get(n.id+"_"+A)){l.remove(u,1)}if(y&&x&&y.nodeType==x.nodeType&&y.nodeType==3&&!c.isOpera){t=y.nodeValue.length;y.appendData(x.nodeValue);l.remove(x);if(A=="start"){j=s=y;o=p=t}else{s=y;p=t}}}}}function m(t){if(l.isBlock(t)&&!t.innerHTML){t.innerHTML=!a?'<br data-mce-bogus="1" />':" "}return t}k("start");k("end");if(j){f=l.createRng();f.setStart(m(j),o);f.setEnd(m(s),p);r.setRng(f)}}else{if(n.name){r.select(l.select(n.name)[n.index])}else{if(n.rng){r.setRng(n.rng)}}}}}},select:function(k,j){var i=this,l=i.dom,g=l.createRng(),f;if(k){f=l.nodeIndex(k);g.setStart(k.parentNode,f);g.setEnd(k.parentNode,f+1);if(j){function h(m,o){var n=new c.dom.TreeWalker(m,m);do{if(m.nodeType==3&&c.trim(m.nodeValue).length!=0){if(o){g.setStart(m,0)}else{g.setEnd(m,m.nodeValue.length)}return}if(m.nodeName=="BR"){if(o){g.setStartBefore(m)}else{g.setEndBefore(m)}return}}while(m=(o?n.next():n.prev()))}h(k,1);h(k)}i.setRng(g)}return k},isCollapsed:function(){var f=this,h=f.getRng(),g=f.getSel();if(!h||h.item){return false}if(h.compareEndPoints){return h.compareEndPoints("StartToEnd",h)===0}return !g||h.collapsed},collapse:function(f){var h=this,g=h.getRng(),i;if(g.item){i=g.item(0);g=h.win.document.body.createTextRange();g.moveToElementText(i)}g.collapse(!!f);h.setRng(g)},getSel:function(){var g=this,f=this.win;return f.getSelection?f.getSelection():f.document.selection},getRng:function(l){var g=this,h,i,k,j=g.win.document;if(l&&g.tridentSel){return g.tridentSel.getRangeAt(0)}try{if(h=g.getSel()){i=h.rangeCount>0?h.getRangeAt(0):(h.createRange?h.createRange():j.createRange())}}catch(f){}if(c.isIE&&i&&i.setStart&&j.selection.createRange().item){k=j.selection.createRange().item(0);i=j.createRange();i.setStartBefore(k);i.setEndAfter(k)}if(!i){i=j.createRange?j.createRange():j.body.createTextRange()}if(g.selectedRange&&g.explicitRange){if(i.compareBoundaryPoints(i.START_TO_START,g.selectedRange)===0&&i.compareBoundaryPoints(i.END_TO_END,g.selectedRange)===0){i=g.explicitRange}else{g.selectedRange=null;g.explicitRange=null}}return i},setRng:function(i){var h,g=this;if(!g.tridentSel){h=g.getSel();if(h){g.explicitRange=i;try{h.removeAllRanges()}catch(f){}h.addRange(i);g.selectedRange=h.getRangeAt(0)}}else{if(i.cloneRange){g.tridentSel.addRange(i);return}try{i.select()}catch(f){}}},setNode:function(g){var f=this;f.setContent(f.dom.getOuterHTML(g));return g},getNode:function(){var h=this,g=h.getRng(),i=h.getSel(),l,k=g.startContainer,f=g.endContainer;if(!g){return h.dom.getRoot()}if(g.setStart){l=g.commonAncestorContainer;if(!g.collapsed){if(g.startContainer==g.endContainer){if(g.endOffset-g.startOffset<2){if(g.startContainer.hasChildNodes()){l=g.startContainer.childNodes[g.startOffset]}}}if(k.nodeType===3&&f.nodeType===3){function j(p,m){var o=p;while(p&&p.nodeType===3&&p.length===0){p=m?p.nextSibling:p.previousSibling}return p||o}if(k.length===g.startOffset){k=j(k.nextSibling,true)}else{k=k.parentNode}if(g.endOffset===0){f=j(f.previousSibling,false)}else{f=f.parentNode}if(k&&k===f){return k}}}if(l&&l.nodeType==3){return l.parentNode}return l}return g.item?g.item(0):g.parentElement()},getSelectedBlocks:function(o,g){var m=this,j=m.dom,l,k,h,i=[];l=j.getParent(o||m.getStart(),j.isBlock);k=j.getParent(g||m.getEnd(),j.isBlock);if(l){i.push(l)}if(l&&k&&l!=k){h=l;var f=new c.dom.TreeWalker(l,j.getRoot());while((h=f.next())&&h!=k){if(j.isBlock(h)){i.push(h)}}}if(k&&l!=k){i.push(k)}return i},normalize:function(){var g=this,f,i;if(c.isIE){return}function h(p){var k,o,n,m=g.dom,j=m.getRoot(),l;k=f[(p?"start":"end")+"Container"];o=f[(p?"start":"end")+"Offset"];if(k.nodeType===9){k=k.body;o=0}if(k===j){if(k.hasChildNodes()){k=k.childNodes[Math.min(!p&&o>0?o-1:o,k.childNodes.length-1)];o=0;if(k.hasChildNodes()){l=k;n=new c.dom.TreeWalker(k,j);do{if(l.nodeType===3){o=p?0:l.nodeValue.length-1;k=l;break}if(l.nodeName==="BR"){o=m.nodeIndex(l);k=l.parentNode;break}}while(l=(p?n.next():n.prev()));i=true}}}if(i){f["set"+(p?"Start":"End")](k,o)}}f=g.getRng();h(true);if(f.collapsed){h()}if(i){g.setRng(f)}},destroy:function(g){var f=this;f.win=null;if(!g){c.removeUnload(f.destroy)}},_fixIESelection:function(){var g=this.dom,m=g.doc,h=m.body,j,n,f;m.documentElement.unselectable=true;function i(o,r){var p=h.createTextRange();try{p.moveToPoint(o,r)}catch(q){p=null}return p}function l(p){var o;if(p.button){o=i(p.x,p.y);if(o){if(o.compareEndPoints("StartToStart",n)>0){o.setEndPoint("StartToStart",n)}else{o.setEndPoint("EndToEnd",n)}o.select()}}else{k()}}function k(){var o=m.selection.createRange();if(n&&!o.item&&o.compareEndPoints("StartToEnd",o)===0){n.select()}g.unbind(m,"mouseup",k);g.unbind(m,"mousemove",l);n=j=0}g.bind(m,["mousedown","contextmenu"],function(o){if(o.target.nodeName==="HTML"){if(j){k()}f=m.documentElement;if(f.scrollHeight>f.clientHeight){return}j=1;n=i(o.x,o.y);if(n){g.bind(m,"mouseup",k);g.bind(m,"mousemove",l);g.win.focus();n.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}e.remove_trailing_brs=true;i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/\s*mce(Item\w+|Selected)\s*/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g,"").replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// <![CDATA[\n"+j(o)+"\n// ]]>"}}else{if(o.length>0){n.firstChild.value="<!--\n"+j(o)+"\n-->"}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(m.getInner?o.innerHTML:a.trim(i.getOuterHTML(o),m),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],f={},d=[],g=0,e;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==e){j.push(m);l[m]=c}if(q){if(!f[m]){f[m]=[]}f[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(f[r],function(s){s.func.call(s.scope)});f[r]=e}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);tinymce.dom.TreeWalker=function(a,c){var b=a;function d(i,f,e,j){var h,g;if(i){if(!j&&i[f]){return i[f]}if(i!=c){h=i[e];if(h){return h}for(g=i.parentNode;g&&g!=c;g=g.parentNode){h=g[e];if(h){return h}}}}}this.current=function(){return b};this.next=function(e){return(b=d(b,"firstChild","nextSibling",e))};this.prev=function(e){return(b=d(b,"lastChild","previousSibling",e))}};(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&d<h.nodeValue.length){i=f(h,d);h=i.previousSibling;if(g>d){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d<h.nodeValue.length){h=f(h,d);d=0}if(i.nodeType==3&&g>0&&g<i.nodeValue.length){i=f(i,g).previousSibling;g=i.nodeValue.length}}return{startContainer:h,startOffset:d,endContainer:i,endOffset:g}}};a.dom.RangeUtils.compareRanges=function(c,b){if(c&&b){if(c.item||c.duplicate){if(c.item&&b.item&&c.item(0)===b.item(0)){return true}if(c.isEqual&&b.isEqual&&b.isEqual(c)){return true}}else{return c.startContainer==b.startContainer&&c.startOffset==b.startOffset}}return false}})(tinymce);(function(b){var a=b.dom.Event,c=b.each;b.create("tinymce.ui.KeyboardNavigation",{KeyboardNavigation:function(e,f){var p=this,m=e.root,l=e.items,n=e.enableUpDown,i=e.enableLeftRight||!e.enableUpDown,k=e.excludeFromTabOrder,j,h,o,d,g;f=f||b.DOM;j=function(q){g=q.target.id};h=function(q){f.setAttrib(q.target.id,"tabindex","-1")};d=function(q){var r=f.get(g);f.setAttrib(r,"tabindex","0");r.focus()};p.focus=function(){f.get(g).focus()};p.destroy=function(){c(l,function(q){f.unbind(f.get(q.id),"focus",j);f.unbind(f.get(q.id),"blur",h)});f.unbind(f.get(m),"focus",d);f.unbind(f.get(m),"keydown",o);l=f=m=p.focus=j=h=o=d=null;p.destroy=function(){}};p.moveFocus=function(u,r){var q=-1,t=p.controls,s;if(!g){return}c(l,function(x,v){if(x.id===g){q=v;return false}});q+=u;if(q<0){q=l.length-1}else{if(q>=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.clientWidth,j.max_width):g.clientWidth;k=j.max_height?Math.min(g.clientHeight,j.max_height):g.clientHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeight<j.max_height){c.setStyle(l,"overflow","hidden")}}},showMenu:function(p,n,r){var z=this,A=z.settings,o,g=c.getViewPort(),u,l,v,q,i=2,k,j,m=z.classPrefix;z.collapse(1);if(z.isMenuVisible){return}if(!z.rendered){o=c.add(z.settings.container,z.renderNode());f(z.items,function(h){h.postRender()});z.element=new b("menu_"+z.id,{blocker:1,container:A.container})}else{o=c.get("menu_"+z.id)}if(!e.isOpera){c.setStyles(o,{left:-65535,top:-65535})}c.show(o);z.update();p+=A.offset_x||0;n+=A.offset_y||0;g.w-=4;g.h-=4;if(A.constrain){u=o.clientWidth-i;l=o.clientHeight-i;v=g.x+g.w;q=g.y+g.h;if((p+A.vp_offset_x+u)>v){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return a.cancel(s)}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.select("#menu_"+g.id)[0];h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='<a role="button" id="'+this.id+'" href="javascript:;" class="'+f+" "+f+"Enabled "+e["class"]+(c?" "+f+"Labeled":"")+'" onmousedown="return false;" onclick="return false;" aria-labelledby="'+this.id+'_voice" title="'+a.encode(e.title)+'">';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+='<img class="mceIcon" src="'+e.image+'" alt="'+a.encode(e.title)+'" />'+c}else{d+='<span class="mceIcon '+e["class"]+'"></span>'+(c?'<span class="'+f+'Label">'+c+"</span>":"")}d+='<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="'+this.id+'_voice">'+e.title+"</span>";d+="</a>";return d},postRender:function(){var c=this,d=c.settings;b.dom.Event.add(c.id,"click",function(f){if(!c.isDisabled()){return d.onclick.call(d.scope,f)}})}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(i,h,f){var g=this;g.parent(i,h,f);g.items=[];g.onChange=new a(g);g.onPostRender=new a(g);g.onAdd=new a(g);g.onRenderMenu=new d.util.Dispatcher(this);g.classPrefix="mceListBox"},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){var h=this,i,j,g;if(f!=h.selectedIndex){i=c.get(h.id+"_text");g=c.get(h.id+"_voiceDesc");j=h.items[f];if(j){h.selectedValue=j.value;h.selectedIndex=f;c.setHTML(i,c.encode(j.title));c.setHTML(g,h.settings.title+" - "+j.title);c.removeClass(i,"mceTitle");c.setAttrib(h.id,"aria-valuenow",j.title)}else{c.setHTML(i,c.encode(h.settings.title));c.setHTML(g,c.encode(h.settings.title));c.addClass(i,"mceTitle");h.selectedValue=h.selectedIndex=null;c.setAttrib(h.id,"aria-valuenow",h.settings.title)}i=0}},add:function(i,f,h){var g=this;h=h||{};h=d.extend(h,{title:i,value:f});g.items.push(h);g.onAdd.dispatch(g,h)},getLength:function(){return this.items.length},renderHTML:function(){var i="",f=this,g=f.settings,j=f.classPrefix;i='<span role="listbox" aria-haspopup="true" aria-labelledby="'+f.id+'_voiceDesc" aria-describedby="'+f.id+'_voiceDesc"><table role="presentation" tabindex="0" id="'+f.id+'" cellpadding="0" cellspacing="0" class="'+j+" "+j+"Enabled"+(g["class"]?(" "+g["class"]):"")+'"><tbody><tr>';i+="<td>"+c.createHTML("span",{id:f.id+"_voiceDesc","class":"voiceLabel",style:"display:none;"},f.settings.title);i+=c.createHTML("a",{id:f.id+"_text",tabindex:-1,href:"javascript:;","class":"mceText",onclick:"return false;",onmousedown:"return false;"},c.encode(f.settings.title))+"</td>";i+="<td>"+c.createHTML("a",{id:f.id+"_open",tabindex:-1,href:"javascript:;","class":"mceOpen",onclick:"return false;",onmousedown:"return false;"},'<span><span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span></span>')+"</td>";i+="</tr></tbody></table></span>";return i},showMenu:function(){var g=this,i,h=c.get(this.id),f;if(g.isDisabled()||g.items.length==0){return}if(g.menu&&g.menu.isMenuVisible){return g.hideMenu()}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}i=c.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.keyboard_focus=!d.isOpera;if(g.oldID){f.items[g.oldID].setSelected(0)}e(g.items,function(j){if(j.value===g.selectedValue){f.items[j.id].setSelected(1);g.oldID=j.id}});f.showMenu(0,h.clientHeight);b.add(c.doc,"mousedown",g.hideMenu,g);c.addClass(g.id,g.classPrefix+"Selected")},hideMenu:function(g){var f=this;if(f.menu&&f.menu.isMenuVisible){c.removeClass(f.id,f.classPrefix+"Selected");if(g&&g.type=="mousedown"&&(g.target.id==f.id+"_text"||g.target.id==f.id+"_open")){return}if(!g||!c.getParent(g.target,".mceMenu")){c.removeClass(f.id,f.classPrefix+"Selected");b.remove(c.doc,"mousedown",f.hideMenu,f);f.menu.hideMenu()}}},renderMenu:function(){var g=this,f;f=g.settings.control_manager.createDropMenu(g.id+"_menu",{menu_line:1,"class":g.classPrefix+"Menu mceNoIcons",max_width:150,max_height:150});f.onHideMenu.add(function(){g.hideMenu();g.focus()});f.add({title:g.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}});e(g.items,function(h){if(h.value===undefined){f.add({title:h.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}})}else{h.id=c.uniqueId();h.role="option";h.onclick=function(){if(g.settings.onselect(h.value)!==false){g.select(h.value)}};f.add(h)}});g.onRenderMenu.dispatch(g,f);g.menu=f},postRender:function(){var f=this,g=f.classPrefix;b.add(f.id,"click",f.showMenu,f);b.add(f.id,"keydown",function(h){if(h.keyCode==32){f.showMenu(h);b.cancel(h)}});b.add(f.id,"focus",function(){if(!f._focused){f.keyDownHandler=b.add(f.id,"keydown",function(h){if(h.keyCode==40){f.showMenu();b.cancel(h)}});f.keyPressHandler=b.add(f.id,"keypress",function(i){var h;if(i.keyCode==13){h=f.selectedValue;f.selectedValue=null;b.cancel(i);f.settings.onselect(h)}})}f._focused=1});b.add(f.id,"blur",function(){b.remove(f.id,"keydown",f.keyDownHandler);b.remove(f.id,"keypress",f.keyPressHandler);f._focused=0});if(d.isIE6||!c.boxModel){b.add(f.id,"mouseover",function(){if(!c.hasClass(f.id,g+"Disabled")){c.addClass(f.id,g+"Hover")}});b.add(f.id,"mouseout",function(){if(!c.hasClass(f.id,g+"Disabled")){c.removeClass(f.id,g+"Hover")}})}f.onPostRender.dispatch(f,c.get(f.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(g,f){this.parent(g,f);this.classPrefix="mceNativeListBox"},setDisabled:function(f){c.get(this.id).disabled=f;this.setAriaProperty("disabled",f)},isDisabled:function(){return c.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){c.get(this.id).selectedIndex=f+1;this.selectedValue=this.items[f]?this.items[f].value:null},add:function(j,g,f){var i,h=this;f=f||{};f.value=g;if(h.isRendered()){c.add(c.get(this.id),"option",f,j)}i={title:j,value:g,attribs:f};h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var g,f=this;g=c.createHTML("option",{value:""},"-- "+f.settings.title+" --");e(f.items,function(h){g+=c.createHTML("option",{value:h.value},h.title)});g=c.createHTML("select",{id:f.id,"class":"mceNativeListBox","aria-labelledby":f.id+"_aria"},g);g+=c.createHTML("span",{id:f.id+"_aria",style:"display: none"},f.settings.title);return g},postRender:function(){var g=this,h,i=true;g.rendered=true;function f(k){var j=g.items[k.target.selectedIndex-1];if(j&&(j=j.value)){g.onChange.dispatch(g,j);if(g.settings.onselect){g.settings.onselect(j)}}}b.add(g.id,"change",f);b.add(g.id,"keydown",function(k){var j;b.remove(g.id,"change",h);i=false;j=b.add(g.id,"blur",function(){if(i){return}i=true;b.add(g.id,"change",f);b.remove(g.id,"blur",j)});if(d.isWebKit&&(k.keyCode==37||k.keyCode==39)){return b.prevent(k)}if(k.keyCode==13||k.keyCode==32){f(k);return b.cancel(k)}});g.onPostRender.dispatch(g,c.get(g.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="<tbody><tr>";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'<span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span>');i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";i+="</tr></tbody>";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(i){i=i.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");g=c.add(g,"a",{role:"option",href:"javascript:;",style:{backgroundColor:"#"+i},title:p.editor.getLang("colors."+i,i),"data-mce-color":"#"+i});if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+i;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return a.cancel(i)});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('<div id="'+f.id+'" role="group" aria-labelledby="'+f.id+'_voice">');i.push("<span role='application'>");i.push('<span id="'+f.id+'_voice" class="mceVoiceLabel" style="display:none;">'+d.encode(g.name)+"</span>");j(e,function(h){i.push(h.renderHTML())});i.push("</span>");i.push("</div>");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e<l.length;e++){k=l[e];d=l[e-1];g=l[e+1];if(e===0){j="mceToolbarStart";if(k.Button){j+=" mceToolbarStartButton"}else{if(k.SplitButton){j+=" mceToolbarStartSplitButton"}else{if(k.ListBox){j+=" mceToolbarStartListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,"<!-- IE -->"))}}if(c.stdMode){f+='<td style="position: relative">'+k.renderHTML()+"</td>"}else{f+="<td>"+k.renderHTML()+"</td>"}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,"<!-- IE -->"))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},"<tbody><tr>"+f+"</tr></tbody>")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!=0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(q){var n=this,p,l=j.ScriptLoader,u,o=[],m;function r(x,y,t){var v=x[y];if(!v){return}if(j.is(v,"string")){t=v.replace(/\.\w+$/,"");t=t?j.resolve(t):0;v=j.resolve(v)}return v.apply(t||this,Array.prototype.slice.call(arguments,2))}q=d({theme:"simple",language:"en"},q);n.settings=q;i.add(document,"init",function(){var s,v;r(q,"onpageload");switch(q.mode){case"exact":s=q.elements||"";if(s.length>0){g(e(s),function(x){if(k.get(x)){m=new j.Editor(x,q);o.push(m);m.render(1)}else{g(document.forms,function(y){g(y.elements,function(z){if(z.name===x){x="mce_editor_"+c++;k.setAttrib(z,"id",x);m=new j.Editor(x,q);o.push(m);m.render(1)}})})}})}break;case"textareas":case"specific_textareas":function t(y,x){return x.constructor===RegExp?x.test(y.className):k.hasClass(y,x)}g(k.select("textarea"),function(x){if(q.editor_deselector&&t(x,q.editor_deselector)){return}if(!q.editor_selector||t(x,q.editor_selector)){u=k.get(x.name);if(!x.id&&!u){x.id=x.name}if(!x.id||n.get(x.id)){x.id=k.uniqueId()}m=new j.Editor(x.id,q);o.push(m);m.render(1)}});break}if(q.oninit){s=v=0;g(o,function(x){v++;if(!x.initialized){x.onInit.add(function(){s++;if(s==v){r(q,"oninit")}})}else{s++}if(s==v){r(q,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l<o.length;l++){if(o[l]==n){o.splice(l,1);break}}if(m.activeEditor==n){m._setActive(o[0])}n.destroy();m.onRemoveEditor.dispatch(m,n);return n},execCommand:function(r,p,o){var q=this,n=q.get(o),l;switch(r){case"mceFocus":n.focus();return true;case"mceAddEditor":case"mceAddControl":if(!q.get(o)){new j.Editor(o,q.settings).render()}return true;case"mceAddFrameControl":l=o.window;l.tinyMCE=tinyMCE;l.tinymce=j;j.DOM.doc=l.document;j.DOM.win=l;n=new j.Editor(o.element_id,o);n.render();if(j.isIE){function m(){n.destroy();l.detachEvent("onunload",m);l=l.tinyMCE=l.tinymce=null}l.attachEvent("onunload",m)}o.page_window=null;return true;case"mceRemoveEditor":case"mceRemoveControl":if(n){n.remove()}return true;case"mceToggleEditor":if(!n){q.execCommand("mceAddControl",0,o);return true}if(n.isHidden()){n.show()}else{n.hide()}return true}if(q.activeEditor){return q.activeEditor.execCommand(r,p,o)}return false},execInstanceCommand:function(p,o,n,m){var l=this.get(p);if(l){return l.execCommand(o,n,m)}return false},triggerSave:function(){g(this.editors,function(l){l.save()})},addI18n:function(n,q){var l,m=this.i18n;if(!j.is(n,"string")){g(n,function(r,p){g(r,function(t,s){g(t,function(v,u){if(s==="common"){m[p+"."+u]=v}else{m[p+"."+s+"."+u]=v}})})})}else{g(q,function(r,p){m[n+"."+p]=r})}},_setActive:function(l){this.selectedInstance=this.activeEditor=l}})})(tinymce);(function(m){var n=m.DOM,j=m.dom.Event,f=m.extend,k=m.util.Dispatcher,i=m.each,a=m.isGecko,b=m.isIE,e=m.isWebKit,d=m.is,h=m.ThemeManager,c=m.PluginManager,o=m.inArray,l=m.grep,g=m.explode;m.create("tinymce.Editor",{Editor:function(r,q){var p=this;p.id=p.editorId=r;p.execCommands={};p.queryStateCommands={};p.queryValueCommands={};p.isNotDirty=false;p.plugins={};i(["onPreInit","onBeforeRenderUI","onPostRender","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState"],function(s){p[s]=new k(p)});p.settings=q=f({id:r,language:"en",docs_language:"en",theme:"simple",skin:"default",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:m.documentBaseURL,add_form_submit_trigger:1,submit_patch:1,add_unload_trigger:1,convert_urls:1,relative_urls:1,remove_script_host:1,table_inline_editing:0,object_resizing:1,cleanup:1,accessibility_focus:1,custom_shortcuts:1,custom_undo_redo_keyboard_shortcuts:1,custom_undo_redo_restore_selection:1,custom_undo_redo:1,doctype:m.isIE6?'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">':"<!DOCTYPE>",visual_table_class:"mceItemTable",visual:1,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:1,directionality:"ltr",forced_root_block:"p",hidden_input:1,padd_empty_editor:1,render_ui:1,init_theme:1,force_p_newlines:1,indentation:"30px",keep_styles:1,fix_table_elements:1,inline_styles:1,convert_fonts_to_spans:true,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",validate:true,entity_encoding:"named",url_converter:p.convertURL,url_converter_scope:p,ie7_compat:true},q);p.documentBaseURI=new m.util.URI(q.document_base_url||m.documentBaseURL,{base_uri:tinyMCE.baseURI});p.baseURI=m.baseURI;p.contentCSS=[];p.execCallback("setup",p)},render:function(r){var u=this,v=u.settings,x=u.id,p=m.ScriptLoader;if(!j.domLoaded){j.add(document,"init",function(){u.render()});return}tinyMCE.settings=v;if(!u.getElement()){return}if(m.isIDevice&&!m.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(u.getElement().nodeName)&&v.hidden_input&&n.getParent(x,"form")){n.insertAfter(n.create("input",{type:"hidden",name:x}),x)}if(m.WindowManager){u.windowManager=new m.WindowManager(u)}if(v.encoding=="xml"){u.onGetContent.add(function(s,t){if(t.save){t.content=n.encode(t.content)}})}if(v.add_form_submit_trigger){u.onSubmit.addToTop(function(){if(u.initialized){u.save();u.isNotDirty=1}})}if(v.add_unload_trigger){u._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(u.initialized&&!u.destroyed&&!u.isHidden()){u.save({format:"raw",no_events:true})}})}m.addUnload(u.destroy,u);if(v.submit_patch){u.onBeforeRenderUI.add(function(){var s=u.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){u.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){m.triggerSave();u.isNotDirty=1;return u.formElement._mceOldSubmit(u.formElement)}}s=null})}function q(){if(v.language&&v.language_load!==false){p.add(m.baseURL+"/langs/"+v.language+".js")}if(v.theme&&v.theme.charAt(0)!="-"&&!h.urls[v.theme]){h.load(v.theme,"themes/"+v.theme+"/editor_template"+m.suffix+".js")}i(g(v.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(z){var y={prefix:"plugins/",resource:z,suffix:"/editor_plugin"+m.suffix+".js"};var z=c.createUrl(y,z);c.load(z.resource,z)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+m.suffix+".js"})}}});p.loadQueue(function(){if(!u.removed){u.init()}})}q()},init:function(){var r,H=this,I=H.settings,E,A,D=H.getElement(),q,p,F,y,C,G,z,v=[];m.add(H);I.aria_label=I.aria_label||n.getAttrib(D,"aria-label",H.getLang("aria.rich_text_area"));if(I.theme){I.theme=I.theme.replace(/-/,"");q=h.get(I.theme);H.theme=new q();if(H.theme.init&&I.init_theme){H.theme.init(H,h.urls[I.theme]||m.documentBaseURL.replace(/\/$/,""))}}function B(J){var K=c.get(J),t=c.urls[J]||m.documentBaseURL.replace(/\/$/,""),s;if(K&&m.inArray(v,J)===-1){i(c.dependencies(J),function(u){B(u)});s=new K(H,t);H.plugins[J]=s;if(s.init){s.init(H,t);v.push(J)}}}i(g(I.plugins.replace(/\-/g,"")),B);if(I.popup_css!==false){if(I.popup_css){I.popup_css=H.documentBaseURI.toAbsolute(I.popup_css)}else{I.popup_css=H.baseURI.toAbsolute("themes/"+I.theme+"/skins/"+I.skin+"/dialog.css")}}if(I.popup_css_add){I.popup_css+=","+H.documentBaseURI.toAbsolute(I.popup_css_add)}H.controlManager=new m.ControlManager(H);if(I.custom_undo_redo){H.onBeforeExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.beforeChange()}});H.onExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.add()}})}H.onExecCommand.add(function(s,t){if(!/^(FontName|FontSize)$/.test(t)){H.nodeChanged()}});if(a){function x(s,t){if(!t||!t.initial){H.execCommand("mceRepaint")}}H.onUndo.add(x);H.onRedo.add(x);H.onSetContent.add(x)}H.onBeforeRenderUI.dispatch(H,H.controlManager);if(I.render_ui){E=I.width||D.style.width||D.offsetWidth;A=I.height||D.style.height||D.offsetHeight;H.orgDisplay=D.style.display;G=/^[0-9\.]+(|px)$/i;if(G.test(""+E)){E=Math.max(parseInt(E)+(q.deltaWidth||0),100)}if(G.test(""+A)){A=Math.max(parseInt(A)+(q.deltaHeight||0),100)}q=H.theme.renderUI({targetNode:D,width:E,height:A,deltaWidth:I.delta_width,deltaHeight:I.delta_height});H.editorContainer=q.editorContainer}if(document.domain&&location.hostname!=document.domain){m.relaxedDomain=document.domain}n.setStyles(q.sizeContainer||q.editorContainer,{width:E,height:A});if(I.content_css){m.each(g(I.content_css),function(s){H.contentCSS.push(H.documentBaseURI.toAbsolute(s))})}A=(q.iframeHeight||A)+(typeof(A)=="number"?(q.deltaHeight||0):"");if(A<100){A=100}H.iframeHTML=I.doctype+'<html><head xmlns="http://www.w3.org/1999/xhtml">';if(I.document_base_url!=m.documentBaseURL){H.iframeHTML+='<base href="'+H.documentBaseURI.getURI()+'" />'}if(I.ie7_compat){H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'}else{H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=edge" />'}H.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(z=0;z<H.contentCSS.length;z++){H.iframeHTML+='<link type="text/css" rel="stylesheet" href="'+H.contentCSS[z]+'" />'}y=I.body_id||"tinymce";if(y.indexOf("=")!=-1){y=H.getParam("body_id","","hash");y=y[H.id]||y}C=I.body_class||"";if(C.indexOf("=")!=-1){C=H.getParam("body_class","","hash");C=C[H.id]||""}H.iframeHTML+='</head><body id="'+y+'" class="mceContentBody '+C+'"><br></body></html>';if(m.relaxedDomain&&(b||(m.isOpera&&parseFloat(opera.version())<11))){F='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+H.id+'");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'}r=n.add(q.iframeContainer,"iframe",{id:H.id+"_ifr",src:F||'javascript:""',frameBorder:"0",allowTransparency:"true",title:I.aria_label,style:{width:"100%",height:A,display:"block"}});H.contentAreaContainer=q.iframeContainer;n.get(q.editorContainer).style.display=H.orgDisplay;n.get(H.id).style.display="none";n.setAttrib(H.id,"aria-hidden",true);if(!m.relaxedDomain||!F){H.setupIframe()}D=r=q=null},setupIframe:function(){var q=this,v=q.settings,x=n.get(q.id),y=q.getDoc(),u,p;if(!b||!m.relaxedDomain){y.open();y.write(q.iframeHTML);y.close();if(m.relaxedDomain){y.domain=m.relaxedDomain}}p=q.getBody();p.disabled=true;if(!v.readonly){p.contentEditable=true}p.disabled=false;q.schema=new m.html.Schema(v);q.dom=new m.dom.DOMUtils(q.getDoc(),{keep_values:true,url_converter:q.convertURL,url_converter_scope:q,hex_colors:v.force_hex_style_colors,class_filter:v.class_filter,update_styles:1,fix_ie_paragraphs:1,schema:q.schema});q.parser=new m.html.DomParser(v,q.schema);if(!q.settings.allow_html_in_named_anchor){q.parser.addAttributeFilter("name",function(s,t){var A=s.length,C,z,B,D;while(A--){D=s[A];if(D.name==="a"&&D.firstChild){B=D.parent;C=D.lastChild;do{z=C.prev;B.insert(C,D);C=z}while(C)}}})}q.parser.addAttributeFilter("src,href,style",function(s,t){var z=s.length,B,D=q.dom,C,A;while(z--){B=s[z];C=B.attr(t);A="data-mce-"+t;if(!B.attributes.map[A]){if(t==="style"){B.attr(A,D.serializeStyle(D.parseStyle(C),B.name))}else{B.attr(A,q.convertURL(C,t,B.name))}}}});q.parser.addNodeFilter("script",function(s,t){var z=s.length,A;while(z--){A=s[z];A.attr("type","mce-"+(A.attr("type")||"text/javascript"))}});q.parser.addNodeFilter("#cdata",function(s,t){var z=s.length,A;while(z--){A=s[z];A.type=8;A.name="#comment";A.value="[CDATA["+A.value+"]]"}});q.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,z){var A=t.length,B,s=q.schema.getNonEmptyElements();while(A--){B=t[A];if(B.isEmpty(s)){B.empty().append(new m.html.Node("br",1)).shortEnded=true}}});q.serializer=new m.dom.Serializer(v,q.dom,q.schema);q.selection=new m.dom.Selection(q.dom,q.getWin(),q.serializer);q.formatter=new m.Formatter(this);q.formatter.register({alignleft:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"}},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"}},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"}},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"}}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(s){return true},onformat:function(z,s,t){i(t,function(B,A){q.dom.setAttrib(z,A,B)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});i("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(s){q.formatter.register(s,{block:s,remove:"all"})});q.formatter.register(q.settings.formats);q.undoManager=new m.UndoManager(q);q.undoManager.onAdd.add(function(t,s){if(t.hasUndo()){return q.onChange.dispatch(q,s,t)}});q.undoManager.onUndo.add(function(t,s){return q.onUndo.dispatch(q,s,t)});q.undoManager.onRedo.add(function(t,s){return q.onRedo.dispatch(q,s,t)});q.forceBlocks=new m.ForceBlocks(q,{forced_root_block:v.forced_root_block});q.editorCommands=new m.EditorCommands(q);q.serializer.onPreProcess.add(function(s,t){return q.onPreProcess.dispatch(q,t,s)});q.serializer.onPostProcess.add(function(s,t){return q.onPostProcess.dispatch(q,t,s)});q.onPreInit.dispatch(q);if(!v.gecko_spellcheck){q.getBody().spellcheck=0}if(!v.readonly){q._addEvents()}q.controlManager.onPostRender.dispatch(q,q.controlManager);q.onPostRender.dispatch(q);q.quirks=new m.util.Quirks(this);if(v.directionality){q.getBody().dir=v.directionality}if(v.nowrap){q.getBody().style.whiteSpace="nowrap"}if(v.handle_node_change_callback){q.onNodeChange.add(function(t,s,z){q.execCallback("handle_node_change_callback",q.id,z,-1,-1,true,q.selection.isCollapsed())})}if(v.save_callback){q.onSaveContent.add(function(s,z){var t=q.execCallback("save_callback",q.id,z.content,q.getBody());if(t){z.content=t}})}if(v.onchange_callback){q.onChange.add(function(t,s){q.execCallback("onchange_callback",q,s)})}if(v.protect){q.onBeforeSetContent.add(function(s,t){if(v.protect){i(v.protect,function(z){t.content=t.content.replace(z,function(A){return"<!--mce:protected "+escape(A)+"-->"})})}})}if(v.convert_newlines_to_brs){q.onBeforeSetContent.add(function(s,t){if(t.initial){t.content=t.content.replace(/\r?\n/g,"<br />")}})}if(v.preformatted){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^\s*<pre.*?>/,"");t.content=t.content.replace(/<\/pre>\s*$/,"");if(t.set){t.content='<pre class="mceItemHidden">'+t.content+"</pre>"}})}if(v.verify_css_classes){q.serializer.attribValueFilter=function(B,z){var A,t;if(B=="class"){if(!q.classesRE){t=q.dom.getClasses();if(t.length>0){A="";i(t,function(s){A+=(A?"|":"")+s["class"]});q.classesRE=new RegExp("("+A+")","gi")}}return !q.classesRE||/(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(z)||q.classesRE.test(z)?z:""}return z}}if(v.cleanup_callback){q.onBeforeSetContent.add(function(s,t){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)});q.onPreProcess.add(function(s,t){if(t.set){q.execCallback("cleanup_callback","insert_to_editor_dom",t.node,t)}if(t.get){q.execCallback("cleanup_callback","get_from_editor_dom",t.node,t)}});q.onPostProcess.add(function(s,t){if(t.set){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)}if(t.get){t.content=q.execCallback("cleanup_callback","get_from_editor",t.content,t)}})}if(v.save_callback){q.onGetContent.add(function(s,t){if(t.save){t.content=q.execCallback("save_callback",q.id,t.content,q.getBody())}})}if(v.handle_event_callback){q.onEvent.add(function(s,t,z){if(q.execCallback("handle_event_callback",t,s,z)===false){j.cancel(t)}})}q.onSetContent.add(function(){q.addVisual(q.getBody())});if(v.padd_empty_editor){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")})}if(a){function r(s,t){i(s.dom.select("a"),function(A){var z=A.parentNode;if(s.dom.isBlock(z)&&z.lastChild===A){s.dom.add(z,"br",{"data-mce-bogus":1})}})}q.onExecCommand.add(function(s,t){if(t==="CreateLink"){r(s)}});q.onSetContent.add(q.selection.onSetContent.add(r))}q.load({initial:true,format:"html"});q.startContent=q.getContent({format:"raw"});q.undoManager.add();q.initialized=true;q.onInit.dispatch(q);q.execCallback("setupcontent_callback",q.id,q.getBody(),q.getDoc());q.execCallback("init_instance_callback",q);q.focus(true);q.nodeChanged({initial:1});i(q.contentCSS,function(s){q.dom.loadCSS(s)});if(v.auto_focus){setTimeout(function(){var s=m.get(v.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}x=null},focus:function(u){var y,q=this,s=q.selection,x=q.settings.content_editable,r,p,v=q.getDoc();if(!u){r=s.getRng();if(r.item){p=r.item(0)}q._refreshContentEditable();s.normalize();if(!x){q.getWin().focus()}if(m.isGecko){q.getBody().focus()}if(p&&p.ownerDocument==v){r=v.body.createControlRange();r.addElement(p);r.select()}}if(m.activeEditor!=q){if((y=m.activeEditor)!=null){y.onDeactivate.dispatch(y,q)}q.onActivate.dispatch(q,y)}m._setActive(q)},execCallback:function(u){var p=this,r=p.settings[u],q;if(!r){return}if(p.callbackLookup&&(q=p.callbackLookup[u])){r=q.func;q=q.scope}if(d(r,"string")){q=r.replace(/\.\w+$/,"");q=q?m.resolve(q):0;r=m.resolve(r);p.callbackLookup=p.callbackLookup||{};p.callbackLookup[u]={func:r,scope:q}}return r.apply(q||p,Array.prototype.slice.call(arguments,1))},translate:function(p){var r=this.settings.language||"en",q=m.i18n;if(!p){return""}return q[r+"."+p]||p.replace(/{\#([^}]+)\}/g,function(t,s){return q[r+"."+s]||"{#"+s+"}"})},getLang:function(q,p){return m.i18n[(this.settings.language||"en")+"."+q]||(d(p)?p:"{#"+q+"}")},getParam:function(u,r,p){var s=m.trim,q=d(this.settings[u])?this.settings[u]:r,t;if(p==="hash"){t={};if(d(q,"string")){i(q.indexOf("=")>0?q.split(/[;,](?![^=;,]*(?:[;,]|$))/):q.split(","),function(x){x=x.split("=");if(x.length>1){t[s(x[0])]=s(x[1])}else{t[s(x[0])]=s(x)}})}else{t=q}return t}return q},nodeChanged:function(r){var p=this,q=p.selection,u=q.getStart()||p.getBody();if(p.initialized){r=r||{};u=b&&u.ownerDocument!=p.getDoc()?p.getBody():u;r.parents=[];p.dom.getParent(u,function(s){if(s.nodeName=="BODY"){return true}r.parents.push(s)});p.onNodeChange.dispatch(p,r?r.controlManager||p.controlManager:p.controlManager,u,q.isCollapsed(),r)}},addButton:function(r,q){var p=this;p.buttons=p.buttons||{};p.buttons[r]=q},addCommand:function(p,r,q){this.execCommands[p]={func:r,scope:q||this}},addQueryStateHandler:function(p,r,q){this.queryStateCommands[p]={func:r,scope:q||this}},addQueryValueHandler:function(p,r,q){this.queryValueCommands[p]={func:r,scope:q||this}},addShortcut:function(r,u,p,s){var q=this,v;if(!q.settings.custom_shortcuts){return false}q.shortcuts=q.shortcuts||{};if(d(p,"string")){v=p;p=function(){q.execCommand(v,false,null)}}if(d(p,"object")){v=p;p=function(){q.execCommand(v[0],v[1],v[2])}}i(g(r),function(t){var x={func:p,scope:s||this,desc:u,alt:false,ctrl:false,shift:false};i(g(t,"+"),function(y){switch(y){case"alt":case"ctrl":case"shift":x[y]=true;break;default:x.charCode=y.charCodeAt(0);x.keyCode=y.toUpperCase().charCodeAt(0)}});q.shortcuts[(x.ctrl?"ctrl":"")+","+(x.alt?"alt":"")+","+(x.shift?"shift":"")+","+x.keyCode]=x});return true},execCommand:function(x,v,z,p){var r=this,u=0,y,q;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(x)&&(!p||!p.skip_focus)){r.focus()}y={};r.onBeforeExecCommand.dispatch(r,x,v,z,y);if(y.terminate){return false}if(r.execCallback("execcommand_callback",r.id,r.selection.getNode(),x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(y=r.execCommands[x]){q=y.func.call(y.scope,v,z);if(q!==true){r.onExecCommand.dispatch(r,x,v,z,p);return q}}i(r.plugins,function(s){if(s.execCommand&&s.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);u=1;return false}});if(u){return true}if(r.theme&&r.theme.execCommand&&r.theme.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(r.editorCommands.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}r.getDoc().execCommand(x,v,z);r.onExecCommand.dispatch(r,x,v,z,p)},queryCommandState:function(u){var q=this,v,r;if(q._isHidden()){return}if(v=q.queryStateCommands[u]){r=v.func.call(v.scope);if(r!==true){return r}}v=q.editorCommands.queryCommandState(u);if(v!==-1){return v}try{return this.getDoc().queryCommandState(u)}catch(p){}},queryCommandValue:function(v){var q=this,u,r;if(q._isHidden()){return}if(u=q.queryValueCommands[v]){r=u.func.call(u.scope);if(r!==true){return r}}u=q.editorCommands.queryCommandValue(v);if(d(u)){return u}try{return this.getDoc().queryCommandValue(v)}catch(p){}},show:function(){var p=this;n.show(p.getContainer());n.hide(p.id);p.load()},hide:function(){var p=this,q=p.getDoc();if(b&&q){q.execCommand("SelectAll")}p.save();n.hide(p.getContainer());n.setStyle(p.id,"display",p.orgDisplay)},isHidden:function(){return !n.isHidden(this.id)},setProgressState:function(p,q,r){this.onSetProgressState.dispatch(this,p,q,r);return p},load:function(s){var p=this,r=p.getElement(),q;if(r){s=s||{};s.load=true;q=p.setContent(d(r.value)?r.value:r.innerHTML,s);s.element=r;if(!s.no_events){p.onLoadContent.dispatch(p,s)}s.element=r=null;return q}},save:function(u){var p=this,s=p.getElement(),q,r;if(!s||!p.initialized){return}u=u||{};u.save=true;if(!u.no_events){p.undoManager.typing=false;p.undoManager.add()}u.element=s;q=u.content=p.getContent(u);if(!u.no_events){p.onSaveContent.dispatch(p,u)}q=u.content;if(!/TEXTAREA|INPUT/i.test(s.nodeName)){s.innerHTML=q;if(r=n.getParent(p.id,"form")){i(r.elements,function(t){if(t.name==p.id){t.value=q;return false}})}}else{s.value=q}u.element=s=null;return q},setContent:function(u,s){var r=this,q,p=r.getBody(),t;s=s||{};s.format=s.format||"html";s.set=true;s.content=u;if(!s.no_events){r.onBeforeSetContent.dispatch(r,s)}u=s.content;if(!m.isIE&&(u.length===0||/^\s+$/.test(u))){t=r.settings.forced_root_block;if(t){u="<"+t+'><br data-mce-bogus="1"></'+t+">"}else{u='<br data-mce-bogus="1">'}p.innerHTML=u;r.selection.select(p,true);r.selection.collapse(true);return}if(s.format!=="raw"){u=new m.html.Serializer({},r.schema).serialize(r.parser.parse(u))}s.content=m.trim(u);r.dom.setHTML(p,s.content);if(!s.no_events){r.onSetContent.dispatch(r,s)}r.selection.normalize();return s.content},getContent:function(q){var p=this,r;q=q||{};q.format=q.format||"html";q.get=true;if(!q.no_events){p.onBeforeGetContent.dispatch(p,q)}if(q.format=="raw"){r=p.getBody().innerHTML}else{r=p.serializer.serialize(p.getBody(),q)}q.content=m.trim(r);if(!q.no_events){p.onGetContent.dispatch(p,q)}return q.content},isDirty:function(){var p=this;return m.trim(p.startContent)!=m.trim(p.getContent({format:"raw",no_events:1}))&&!p.isNotDirty},getContainer:function(){var p=this;if(!p.container){p.container=n.get(p.editorContainer||p.id+"_parent")}return p.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return n.get(this.settings.content_element||this.id)},getWin:function(){var p=this,q;if(!p.contentWindow){q=n.get(p.id+"_if