@phoenix-plugin-registry/swmitra.html-designer
Version:
NOW WITH RESPONSIVE DESIGN TOOLS (BETA)! Design and customize web ui with HTML and CSS. Now with taggable Design snippet/bookmark support.
283 lines (247 loc) • 12.2 kB
JavaScript
/**
* @author Swagatam Mitra
*/
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, document, console, brackets, $, Mustache */
define(function (require, exports, module) {
"use strict";
var AppInit = brackets.getModule("utils/AppInit"),
Resizer = brackets.getModule("utils/Resizer"),
HTMLUtils = brackets.getModule("language/HTMLUtils"),
DocumentManager = brackets.getModule("document/DocumentManager"),
EditorManager = brackets.getModule("editor/EditorManager");
var CodeMirror = brackets.getModule("thirdparty/CodeMirror2/lib/codemirror");
var ViewPresentationPresets = require("view/ViewPresentationPresets");
var sourceEditor;
var currentInlineEditor = null;
var editorMap = {};
var isFragmentModeOn = false;
var HTMLDOMParser = null;
/*$(document).on('click',"#source-editor-minimize",function(){
$("#styles-editor-maximize").click();
ViewPresentationPresets.applyDesignAndStylesSplit();
$("#source-editor-container").addClass("minimizedSourceView");
});
$(document).on('click',"#source-editor-maximize",function(){
$("#source-editor-container").removeClass("minimizedSourceView");
});*/
$(document).on('click',"#source-editor-close",function(){
$("#source-editor-container").hide();
});
$(document).on('fragmentDesignModeon',"#html-design-editor",function(){
isFragmentModeOn = true;
});
$(document).on('design-dom-changed',"#html-design-editor",function(){
isFragmentModeOn = false;
});
$(document).on('before.save.dom',"#html-design-editor",function(){
if(sourceEditor){
sourceEditor.off("change",_synchDesignWithCode);
}
});
$(document).on('after.save.dom',"#html-design-editor",function(){
if(sourceEditor){
sourceEditor.on("change",_synchDesignWithCode);
}
});
function _showSourceView() {
$("#source-editor-container").show();
_setupLiveEdit();
}
function _quitSourceView() {
$("#source-editor-container").hide();
if(sourceEditor){
sourceEditor.off("change",_synchDesignWithCode);
}
}
function _synchDesignWithCode(cm, change){
var toBeUpdated = document.getElementById('htmldesignerIframe').contentWindow.document;
$("#html-design-editor").trigger("deselect.all");
if(isFragmentModeOn === true){
$(toBeUpdated).find("#ad-fragment-container").html(sourceEditor.getDoc().getValue());
} else {
_dynamicUpdateHandler(cm, change);
}
//$("#html-design-editor").trigger("design-dom-changed");
}
function _setupLiveEdit(){
var doc = DocumentManager.getCurrentDocument();
if(currentInlineEditor){
currentInlineEditor.setVisible(false,true);
}
currentInlineEditor = editorMap[doc];
if(!currentInlineEditor){
currentInlineEditor = EditorManager
.createInlineEditorForDocument(
doc
, null
, $("#html-inline-editor")[0]
).editor;
editorMap[doc] = currentInlineEditor;
currentInlineEditor.focus();
doc.addRef();
} else {
currentInlineEditor.focus();
}
$("#html-inline-editor > *").css('height', '100%');
sourceEditor = currentInlineEditor._codeMirror;
if(sourceEditor){
sourceEditor.off("change",_synchDesignWithCode);
sourceEditor.refresh();
sourceEditor.on("change",_synchDesignWithCode);
//sourceEditor.focus();
}
}
$(document).on("refresh-split-view","#html-design-editor",function(){
sourceEditor.refresh();
});
function _getXPath( element ){
var xpath = '';
for ( ; element && element.nodeType == 1; element = element.parentNode )
{
var id = $(element.parentNode).children(element.tagName).index(element) + 1;
id > 1 ? (id = ':nth-of-type(' + id + ')') : (id = '');
xpath = ' ' + element.tagName.toLowerCase() + id + xpath;
}
return xpath;
}
function _handleHEADUpdate(before,after,text){
var updateType = "";
//Check if this is an attribute change
var htmlContext = _isTagAttributeChange();
if(htmlContext){
updateType = _handleAttributeChange(htmlContext,before,after,text);
} else {
var fragmentDOM = HTMLDOMParser.parseFromString(before,'text/html');
var breakPointElm = $(fragmentDOM).find("head").children().last()[0];
if(breakPointElm && breakPointElm.parentElement.tagName !== 'HEAD'){
var elementXPath = _getXPath(breakPointElm);
var sourceDOM = HTMLDOMParser.parseFromString(before+text+after,'text/html');
var toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
var toBeModifiedWith = $(sourceDOM).find(elementXPath);
if(toBeModified[0]){
toBeModified[0].outerHTML = toBeModifiedWith[0].outerHTML;
} else {
if($(toBeModifiedWith).prev()[0]){
elementXPath = _getXPath($(toBeModifiedWith).prev()[0]);
toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
$(toBeModified).after(toBeModifiedWith[0].outerHTML);
} else {
elementXPath = _getXPath($(toBeModifiedWith).parent()[0]);
toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
toBeModified.append(toBeModifiedWith[0].outerHTML);
}
}
updateType = toBeModifiedWith[0].tagName;
}
}
return updateType;
}
function _isTagAttributeChange(){
var tagInfo = HTMLUtils.getTagInfo(currentInlineEditor,sourceEditor.getCursor());
if(tagInfo.tagName){
return tagInfo;
} else {
return null;
}
}
function _handleAttributeChange(tagInfo,before,after,text){
var breakPointFragment = before+"\"><breakpoint id='ad-breakpoint'></breakpoint>";
var fragmentDOM = HTMLDOMParser.parseFromString(breakPointFragment,'text/html');
var breakPointElm = $(fragmentDOM).find("#ad-breakpoint")[0];
var updateType = "";
if(breakPointElm){
var elementXPath = _getXPath(breakPointElm.parentElement);
var sourceDOM = HTMLDOMParser.parseFromString(before+text+after,'text/html');
var toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
var toBeModifiedWith = $(sourceDOM).find(elementXPath);
if(toBeModified[0] && tagInfo.attr.name){
if(tagInfo.attr.valueAssigned){
toBeModified.attr(tagInfo.attr.name,toBeModifiedWith.attr(tagInfo.attr.name) || '');
} else {
toBeModified.removeAttr(tagInfo.attr.name);
}
}
updateType = toBeModified[0].tagName;
}
return updateType;
}
function _handleBODYUpdate(before,after,text){
var updateType = "";
//Check if this is an attribute change
var htmlContext = _isTagAttributeChange();
if(htmlContext){
updateType = _handleAttributeChange(htmlContext,before,after,text);
} else {
var breakPointFragment = before+"<breakpoint id='ad-breakpoint'></breakpoint>";
var fragmentDOM = HTMLDOMParser.parseFromString(breakPointFragment,'text/html');
var breakPointElm = $(fragmentDOM).find("#ad-breakpoint")[0];
if(breakPointElm && breakPointElm.parentElement.tagName !== 'BODY'){
var elementXPath = _getXPath(breakPointElm.parentElement);
var sourceDOM = HTMLDOMParser.parseFromString(before+text+after,'text/html');
var toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
var toBeModifiedWith = $(sourceDOM).find(elementXPath);
if(toBeModified[0]){
toBeModified[0].outerHTML = toBeModifiedWith[0].outerHTML;
} else {
if($(toBeModifiedWith).prev()[0]){
elementXPath = _getXPath($(toBeModifiedWith).prev()[0]);
toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
$(toBeModified).after(toBeModifiedWith[0].outerHTML);
} else {
elementXPath = _getXPath($(toBeModifiedWith).parent()[0]);
toBeModified = $(document.getElementById('htmldesignerIframe').contentWindow.document).find(elementXPath);
toBeModified.append(toBeModifiedWith[0].outerHTML);
}
}
updateType = toBeModifiedWith[0].tagName;
}
}
return updateType;
}
function _dynamicUpdateHandler(cm, change){
var from = change.from;
var text = change.text.join("\n");
var removed = change.removed.join("\n");
if(text === "\n" || removed === "\n"){
return;
}
var to = cm.posFromIndex(cm.indexFromPos(from) + text.length);
var before = cm.getRange({ line: 0, ch: 0 }, from);
var after = cm.getRange(to, { line: cm.lineCount() + 1, ch: 0 });
var partialDOM = HTMLDOMParser.parseFromString(before+"\">",'text/html');
var updateType = "";
if($(partialDOM).find('body').children().length === 0){
if($(partialDOM).find('head').children().length > 0 ){
updateType = _handleHEADUpdate(before,after,text);
}
} else {
updateType = _handleBODYUpdate(before,after,text);
}
if(updateType === 'BODY'){
$(document.getElementById('htmldesignerIframe').contentWindow.document).find('head').not('head:first').remove();
$(document.getElementById('htmldesignerIframe').contentWindow.document).find('body').not('body:first').remove();
}
if(updateType === "LINK"){
$("#html-design-editor").trigger("design-dom-changed");
}
}
$(document).on('source-file-select-requested',"#html-design-editor",function(event,value){
if(value){
_showSourceView();
}
});
function _init() {
Resizer.makeResizable($("#source-editor-container")[0], Resizer.DIRECTION_HORIZONTAL, Resizer.POSITION_RIGHT, 250, false, undefined, false);
Resizer.makeResizable($("#source-editor-container")[0], Resizer.DIRECTION_VERTICAL, Resizer.POSITION_BOTTOM, 250, false, undefined, false);
$("#source-editor-container").on("panelResizeUpdate", function () {
if(sourceEditor){
sourceEditor.refresh();
}
});
HTMLDOMParser = new DOMParser();
}
exports.launch = _showSourceView;
exports.hide = _quitSourceView;
exports.init = _init;
});