Skip to content

Commit

Permalink
Added "insertCode" command to message editor
Browse files Browse the repository at this point in the history
  • Loading branch information
archimag committed May 9, 2010
1 parent 3e6968f commit e619faf
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 25 deletions.
37 changes: 37 additions & 0 deletions resources/css/jqModal.css
@@ -0,0 +1,37 @@
/* jqModal base Styling courtesy of;
Brice Burgess <bhb@iceburg.net> */

/* The Window's CSS z-index value is respected (takes priority). If none is supplied,
the Window's z-index value will be set to 3000 by default (via jqModal.js). */

.jqmWindow {
display: none;

position: fixed;
top: 17%;
left: 50%;

margin-left: -300px;
width: 600px;

background-color: #EEE;
color: #333;
border: 1px solid black;
padding: 12px;
}

.jqmOverlay { background-color: #000; }

/* Background iframe styling for IE6. Prevents ActiveX bleed-through (<select> form elements, etc.) */
* iframe.jqm {position:absolute;top:0;left:0;z-index:-1;
width: expression(this.parentNode.offsetWidth+'px');
height: expression(this.parentNode.offsetHeight+'px');
}

/* Fixed posistioning emulation for IE6
Star selector used to hide definition from browsers other than IE6
For valid CSS, use a conditional include instead */
* html .jqmWindow {
position: absolute;
top: expression((document.documentElement.scrollTop || document.body.scrollTop) + Math.round(17 * (document.documentElement.offsetHeight || document.body.clientHeight) / 100) + 'px');
}
96 changes: 75 additions & 21 deletions resources/js/forum.js
Expand Up @@ -3,8 +3,12 @@
$(document).ready( function () {
$("a.reply-link").click(showReplyForm);
$("input[type='reset']").click(hideReplyForm);
$("#insert-code-preview").click(previewColorizeCode);
$("#insert-code-ok").click(insertColorizeCode);
});

function insertCodeFrame () { return $("#insert-code"); }

function replyForm () { return $('form'); }

function wysiwygTextArea () { return $('#wysiwyg'); }
Expand All @@ -16,6 +20,23 @@ function hideReplyForm () {
textarea.show();
}

function showWysiwygEditor (form) {
form.show();

wysiwygTextArea().wysiwyg({
controls : {
insertCode: {
visible: true,
exec: function () {
insertCodeFrame().jqm();
insertCodeFrame().jqmShow();
},
tooltip: "Insert code"}
},
css: "http://" + location.host + "/css/style.css" });
};


function showReplyForm (evt) {
var form = replyForm();

Expand All @@ -25,16 +46,8 @@ function showReplyForm (evt) {

var href = $(evt.target).attr("href");
if (href && href != "") form.attr("action", href);

form.show();
wysiwygTextArea().wysiwyg(
{ controls :
{ separator04 : { visible : true },
insertOrderedList : { visible : true },
insertUnorderedList : { visible : true }
}
}
);

showWysiwygEditor(form);

return false;
}
Expand All @@ -43,20 +56,61 @@ function newmessage () {
var form = $('form');

if (form.css("display") == "none") {
form.show();
showWysiwygEditor(form)
location.hash = "#editor";
}
}

$('#wysiwyg').wysiwyg(
{
controls : {
separator04 : { visible : true },
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Insert code dialog
////////////////////////////////////////////////////////////////////////////////////////////////////

insertOrderedList : { visible : true },
insertUnorderedList : { visible : true }
}
}
);
function getColorizingCode (frame) {
var area = frame || insertCodeFrame();

location.hash = "#editor";
var lang = $("select", area).val();
var code = $("textarea", area).val();

if (lang == "NONE") return "<br /><pre class=\"code\">" + code + "</pre><br />";

return "<br /><div class=\"code\">" +
$.ajax( {
url: "/forum/colorize",
type: "POST",
data: { lang: lang,
code: code },
async: false
}).responseText +
"</div><br />";
}

function previewColorizeCode (evt) {
var frame = insertCodeFrame();

var sourceArea = $("textarea", frame);
var previewArea = sourceArea.next();

if (previewArea.css("display") == "none") {
previewArea.width( sourceArea.width() - 30 );
previewArea.height( sourceArea.height() );
previewArea.html( getColorizingCode(frame) );

sourceArea.hide();
previewArea.show();

$("#insert-code-preview").html("Редактировать");
}
else {
previewArea.hide();
sourceArea.show();

$("#insert-code-preview").html("Предпросмотр");
}
}

function insertColorizeCode (evt) {
var frame = insertCodeFrame();
wysiwygTextArea().wysiwyg('insertHtml',
getColorizingCode(frame));
frame.jqmHide();
}
69 changes: 69 additions & 0 deletions resources/js/jqModal.js
@@ -0,0 +1,69 @@
/*
* jqModal - Minimalist Modaling with jQuery
* (http://dev.iceburg.net/jquery/jqModal/)
*
* Copyright (c) 2007,2008 Brice Burgess <bhb@iceburg.net>
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* $Version: 03/01/2009 +r14
*/
(function($) {
$.fn.jqm=function(o){
var p={
overlay: 50,
overlayClass: 'jqmOverlay',
closeClass: 'jqmClose',
trigger: '.jqModal',
ajax: F,
ajaxText: '',
target: F,
modal: F,
toTop: F,
onShow: F,
onHide: F,
onLoad: F
};
return this.each(function(){if(this._jqm)return H[this._jqm].c=$.extend({},H[this._jqm].c,o);s++;this._jqm=s;
H[s]={c:$.extend(p,$.jqm.params,o),a:F,w:$(this).addClass('jqmID'+s),s:s};
if(p.trigger)$(this).jqmAddTrigger(p.trigger);
});};

$.fn.jqmAddClose=function(e){return hs(this,e,'jqmHide');};
$.fn.jqmAddTrigger=function(e){return hs(this,e,'jqmShow');};
$.fn.jqmShow=function(t){return this.each(function(){t=t||window.event;$.jqm.open(this._jqm,t);});};
$.fn.jqmHide=function(t){return this.each(function(){t=t||window.event;$.jqm.close(this._jqm,t)});};

$.jqm = {
hash:{},
open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=(parseInt(h.w.css('z-index'))),z=(z>0)?z:3000,o=$('<div></div>').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});if(h.a)return F;h.t=t;h.a=true;h.w.css('z-index',z);
if(c.modal) {if(!A[0])L('bind');A.push(s);}
else if(c.overlay > 0)h.w.jqmAddClose(o);
else o=F;

h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):F;
if(ie6){$('html,body').css({height:'100%',width:'100%'});if(o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}}

if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u;
r.html(c.ajaxText).load(u,function(){if(c.onLoad)c.onLoad.call(this,h);if(cc)h.w.jqmAddClose($(cc,h.w));e(h);});}
else if(cc)h.w.jqmAddClose($(cc,h.w));

if(c.toTop&&h.o)h.w.before('<span id="jqmP'+h.w[0]._jqm+'"></span>').insertAfter(h.o);
(c.onShow)?c.onShow(h):h.w.show();e(h);return F;
},
close:function(s){var h=H[s];if(!h.a)return F;h.a=F;
if(A[0]){A.pop();if(!A[0])L('unbind');}
if(h.c.toTop&&h.o)$('#jqmP'+h.w[0]._jqm).after(h.w).remove();
if(h.c.onHide)h.c.onHide(h);else{h.w.hide();if(h.o)h.o.remove();} return F;
},
params:{}};
var s=0,H=$.jqm.hash,A=[],ie6=$.browser.msie&&($.browser.version == "6.0"),F=false,
i=$('<iframe src="javascript:false;document.write(\'\');" class="jqm"></iframe>').css({opacity:0}),
e=function(h){if(ie6)if(h.o)h.o.html('<p style="width:100%;height:100%"/>').prepend(i);else if(!$('iframe.jqm',h.w)[0])h.w.prepend(i); f(h);},
f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(_){}},
L=function(t){$()[t]("keypress",m)[t]("keydown",m)[t]("mousedown",m);},
m=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);if(r)f(h);return !r;},
hs=function(w,t,c){return w.each(function(){var s=this._jqm;$(t).each(function() {
if(!this[c]){this[c]=[];$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});};
})(jQuery);
3 changes: 2 additions & 1 deletion resources/js/jquery.wysiwyg.js
Expand Up @@ -74,7 +74,7 @@
}

