write-js.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
  2. <?php \Typecho\Plugin::factory('admin/write-js.php')->write(); ?>
  3. <?php \Widget\Metas\Tag\Cloud::alloc('sort=count&desc=1&limit=200')->to($tags); ?>
  4. <script src="<?php $options->adminStaticUrl('js', 'timepicker.js'); ?>"></script>
  5. <script src="<?php $options->adminStaticUrl('js', 'tokeninput.js'); ?>"></script>
  6. <script>
  7. $(document).ready(function() {
  8. // 日期时间控件
  9. $('#date').mask('9999-99-99 99:99').datetimepicker({
  10. currentText : '<?php _e('现在'); ?>',
  11. prevText : '<?php _e('上一月'); ?>',
  12. nextText : '<?php _e('下一月'); ?>',
  13. monthNames : ['<?php _e('一月'); ?>', '<?php _e('二月'); ?>', '<?php _e('三月'); ?>', '<?php _e('四月'); ?>',
  14. '<?php _e('五月'); ?>', '<?php _e('六月'); ?>', '<?php _e('七月'); ?>', '<?php _e('八月'); ?>',
  15. '<?php _e('九月'); ?>', '<?php _e('十月'); ?>', '<?php _e('十一月'); ?>', '<?php _e('十二月'); ?>'],
  16. dayNames : ['<?php _e('星期日'); ?>', '<?php _e('星期一'); ?>', '<?php _e('星期二'); ?>',
  17. '<?php _e('星期三'); ?>', '<?php _e('星期四'); ?>', '<?php _e('星期五'); ?>', '<?php _e('星期六'); ?>'],
  18. dayNamesShort : ['<?php _e('周日'); ?>', '<?php _e('周一'); ?>', '<?php _e('周二'); ?>', '<?php _e('周三'); ?>',
  19. '<?php _e('周四'); ?>', '<?php _e('周五'); ?>', '<?php _e('周六'); ?>'],
  20. dayNamesMin : ['<?php _e('日'); ?>', '<?php _e('一'); ?>', '<?php _e('二'); ?>', '<?php _e('三'); ?>',
  21. '<?php _e('四'); ?>', '<?php _e('五'); ?>', '<?php _e('六'); ?>'],
  22. closeText : '<?php _e('完成'); ?>',
  23. timeOnlyTitle : '<?php _e('选择时间'); ?>',
  24. timeText : '<?php _e('时间'); ?>',
  25. hourText : '<?php _e('时'); ?>',
  26. amNames : ['<?php _e('上午'); ?>', 'A'],
  27. pmNames : ['<?php _e('下午'); ?>', 'P'],
  28. minuteText : '<?php _e('分'); ?>',
  29. secondText : '<?php _e('秒'); ?>',
  30. dateFormat : 'yy-mm-dd',
  31. timezone : <?php $options->timezone(); ?> / 60,
  32. hour : (new Date()).getHours(),
  33. minute : (new Date()).getMinutes()
  34. });
  35. // 聚焦
  36. $('#title').select();
  37. // text 自动拉伸
  38. Typecho.editorResize('text', '<?php $security->index('/action/ajax?do=editorResize'); ?>');
  39. // tag autocomplete 提示
  40. var tags = $('#tags'), tagsPre = [];
  41. if (tags.length > 0) {
  42. var items = tags.val().split(','), result = [];
  43. for (var i = 0; i < items.length; i ++) {
  44. var tag = items[i];
  45. if (!tag) {
  46. continue;
  47. }
  48. tagsPre.push({
  49. id : tag,
  50. tags : tag
  51. });
  52. }
  53. tags.tokenInput(<?php
  54. $data = array();
  55. while ($tags->next()) {
  56. $data[] = array(
  57. 'id' => $tags->name,
  58. 'tags' => $tags->name
  59. );
  60. }
  61. echo json_encode($data);
  62. ?>, {
  63. propertyToSearch: 'tags',
  64. tokenValue : 'tags',
  65. searchDelay : 0,
  66. preventDuplicates : true,
  67. animateDropdown : false,
  68. hintText : '<?php _e('请输入标签名'); ?>',
  69. noResultsText : '<?php _e('此标签不存在, 按回车创建'); ?>',
  70. prePopulate : tagsPre,
  71. onResult : function (result, query, val) {
  72. if (!query) {
  73. return result;
  74. }
  75. if (!result) {
  76. result = [];
  77. }
  78. if (!result[0] || result[0]['id'] != query) {
  79. result.unshift({
  80. id : val,
  81. tags : val
  82. });
  83. }
  84. return result.slice(0, 5);
  85. }
  86. });
  87. // tag autocomplete 提示宽度设置
  88. $('#token-input-tags').focus(function() {
  89. var t = $('.token-input-dropdown'),
  90. offset = t.outerWidth() - t.width();
  91. t.width($('.token-input-list').outerWidth() - offset);
  92. });
  93. }
  94. // 缩略名自适应宽度
  95. var slug = $('#slug');
  96. if (slug.length > 0) {
  97. var wrap = $('<div />').css({
  98. 'position' : 'relative',
  99. 'display' : 'inline-block'
  100. }),
  101. justifySlug = $('<pre />').css({
  102. 'display' : 'block',
  103. 'visibility': 'hidden',
  104. 'height' : slug.height(),
  105. 'padding' : '0 2px',
  106. 'margin' : 0
  107. }).insertAfter(slug.wrap(wrap).css({
  108. 'left' : 0,
  109. 'top' : 0,
  110. 'minWidth' : '5px',
  111. 'position' : 'absolute',
  112. 'width' : '100%'
  113. })), originalWidth = slug.width();
  114. function justifySlugWidth() {
  115. var val = slug.val();
  116. justifySlug.text(val.length > 0 ? val : ' ');
  117. }
  118. slug.bind('input propertychange', justifySlugWidth);
  119. justifySlugWidth();
  120. }
  121. // 原始的插入图片和文件
  122. Typecho.insertFileToEditor = function (file, url, isImage) {
  123. var textarea = $('#text'), sel = textarea.getSelection(),
  124. html = isImage ? '<img src="' + url + '" alt="' + file + '" />'
  125. : '<a href="' + url + '">' + file + '</a>',
  126. offset = (sel ? sel.start : 0) + html.length;
  127. textarea.replaceSelection(html);
  128. textarea.setSelection(offset, offset);
  129. };
  130. var submitted = false, form = $('form[name=write_post],form[name=write_page]').submit(function () {
  131. submitted = true;
  132. }), formAction = form.attr('action'),
  133. idInput = $('input[name=cid]'),
  134. cid = idInput.val(),
  135. draft = $('input[name=draft]'),
  136. draftId = draft.length > 0 ? draft.val() : 0,
  137. btnSave = $('#btn-save').removeAttr('name').removeAttr('value'),
  138. btnSubmit = $('#btn-submit').removeAttr('name').removeAttr('value'),
  139. btnPreview = $('#btn-preview'),
  140. doAction = $('<input type="hidden" name="do" value="publish" />').appendTo(form),
  141. locked = false,
  142. changed = false,
  143. autoSave = $('<span id="auto-save-message" class="left"></span>').prependTo('.submit'),
  144. lastSaveTime = null;
  145. $(':input', form).bind('input change', function (e) {
  146. var tagName = $(this).prop('tagName');
  147. if (tagName.match(/(input|textarea)/i) && e.type == 'change') {
  148. return;
  149. }
  150. changed = true;
  151. });
  152. form.bind('field', function () {
  153. changed = true;
  154. });
  155. // 发送保存请求
  156. function saveData(cb) {
  157. function callback(o) {
  158. lastSaveTime = o.time;
  159. cid = o.cid;
  160. draftId = o.draftId;
  161. idInput.val(cid);
  162. autoSave.text('<?php _e('已保存'); ?>' + ' (' + o.time + ')').effect('highlight', 1000);
  163. locked = false;
  164. btnSave.removeAttr('disabled');
  165. btnPreview.removeAttr('disabled');
  166. if (!!cb) {
  167. cb(o)
  168. }
  169. }
  170. changed = false;
  171. btnSave.attr('disabled', 'disabled');
  172. btnPreview.attr('disabled', 'disabled');
  173. autoSave.text('<?php _e('正在保存'); ?>');
  174. if (typeof FormData !== 'undefined') {
  175. var data = new FormData(form.get(0));
  176. data.append('do', 'save');
  177. $.ajax({
  178. url: formAction,
  179. processData: false,
  180. contentType: false,
  181. type: 'POST',
  182. data: data,
  183. success: callback
  184. });
  185. } else {
  186. var data = form.serialize() + '&do=save';
  187. $.post(formAction, data, callback, 'json');
  188. }
  189. }
  190. // 计算夏令时偏移
  191. var dstOffset = (function () {
  192. var d = new Date(),
  193. jan = new Date(d.getFullYear(), 0, 1),
  194. jul = new Date(d.getFullYear(), 6, 1),
  195. stdOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
  196. return stdOffset - d.getTimezoneOffset();
  197. })();
  198. if (dstOffset > 0) {
  199. $('<input name="dst" type="hidden" />').appendTo(form).val(dstOffset);
  200. }
  201. // 时区
  202. $('<input name="timezone" type="hidden" />').appendTo(form).val(- (new Date).getTimezoneOffset() * 60);
  203. // 自动保存
  204. <?php if ($options->autoSave): ?>
  205. var autoSaveOnce = !!cid;
  206. function autoSaveListener () {
  207. setInterval(function () {
  208. if (changed && !locked) {
  209. locked = true;
  210. saveData();
  211. }
  212. }, 10000);
  213. }
  214. if (autoSaveOnce) {
  215. autoSaveListener();
  216. }
  217. $('#text').bind('input propertychange', function () {
  218. if (!locked) {
  219. autoSave.text('<?php _e('尚未保存'); ?>' + (lastSaveTime ? ' (<?php _e('上次保存时间'); ?>: ' + lastSaveTime + ')' : ''));
  220. }
  221. if (!autoSaveOnce) {
  222. autoSaveOnce = true;
  223. autoSaveListener();
  224. }
  225. });
  226. <?php endif; ?>
  227. // 自动检测离开页
  228. $(window).bind('beforeunload', function () {
  229. if (changed && !submitted) {
  230. return '<?php _e('内容已经改变尚未保存, 您确认要离开此页面吗?'); ?>';
  231. }
  232. });
  233. // 预览功能
  234. var isFullScreen = false;
  235. function previewData(cid) {
  236. isFullScreen = $(document.body).hasClass('fullscreen');
  237. $(document.body).addClass('fullscreen preview');
  238. var frame = $('<iframe frameborder="0" class="preview-frame preview-loading"></iframe>')
  239. .attr('src', './preview.php?cid=' + cid)
  240. .attr('sandbox', 'allow-same-origin allow-scripts')
  241. .appendTo(document.body);
  242. frame.load(function () {
  243. frame.removeClass('preview-loading');
  244. });
  245. frame.height($(window).height() - 53);
  246. }
  247. function cancelPreview() {
  248. if (submitted) {
  249. return;
  250. }
  251. if (!isFullScreen) {
  252. $(document.body).removeClass('fullscreen');
  253. }
  254. $(document.body).removeClass('preview');
  255. $('.preview-frame').remove();
  256. };
  257. $('#btn-cancel-preview').click(cancelPreview);
  258. $(window).bind('message', function (e) {
  259. if (e.originalEvent.data == 'cancelPreview') {
  260. cancelPreview();
  261. }
  262. });
  263. btnPreview.click(function () {
  264. if (changed) {
  265. locked = true;
  266. if (confirm('<?php _e('修改后的内容需要保存后才能预览, 是否保存?'); ?>')) {
  267. saveData(function (o) {
  268. previewData(o.draftId);
  269. });
  270. } else {
  271. locked = false;
  272. }
  273. } else if (!!draftId) {
  274. previewData(draftId);
  275. } else if (!!cid) {
  276. previewData(cid);
  277. }
  278. });
  279. btnSave.click(function () {
  280. doAction.attr('value', 'save');
  281. });
  282. btnSubmit.click(function () {
  283. doAction.attr('value', 'publish');
  284. });
  285. // 控制选项和附件的切换
  286. var fileUploadInit = false;
  287. $('#edit-secondary .typecho-option-tabs li').click(function() {
  288. $('#edit-secondary .typecho-option-tabs li').removeClass('active');
  289. $(this).addClass('active');
  290. $(this).parents('#edit-secondary').find('.tab-content').addClass('hidden');
  291. var selected_tab = $(this).find('a').attr('href'),
  292. selected_el = $(selected_tab).removeClass('hidden');
  293. if (!fileUploadInit) {
  294. selected_el.trigger('init');
  295. fileUploadInit = true;
  296. }
  297. return false;
  298. });
  299. // 高级选项控制
  300. $('#advance-panel-btn').click(function() {
  301. $('#advance-panel').toggle();
  302. return false;
  303. });
  304. // 自动隐藏密码框
  305. $('#visibility').change(function () {
  306. var val = $(this).val(), password = $('#post-password');
  307. if ('password' == val) {
  308. password.removeClass('hidden');
  309. } else {
  310. password.addClass('hidden');
  311. }
  312. });
  313. // 草稿删除确认
  314. $('.edit-draft-notice a').click(function () {
  315. if (confirm('<?php _e('您确认要删除这份草稿吗?'); ?>')) {
  316. window.location.href = $(this).attr('href');
  317. }
  318. return false;
  319. });
  320. });
  321. </script>