/* jshint browser: true, jquery: true */ /* Author: Sotaro KARASAWA */ var jsdiff = require('diff'); var io = require('socket.io-client'); //require('bootstrap-sass'); //require('jquery.cookie'); var Crowi = {}; if (!window) { window = {}; } window.Crowi = Crowi; Crowi.createErrorView = function(msg) { $('#main').prepend($('

' + msg + '

')); }; Crowi.linkPath = function(revisionPath) { var $revisionPath = revisionPath || '#revision-path'; var $title = $($revisionPath); var pathData = $('#content-main').data('path'); if (!pathData) { return ; } var realPath = pathData.trim(); if (realPath.substr(-1, 1) == '/') { realPath = realPath.substr(0, realPath.length - 1); } var path = ''; var pathHtml = ''; var splittedPath = realPath.split(/\//); splittedPath.shift(); splittedPath.forEach(function(sub) { path += '/'; pathHtml += ' / '; if (sub) { path += sub; pathHtml += '' + Crowi.escape(sub) + ''; } }); if (path.substr(-1, 1) != '/') { path += '/'; pathHtml += ' /'; } $title.html(pathHtml); }; Crowi.correctHeaders = function(contentId) { // h1 ~ h6 の id 名を補正する var $content = $(contentId || '#revision-body-content'); var i = 0; $('h1,h2,h3,h4,h5,h6', $content).each(function(idx, elm) { var id = 'head' + i++; $(this).attr('id', id); $(this).addClass('revision-head'); $(this).append(''); }); }; Crowi.revisionToc = function(contentId, tocId) { var $content = $(contentId || '#revision-body-content'); var $tocId = $(tocId || '#revision-toc'); var $tocContent = $('
'); $tocId.append($tocContent); $('h1', $content).each(function(idx, elm) { var id = $(this).attr('id'); var title = $(this).text(); var selector = '#' + id + ' ~ h2:not(#' + id + ' ~ h1 ~ h2)'; var $toc = $(''); var $tocLi = $('
  • ' + title + '
  • '); $tocContent.append($toc); $toc.append($tocLi); $(selector).each(function() { var id2 = $(this).attr('id'); var title2 = $(this).text(); var selector2 = '#' + id2 + ' ~ h3:not(#' + id2 + ' ~ h2 ~ h3)'; var $toc2 = $(''); var $tocLi2 = $('
  • ' + title2 + '
  • '); $tocLi.append($toc2); $toc2.append($tocLi2); $(selector2).each(function() { var id3 = $(this).attr('id'); var title3 = $(this).text(); var $toc3 = $(''); var $tocLi3 = $('
  • ' + title3 + '
  • '); $tocLi2.append($toc3); $toc3.append($tocLi3); }); }); }); }; Crowi.escape = function(s) { s = s.replace(/&/g, '&') .replace(//g, '>') .replace(/'/g, ''') .replace(/"/g, '"') ; return s; }; Crowi.unescape = function(s) { s = s.replace(/ /g, ' ') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/'/g, '\'') .replace(/"/g, '"') ; return s; }; // original: middleware.swigFilter Crowi.userPicture = function (user) { if (!user) { return '/images/userpicture.png'; } if (user.image && user.image != '/images/userpicture.png') { return user.image; } else { return '/images/userpicture.png'; } }; Crowi.modifyScrollTop = function() { var offset = 10; var hash = window.location.hash; if (hash === "") { return; } var pageHeader = document.querySelector('#page-header'); if (!pageHeader) { return; } var pageHeaderRect = pageHeader.getBoundingClientRect(); var sectionHeader = document.querySelector(hash); if (sectionHeader === null) { return; } var timeout = 0; if (window.scrollY === 0) { timeout = 200; } setTimeout(function() { var sectionHeaderRect = sectionHeader.getBoundingClientRect(); if (sectionHeaderRect.top >= pageHeaderRect.bottom) { return; } window.scrollTo(0, (window.scrollY - pageHeaderRect.height - offset)); }, timeout); } $(function() { var pageId = $('#content-main').data('page-id'); var revisionId = $('#content-main').data('page-revision-id'); var revisionCreatedAt = $('#content-main').data('page-revision-created'); var currentUser = $('#content-main').data('current-user'); var isSeen = $('#content-main').data('page-is-seen'); var pagePath= $('#content-main').data('path'); Crowi.linkPath(); $('[data-toggle="popover"]').popover(); $('[data-toggle="tooltip"]').tooltip(); $('[data-tooltip-stay]').tooltip('show'); $('#toggle-sidebar').click(function(e) { var $mainContainer = $('.main-container'); if ($mainContainer.hasClass('aside-hidden')) { $('.main-container').removeClass('aside-hidden'); $.cookie('aside-hidden', 0, { expires: 30, path: '/' }); } else { $mainContainer.addClass('aside-hidden'); $.cookie('aside-hidden', 1, { expires: 30, path: '/' }); } return false; }); if ($.cookie('aside-hidden') == 1) { $('.main-container').addClass('aside-hidden'); } $('.copy-link').on('click', function () { $(this).select(); }); $('#create-page').on('shown.bs.modal', function (e) { var input2Width = $('#create-page-today .page-today-input2').outerWidth(); var newWidth = input2Width - $('#create-page-today .page-today-prefix').outerWidth() - $('#create-page-today .page-today-input1').outerWidth() - $('#create-page-today .page-today-suffix').outerWidth() - 10 ; $('#create-page-today .form-control.page-today-input2').css({width: newWidth}).focus(); }); $('#create-page-today').submit(function(e) { var prefix1 = $('input.page-today-input1', this).data('prefix'); var input1 = $('input.page-today-input1', this).val(); var prefix2 = $('input.page-today-input2', this).data('prefix'); var input2 = $('input.page-today-input2', this).val(); if (input1 === '') { prefix1 = 'メモ'; } if (input2 === '') { prefix2 = prefix2.slice(0, -1); } top.location.href = prefix1 + input1 + prefix2 + input2; return false; }); $('#create-page-under-tree').submit(function(e) { var name = $('input', this).val(); if (!name.match(/^\//)) { name = '/' + name; } if (name.match(/.+\/$/)) { name = name.substr(0, name.length - 1); } top.location.href = name; return false; }); // rename $('#renamePage').on('shown.bs.modal', function (e) { $('#newPageName').focus(); }); $('#renamePageForm, #unportalize-form').submit(function(e) { $.ajax({ type: 'POST', url: '/_api/pages.rename', data: $(this).serialize(), dataType: 'json' }).done(function(res) { if (!res.ok) { $('#newPageNameCheck').html(' ' + res.error); $('#newPageNameCheck').addClass('alert-danger'); } else { var page = res.page; $('#newPageNameCheck').removeClass('alert-danger'); $('#newPageNameCheck').html(' 移動しました。移動先にジャンプします。'); setTimeout(function() { top.location.href = page.path + '?renamed=' + pagePath; }, 1000); } }); return false; }); // delete $('#delete-page-form').submit(function(e) { $.ajax({ type: 'POST', url: '/_api/pages.remove', data: $('#delete-page-form').serialize(), dataType: 'json' }).done(function(res) { if (!res.ok) { $('#delete-errors').html(' ' + res.error); $('#delete-errors').addClass('alert-danger'); } else { var page = res.page; top.location.href = page.path; } }); return false; }); $('#revert-delete-page-form').submit(function(e) { $.ajax({ type: 'POST', url: '/_api/pages.revertRemove', data: $('#revert-delete-page-form').serialize(), dataType: 'json' }).done(function(res) { if (!res.ok) { $('#delete-errors').html(' ' + res.error); $('#delete-errors').addClass('alert-danger'); } else { var page = res.page; top.location.href = page.path; } }); return false; }); $('#create-portal-button').on('click', function(e) { $('.portal').removeClass('hide'); $('.content-main').addClass('on-edit'); $('.portal a[data-toggle="tab"][href="#edit-form"]').tab('show'); var path = $('.content-main').data('path'); if (path != '/' && $('.content-main').data('page-id') == '') { var upperPage = path.substr(0, path.length - 1); $.get('/_api/pages.get', {path: upperPage}, function(res) { if (res.ok && res.page) { $('#portal-warning-modal').modal('show'); } }); } }); $('#portal-form-close').on('click', function(e) { $('.portal').addClass('hide'); $('.content-main').removeClass('on-edit'); return false; }); // list-link $('.page-list-link').each(function() { var $link = $(this); var text = $link.text(); var path = $link.data('path'); var shortPath = new String($link.data('short-path')); var escape = function(s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); }; path = Crowi.escape(path); var pattern = escape(Crowi.escape(shortPath)) + '(/)?$'; $link.html(path.replace(new RegExp(pattern), '' + shortPath + '$1')); }); // for list page $('a[data-toggle="tab"][href="#view-timeline"]').on('show.bs.tab', function() { var isShown = $('#view-timeline').data('shown'); if (isShown == 0) { $('#view-timeline .timeline-body').each(function() { var id = $(this).attr('id'); var contentId = '#' + id + ' > script'; var revisionBody = '#' + id + ' .revision-body'; var revisionPath = '#' + id + ' .revision-path'; var markdown = Crowi.unescape($(contentId).html()); var parsedHTML = crowiRenderer.render(markdown); $(revisionBody).html(parsedHTML); $('.template-create-button', revisionBody).on('click', function() { var path = $(this).data('path'); var templateId = $(this).data('template'); var template = $('#' + templateId).html(); crowi.saveDraft(path, template); top.location.href = path; }); }); $('#view-timeline').data('shown', 1); } }); // login $('#register').on('click', function() { $('#login-dialog').addClass('to-flip'); return false; }); $('#login').on('click', function() { $('#login-dialog').removeClass('to-flip'); return false; }); $('#register-form input[name="registerForm[username]"]').change(function(e) { var username = $(this).val(); $('#input-group-username').removeClass('has-error'); $('#help-block-username').html(""); $.getJSON('/_api/check_username', {username: username}, function(json) { if (!json.valid) { $('#help-block-username').html('このユーザーIDは利用できません。
    '); $('#input-group-username').addClass('has-error'); } }); }); if (pageId) { // if page exists var $rawTextOriginal = $('#raw-text-original'); if ($rawTextOriginal.length > 0) { var markdown = Crowi.unescape($('#raw-text-original').html()); var parsedHTML = crowiRenderer.render(markdown); $('#revision-body-content').html(parsedHTML); $('.template-create-button').on('click', function() { var path = $(this).data('path'); var templateId = $(this).data('template'); var template = $('#' + templateId).html(); crowi.saveDraft(path, template); top.location.href = path; }); Crowi.correctHeaders('#revision-body-content'); Crowi.revisionToc('#revision-body-content', '#revision-toc'); } // header var $header = $('#page-header'); if ($header.length > 0) { var headerHeight = $header.outerHeight(true); $('.header-wrap').css({height: (headerHeight + 16) + 'px'}); $header.affix({ offset: { top: function() { return headerHeight + 86; // (54 header + 16 header padding-top + 16 content padding-top) } } }); $('[data-affix-disable]').on('click', function(e) { var $elm = $($(this).data('affix-disable')); $(window).off('.affix'); $elm.removeData('affix').removeClass('affix affix-top affix-bottom'); return false; }); } // omg function createCommentHTML(revision, creator, comment, commentedAt) { var $comment = $('
    '); var $commentImage = $('') .attr('src', Crowi.userPicture(creator)); var $commentCreator = $('
    ') .text(creator.username); var $commentRevision = $('') .attr('href', '?revision=' + revision) .text(revision.substr(0,8)); if (revision !== revisionId) { $commentRevision.addClass('label-default'); } else { $commentRevision.addClass('label-primary'); } var $commentMeta = $('
    ') .text(commentedAt + ' ') .append($commentRevision); var $commentBody = $('
    ') .html(comment.replace(/(\r\n|\r|\n)/g, '
    ')); var $commentMain = $('
    ') .append($commentCreator) .append($commentBody) .append($commentMeta) $comment.addClass('page-comment'); if (creator._id === currentUser) { $comment.addClass('page-comment-me'); } if (revision !== revisionId) { $comment.addClass('page-comment-old'); } $comment .append($commentImage) .append($commentMain); return $comment; } // get comments var $pageCommentList = $('.page-comments-list'); var $pageCommentListNewer = $('#page-comments-list-newer'); var $pageCommentListCurrent = $('#page-comments-list-current'); var $pageCommentListOlder = $('#page-comments-list-older'); var hasNewer = false; var hasOlder = false; $.get('/_api/comments.get', {page_id: pageId}, function(res) { if (res.ok) { var comments = res.comments; $.each(comments, function(i, comment) { var commentContent = createCommentHTML(comment.revision, comment.creator, comment.comment, comment.createdAt); if (comment.revision == revisionId) { $pageCommentListCurrent.append(commentContent); } else { if (Date.parse(comment.createdAt)/1000 > revisionCreatedAt) { $pageCommentListNewer.append(commentContent); hasNewer = true; } else { $pageCommentListOlder.append(commentContent); hasOlder = true; } } }); } }).fail(function(data) { }).always(function() { if (!hasNewer) { $('.page-comments-list-toggle-newer').hide(); } if (!hasOlder) { $pageCommentListOlder.addClass('collapse'); $('.page-comments-list-toggle-older').hide(); } }); // post comment event $('#page-comment-form').on('submit', function() { var $button = $('#comment-form-button'); $button.attr('disabled', 'disabled'); $.post('/_api/comments.add', $(this).serialize(), function(data) { $button.removeAttr('disabled'); if (data.ok) { var comment = data.comment; $pageCommentList.prepend(createCommentHTML(comment.revision, comment.creator, comment.comment, comment.createdAt)); $('#comment-form-comment').val(''); $('#comment-form-message').text(''); } else { $('#comment-form-message').text(data.error); } }).fail(function(data) { if (data.status !== 200) { $('#comment-form-message').text(data.statusText); } }); return false; }); // attachment var $pageAttachmentList = $('.page-attachments ul'); $.get('/_api/attachment/page/' + pageId, function(res) { var attachments = res.data.attachments; if (attachments.length > 0) { $.each(attachments, function(i, file) { $pageAttachmentList.append( '
  • ' + (file.originalName || file.fileName) + ' ' + file.fileFormat + '
  • ' ); }) } else { $('.page-attachments').remove(); } }); // bookmark var $bookmarkButton = $('#bookmark-button'); $.get('/_api/bookmarks.get', {page_id: pageId}, function(res) { if (res.ok) { if (res.bookmark) { MarkBookmarked(); } } }); $bookmarkButton.click(function() { var bookmarked = $bookmarkButton.data('bookmarked'); var token = $bookmarkButton.data('csrftoken'); if (!bookmarked) { $.post('/_api/bookmarks.add', {_csrf: token, page_id: pageId}, function(res) { if (res.ok && res.bookmark) { MarkBookmarked(); } }); } else { $.post('/_api/bookmarks.remove', {_csrf: token, page_id: pageId}, function(res) { if (res.ok) { MarkUnBookmarked(); } }); } return false; }); function MarkBookmarked() { $('i', $bookmarkButton) .removeClass('fa-star-o') .addClass('fa-star'); $bookmarkButton.data('bookmarked', 1); } function MarkUnBookmarked() { $('i', $bookmarkButton) .removeClass('fa-star') .addClass('fa-star-o'); $bookmarkButton.data('bookmarked', 0); } // Like var $likeButton = $('#like-button'); var $likeCount = $('#like-count'); $likeButton.click(function() { var liked = $likeButton.data('liked'); var token = $likeButton.data('csrftoken'); if (!liked) { $.post('/_api/likes.add', {_csrf: token, page_id: pageId}, function(res) { if (res.ok) { MarkLiked(); } }); } else { $.post('/_api/likes.remove', {_csrf: token, page_id: pageId}, function(res) { if (res.ok) { MarkUnLiked(); } }); } return false; }); var $likerList = $("#liker-list"); var likers = $likerList.data('likers'); if (likers && likers.length > 0) { // FIXME: user data cache $.get('/_api/users.list', {user_ids: likers}, function(res) { // ignore unless response has error if (res.ok) { AddToLikers(res.users); } }); } function AddToLikers (users) { $.each(users, function(i, user) { $likerList.append(CreateUserLinkWithPicture(user)); }); } function MarkLiked() { $likeButton.addClass('active'); $likeButton.data('liked', 1); $likeCount.text(parseInt($likeCount.text()) + 1); } function MarkUnLiked() { $likeButton.removeClass('active'); $likeButton.data('liked', 0); $likeCount.text(parseInt($likeCount.text()) - 1); } if (!isSeen) { $.post('/_api/pages.seen', {page_id: pageId}, function(res) { // ignore unless response has error if (res.ok && res.seenUser) { $('#content-main').data('page-is-seen', 1); } }); } var $seenUserList = $("#seen-user-list"); if ($seenUserList && $seenUserList.length > 0) { var seenUsers = $seenUserList.data('seen-users'); var seenUsersArray = seenUsers.split(','); if (seenUsers && seenUsersArray.length > 0 && seenUsersArray.length <= 10) { // FIXME: user data cache $.get('/_api/users.list', {user_ids: seenUsers}, function(res) { // ignore unless response has error if (res.ok) { AddToSeenUser(res.users); } }); } } function CreateUserLinkWithPicture (user) { var $userHtml = $(''); $userHtml.data('user-id', user._id); $userHtml.attr('href', '/user/' + user.username); $userHtml.attr('title', user.name); var $userPicture = $(''); $userPicture.attr('alt', user.name); $userPicture.attr('src', Crowi.userPicture(user)); $userHtml.append($userPicture); return $userHtml; } function AddToSeenUser (users) { $.each(users, function(i, user) { $seenUserList.append(CreateUserLinkWithPicture(user)); }); } // History Diff var allRevisionIds = []; $.each($('.diff-view'), function() { allRevisionIds.push($(this).data('revisionId')); }); $('.diff-view').on('click', function(e) { e.preventDefault(); var getBeforeRevisionId = function(revisionId) { var currentPos = $.inArray(revisionId, allRevisionIds); if (currentPos < 0) { return false; } var beforeRevisionId = allRevisionIds[currentPos + 1]; if (typeof beforeRevisionId === 'undefined') { return false; } return beforeRevisionId; }; var revisionId = $(this).data('revisionId'); var beforeRevisionId = getBeforeRevisionId(revisionId); var $diffDisplay = $('#diff-display-' + revisionId); var $diffIcon = $('#diff-icon-' + revisionId); if ($diffIcon.hasClass('fa-arrow-circle-right')) { $diffIcon.removeClass('fa-arrow-circle-right'); $diffIcon.addClass('fa-arrow-circle-down'); } else { $diffIcon.removeClass('fa-arrow-circle-down'); $diffIcon.addClass('fa-arrow-circle-right'); } if (beforeRevisionId === false) { $diffDisplay.text('差分はありません'); $diffDisplay.slideToggle(); } else { var revisionIds = revisionId + ',' + beforeRevisionId; if ($diffDisplay.data('loaded')) { $diffDisplay.slideToggle(); return true; } $.ajax({ type: 'GET', url: '/_api/revisions.list?revision_ids=' + revisionIds, dataType: 'json' }).done(function(res) { var currentText = res[0].body; var previousText = res[1].body; $diffDisplay.text(''); var diff = jsdiff.diffLines(previousText, currentText); diff.forEach(function(part) { var color = part.added ? 'green' : part.removed ? 'red' : 'grey'; var $span = $(''); $span.css('color', color); $span.text(part.value); $diffDisplay.append($span); }); $diffDisplay.data('loaded', 1); $diffDisplay.slideToggle(); }); } }); // default open $('a[data-toggle="tab"][href="#revision-history"]').on('show.bs.tab', function() { $('.diff-view').each(function(i, diffView) { if (i < 2) { $(diffView).click(); } }); }); // presentation var presentaionInitialized = false , $b = $('body'); $(document).on('click', '.toggle-presentation', function(e) { var $a = $(this); e.preventDefault(); $b.toggleClass('overlay-on'); if (!presentaionInitialized) { presentaionInitialized = true; $('