options = $.extend({
html : '<'+'?xml version="1.0" encoding="UTF-8"?'+'><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">STYLE_SHEET</head><body style="margin: 0px;">INITIAL_CONTENT</body></html>',
html : '<'+'?xml version="1.0" encoding="UTF-8"?'+'><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">STYLE_SHEET</head><body class="wysiwyg" style="margin: 0px;">INITIAL_CONTENT</body></html>',
css : {},

debug : false,
Expand Down Expand Up @@ -371,6 +371,7 @@
$.data(element, 'wysiwyg', this);

var newX = element.width || element.clientWidth;

var newY = element.height || element.clientHeight;

if ( element.nodeName.toLowerCase() == 'textarea' )
Expand Down
2 changes: 1 addition & 1 deletion restas-forum.asd
Expand Up @@ -6,7 +6,7 @@
;;;; Author: Moskvitin Andrey <archimag@gmail.com>

(defsystem restas-forum
:depends-on (#:restas #:closure-template #:restas-directory-publisher #:metabang-bind)
:depends-on (#:restas #:closure-template #:restas-directory-publisher #:metabang-bind #:colorize)
:components ((:module "src"
:components ((:file "defmodule")
(:file "storage" :depends-on ("defmodule"))
Expand Down
26 changes: 24 additions & 2 deletions src/forum.lisp
Expand Up @@ -46,11 +46,17 @@
"RESTAS-FORUMS"))

(defun js-urls ()
(iter (for item in '("jquery.js" "jquery.wysiwyg.js" "forum.js"))
(iter (for item in '("jquery.js" "jquery.wysiwyg.js" "jqModal.js" "forum.js"))
(collect (restas:genurl-submodule 'resources
'restas.directory-publisher:route
:path (list "js" item)))))

(defun colorize-traits ()
(list :href (restas:genurl 'colorize-code)
:langs (iter (for (id . title) in (colorize:coloring-types))
(collect (list :id (symbol-name id)
:title title)))))

;;;; list all forums

(define-route list-forums ("")
Expand Down Expand Up @@ -162,7 +168,8 @@
:reply-id (getf item :prev-id)))))
item)))
:can-create-message user
:title (getf message :title))))
:title (getf message :title)
:colorize (colorize-traits))))

