Commits

Luke Plant committed f1308ab

Implemented preview functionality

Comments (0)

Files changed (6)

semanticeditor/media/semanticeditor/javascript/wymeditor/plugins/semantic/wymeditor.semantic.js

     var headingsbox_id = id_prefix + 'headings';
     var optsbox_id = id_prefix + 'optsbox';
     var headingsfilter_id = id_prefix + 'headingsfilter';
+    var layoutpreview_id = id_prefix + 'layoutpreview';
+    var refresh_id = id_prefix + 'refresh';
     var self = this;
 
     // Create elements
 	"<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td width=\"50%\"><div class=\"prescontrolheadings\">Structure:<br/><select size=\"7\" id=\"" + headingsbox_id + "\"></select>" +
 	"<br/><label><input type=\"checkbox\" id=\"" + headingsfilter_id + "\" checked=\"checked\"> Headings only</label></div></td>" +
 	"<td width=\"50%\"><div class=\"prescontroloptsboxcont\">Presentation choices:<div class=\"prescontroloptsbox\" id=\"" + optsbox_id + "\"></div></div></td></tr></table>" +
-	"<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td><div class=\"prescontrolrefresh\"><input type=\"submit\" value=\"Refresh structure\" id=\"" + id_prefix + "refresh" + "\" /></div></td>" +
+	"<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td><div class=\"prescontrolrefresh\">" +
+	    "<input type=\"submit\" value=\"Refresh structure\" id=\"" + refresh_id + "\" />" +
+	    "<input type=\"submit\" value=\"Preview (hover/click)\" id=\"" + layoutpreview_id + "\" />" +
+	"</div></td>" +
 	"<td width=\"*\"><div class=\"prescontrolerror\" id=\"" + id_prefix + "errorbox" + "\"></div></td></tr></table>" +
         "</div>");
 
     this.headingscontrol = jQuery('#' + headingsbox_id);
     this.headingsfilter = jQuery('#' + headingsfilter_id);
     this.errorbox = jQuery('#' + id_prefix + "errorbox");
+    this.layoutpreview = jQuery('#' + layoutpreview_id);
+    this.refreshbutton = jQuery('#' + refresh_id);
     this.optsbox.css('height', this.headingscontrol.get(0).clientHeight.toString() + "px");
 
     // Initial set up
     this.headingscontrol.change(function(event) {
 				    self.update_optsbox();
     });
-    jQuery("#" + id_prefix + "refresh").click(function(event) {
-						  self.refresh_headings();
-						  self.headingscontrol.get(0).focus();
-						  return false;
-					      });
+    this.refreshbutton.click(function(event) {
+				 self.refresh_headings();
+				 self.headingscontrol.get(0).focus();
+				 return false;
+			     });
+    this.layoutpreview.click(function(event) {
+				 self.show_layout_preview();
+				 return false;
+			     });
     this.headingsfilter.change(function(event) {
 				   self.update_active_heading_list();
 				   self.update_headingbox();
     this.optsbox.find("input").removeAttr("disabled");
 };
 
+PresentationControls.prototype.show_layout_preview = function() {
+    var self = this;
+    jQuery.post(this.opts.preview_url, { 'html': self.wym.xhtml(),
+					 'presentation': JSON.stringify(this.presentation_info)
+					},
+		function(data) {
+		    self.with_good_data(data,
+			function(value) {
+			    jQuery(".orbitaltooltip-previewbox").remove();
+			    self.layoutpreview.orbitaltooltip({
+				orbitalPosition: 0,
+				spacing:         8,
+				tooltipClass: 	 'orbitaltooltip-previewbox',
+				html:            value.html
+			    });
+			});
+		}, "json");
+    return false;
+};
+
 PresentationControls.prototype.add_style = function(heading, presinfo) {
     var styles = this.presentation_info[heading];
     styles.push(presinfo);

semanticeditor/media/semanticeditor/javascript/wymeditor/skins/semanticeditor/skin.css

 	    border: 2px solid #607e98;
 	    padding: 2px;
 	}
+
+
+	.orbitaltooltip-previewbox {
+	    background: #fff;
+	    width: 400px;
+	    height: 400px;
+	    overflow-y: scroll;
+	    overflow-x: hidden;
+	    border: 2px solid #008000;
+	    padding: 4px;
+	}
+
+	.orbitaltooltip-previewbox .structural {
+	    border: 2px solid #888;
+	    margin: 2px;
+	}
+
+	.orbitaltooltip-previewbox .tagh1,
+	.orbitaltooltip-previewbox .tagh2,
+	.orbitaltooltip-previewbox .tagh3,
+	.orbitaltooltip-previewbox .tagh4,
+	.orbitaltooltip-previewbox .tagh5,
+	.orbitaltooltip-previewbox .tagh6 {
+	    font-weight: bold;
+	}
+
+	.orbitaltooltip-previewbox .row1col,
+	.orbitaltooltip-previewbox .row2col,
+	.orbitaltooltip-previewbox .row3col,
+	.orbitaltooltip-previewbox .row4col
+	{
+	    clear: left;
+	    border: 1px solid red;
+	    padding: 3px;
+	    margin-bottom: 2px;
+	}
+
+	.orbitaltooltip-previewbox .rowclear
+	{
+	    clear: left;
+	}
+
+	.orbitaltooltip-previewbox .row2col .col {
+	    float: left;
+	    width: 50%;
+	}
+	.orbitaltooltip-previewbox .row3col .col {
+	    float: left;
+	    width: 32%;
+	}
+	.orbitaltooltip-previewbox .row4col .col {
+	    float: left;
+	    width: 25%;
+	}
+

semanticeditor/templates/semanticeditor/editorwidget.html

                 extract_headings_url: "{% url semantic.extract_headings %}",
                 retrieve_styles_url: "{% url semantic.retrieve_styles %}",
                 separate_presentation_url: "{% url semantic.separate_presentation %}",
-                combine_presentation_url: "{% url semantic.combine_presentation %}"
+                combine_presentation_url: "{% url semantic.combine_presentation %}",
+                preview_url: "{% url semantic.preview %}"
             };
             wym.semantic(symanticopts);
         },