;;;; view topic

Expand Down Expand Up @@ -266,3 +273,18 @@
:topic-id topic-id)
:messages (make-rss-items (storage-topic-news *storage* topic-id *rss-item-count*)))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Colorize
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define-route colorize-code ("colorize"
:method :post
:render-method 'identity)
(let ((code (hunchentoot:post-parameter "code"))
(lang (hunchentoot:post-parameter "lang")))
(colorize::html-colorization (or (find-symbol lang :keyword)
(error "Unknow coloring type: ~A" lang))
code)))


25 changes: 25 additions & 0 deletions src/forum.tmpl
Expand Up @@ -221,6 +221,8 @@
<input type="reset" name="cancel" value="Отмена" />
</div>
</form>

{call insertCodeDialog data="$colorize" /}
{/if}
{/template}

Expand Down Expand Up @@ -256,3 +258,26 @@
</channel>
</rss>
{/template}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Insert code dialog
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

{template insertCodeDialog}
<div id="insert-code" class="jqmWindow">
<select>
<option value="NONE">None</option>
{foreach $lang in $langs}
<option value="{$lang.id}">{$lang.title}</option>
{/foreach}
</select>
<div>
<textarea rows="20" cols="80" ></textarea>
<div style="display: none"></div>
</div>
<button id="insert-code-ok">Готово</button>
<button id="insert-code-preview">Предпросмотр</button>
<button id="insert-code-cancel" class="jqmClose">Отмена</button>
</div>
{/template}

0 comments on commit e619faf

Please sign in to comment.