semanticeditor/urls.py

 from django.conf.urls.defaults import patterns, url
-from semanticeditor.views import extract_headings_view, retrieve_styles, separate_presentation, combine_presentation
+from semanticeditor.views import extract_headings_view, retrieve_styles, separate_presentation, combine_presentation, preview
 
 urlpatterns = patterns('',
     url(r'extract_headings/', extract_headings_view, name="semantic.extract_headings"),
     url(r'retrieve_styles/', retrieve_styles, name="semantic.retrieve_styles"),
     url(r'separate_presentation/', separate_presentation, name="semantic.separate_presentation"),
     url(r'combine_presentation/', combine_presentation, name="semantic.combine_presentation"),
+    url(r'preview/', preview, name="semantic.preview"),
 )

semanticeditor/utils/presentation.py

 # make the previous H1 into the start of a *2* column row!
 
 
-def format_html(html, styleinfo):
+def format_html(html, styleinfo, return_tree=False):
     """
     Formats the XHTML given using a dictionary of style information.
     The dictionary has keys which are the names of headings,
     # Apply row/column commands
     _apply_commands(root, section_nodes, styleinfo, structure)
 
-    return _html_extract(root)
+    if return_tree:
+        return (root, structure, section_nodes)
+    else:
+        return _html_extract(root)
 
 def _html_extract(root):
     if len(root) == 0 and root.text is None and root.tail is None:
 
     return out
 
-# TODO - this might be redundant now
 def _assert_sane_sections(root, structure):
     # First, all h1, h2 etc tags will be children of the root.
     # remove_tag should have ensured that, otherwise we will be unable
         newcol = wrap_elements_in_tag(newrow, idx, columns[i - 1][0], 'div')
         newcol.set('class', COLUMNCLASS)
 
+def preview_html(html, pres):
+    root, structure, section_nodes = format_html(html, pres, return_tree=True)
+    known_nodes = _invert_dict(section_nodes)
+    _create_preview(root, structure, known_nodes)
+    return _html_extract(root)
+
+def _replace_with_text(n, text):
+    n[:] = []
+    n.tail = ""
+    n.text = text
+
+def _create_preview(node, structure, known_nodes):
+    for n in node.getchildren():
+        if n.tag == 'div':
+            _create_preview(n, structure, known_nodes)
+        else:
+            parent = node
+            name = known_nodes.get(parent)
+            if name is not None:
+                n.set('class', 'structural ' + "tag" + n.tag.lower() )
+                n.tag = "div"
+                n[:] = []
+                n.text = name
+            else:
+                n[:] = []
+                n.tail = None
+                n.text = None
+                n.tag = None
 
 def extract_presentation(html):
     """

semanticeditor/views.py

 from django.utils import simplejson
 from django.core.mail import mail_admins
 from django.utils.translation import ugettext as _
-from semanticeditor.utils import extract_headings, extract_presentation, format_html, AllUserErrors, NEWROW, NEWCOL, PresentationInfo, PresentationClass
+from semanticeditor.utils import extract_headings, extract_presentation, format_html, preview_html, AllUserErrors, NEWROW, NEWCOL, PresentationInfo, PresentationClass
 from semanticeditor.models import CssClass
 import sys
 try:
 
     return graceful_errors(AllUserErrors, _handled)
 
+def _convert_pres(pres):
+    # Convert dictionaries into PresentationInfo classes
+    for k, v in pres.items():
+        # v is list of PI dicts
+        for i, item in enumerate(v):
+            v[i] = dict_to_PI(item)
+
 @json_view
 def combine_presentation(request):
     """
     html = request.POST.get('html', '').encode("utf-8")
     presentation = request.POST.get('presentation', '{}')
     presentation = simplejson.loads(presentation)
-    # Convert dictionaries into PresentationInfo classes
-    for k, v in presentation.items():
-        # v is list of PI dicts
-        for i, item in enumerate(v):
-            v[i] = dict_to_PI(item)
+    _convert_pres(presentation)
 
     return graceful_errors(AllUserErrors, lambda: dict(html=format_html(html, presentation)))
+
+@json_view
+def preview(request):
+    html = request.POST.get('html', '').encode("utf-8")
+    presentation = request.POST.get('presentation', '{}')
+    print html
+    print presentation
+    presentation = simplejson.loads(presentation)
+    _convert_pres(presentation)
+
+    return graceful_errors(AllUserErrors, lambda: dict(html=preview_html(html, presentation)))