From 2a56c043d770b788a8249ce27a25a97466b9542f Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 27 Aug 2012 21:48:57 +0100 Subject: [PATCH] Basic, dumb saving in TiddlyFox now works It seems to work OK, but could do with more of a user interface for confirmations and so on... --- tiddlyfox/extension/content/inject.js | 45 ++++++++ tiddlyfox/extension/content/overlay.js | 102 ++++++++++++++++-- .../extension/content/tiddlyfox_32x32.png | Bin 5823 -> 3649 bytes tiddlyfox/extension/tiddlyfox.xpi | Bin 10788 -> 10748 bytes 4 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 tiddlyfox/extension/content/inject.js diff --git a/tiddlyfox/extension/content/inject.js b/tiddlyfox/extension/content/inject.js new file mode 100644 index 000000000..caa732290 --- /dev/null +++ b/tiddlyfox/extension/content/inject.js @@ -0,0 +1,45 @@ +/* +The JavaScript in this file is injected into each TiddlyWiki page that loads +*/ + +(function () { + + /* + Returns true if successful, false if failed, null if not available + */ + var injectedSaveFile = function(path,content) { + // Find the message box element + var messageBox = document.getElementById("tiddlyfox-message-box"); + if(messageBox) { + // Create the message element and put it in the message box + var message = document.createElement("div"); + message.setAttribute("tiddlyfox-path",path); + message.setAttribute("tiddlyfox-content",content); + messageBox.appendChild(message); + // Create and dispatch the custom event to the extension + var event = document.createEvent("Events"); + event.initEvent("tiddlyfox-save-file",true,false); + message.dispatchEvent(event); + } + return true; + }; + + /* + Returns text if successful, false if failed, null if not available + */ + var injectedLoadFile = function(path) { + try { + // Just the read the file synchronously + var xhReq = new XMLHttpRequest(); + xhReq.open("GET", "file://" + path, false); + xhReq.send(null); + return xhReq.responseText; + } catch(ex) { + return false; + } + }; + + window.mozillaSaveFile = injectedSaveFile; + window.mozillaLoadFile = injectedLoadFile; + +})(); \ No newline at end of file diff --git a/tiddlyfox/extension/content/overlay.js b/tiddlyfox/extension/content/overlay.js index 579e06383..d9d0bb4fe 100644 --- a/tiddlyfox/extension/content/overlay.js +++ b/tiddlyfox/extension/content/overlay.js @@ -1,12 +1,96 @@ -var TiddlyFox = { - onLoad: function() { - // initialization code - this.initialized = true; - }, +/* + +The JavaScript code in this file is executed via `overlay.xul` when Firefox starts up. + +*/ + +var TiddlyFox = { + + // Called when the main browser has loaded + onLoad: function(event) { + // Register a page load event + var appcontent = document.getElementById("appcontent"); + if(appcontent){ + appcontent.addEventListener("DOMContentLoaded",TiddlyFox.onPageLoad,true); + } + }, + + // Called each time a page loads + onPageLoad: function(event) { + // Get the document and window + var doc = event.originalTarget, + win = doc.defaultView; + // If it is a TiddlyWiki + if(TiddlyFox.isTiddlyWiki(doc,win)) { + alert("TiddlyFox: Enabling TiddlyWiki file saving"); + TiddlyFox.injectPage(doc); + } + }, + + injectPage: function(doc) { + // Inject the message box + var messageBox = doc.createElement("div"); + messageBox.id = "tiddlyfox-message-box"; + messageBox.style.display = "none"; + doc.body.appendChild(messageBox); + // Attach the event handler to the message box + messageBox.addEventListener("tiddlyfox-save-file",TiddlyFox.onSaveFile,false); + // Load the script text + var xhReq = new XMLHttpRequest(); + xhReq.open("GET","chrome://tiddlyfox/content/inject.js",false); + xhReq.send(null); + var injectCode = xhReq.responseText; + // Inject the script + var code = doc.createTextNode(injectCode); + var scr = doc.createElement("script"); + scr.type = "text/javascript"; + scr.appendChild(code); + doc.getElementsByTagName("head")[0].appendChild(scr) + }, + + saveFile: function(filePath,content) { + try { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(filePath); + if(!file.exists()) + file.create(0,0x01B4);// 0x01B4 = 0664 + var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); + out.init(file,0x22,0x04,null); + out.write(content,content.length); + out.flush(); + out.close(); + return true; + } catch(ex) { + return false; + } + }, + + onSaveFile: function(event) { + // Get the details from the message + var message = event.target, + path = message.getAttribute("tiddlyfox-path"), + content = message.getAttribute("tiddlyfox-content"); + // Save the file + TiddlyFox.saveFile(path,content); + // Remove the message element from the message box + message.parentNode.removeChild(message); + return false; + }, + + // Called via `overlay.xul` when the menu item is selected + onMenuItemCommand: function() { + window.open("chrome://tiddlyfox/content/hello.xul", "", "chrome"); + }, + + isTiddlyWiki: function(doc,win) { + // Test whether the document is a TiddlyWiki (we don't have access to JS objects in it) + return (doc.scripts[0].id === "versionArea"); + } - onMenuItemCommand: function() { - window.open("chrome://tiddlyfox/content/hello.xul", "", "chrome"); - } }; -window.addEventListener("load", function(e) { TiddlyFox.onLoad(e); }, false); +window.addEventListener("load",function load(event) { + window.removeEventListener("load",load,false); + TiddlyFox.onLoad(event); +},false); diff --git a/tiddlyfox/extension/content/tiddlyfox_32x32.png b/tiddlyfox/extension/content/tiddlyfox_32x32.png index 8ed46bd7ea52644a54c25d08a706887bed6d0cab..058cbf71a53514258bb66e8d94f6b29abfc804f6 100644 GIT binary patch delta 971 zcmV;+12p`ee_p1s!E z`|Lv;gKlnaczb)BUteEiNdKP*eSCayRC{}SQ;Ua(huquS%S3;~!^6XTe0;2Y%tz_P z;bB3L1Kr=>^ZWZdlfDHWX6)hNf&2UW6+}fvh4$Uu-F$Izp&Bp{mtfPto6gG03h(aj zDyT>x7LDcQWp$p(WSo93_*m!<^-WC?>4S;{*`T3bQH#d1~Y)lu`*4D=08Kp1~2OfzLN~hD5 z&*w={lcY!IOiX|gnxu*ZDAm-|P(wol_4W0U)R5}b*Vn6#L`&^#Y;4fl+8XWe?<*hr z5^b8Doh8V~;$(>dvb2b@A{S8Fi-lNyb8|CKO-*UoQQUu3RaKrI>I|)^sfo|e&%M+F zLI{ZEb75gY(_%#$1cH=d4yi)>46p$(TO%VQx_p04NlaWq*gyvd2LP#Qa3y}fVNMK% zrl611qDPwjasoue(6 z3I!b-PhWpZ^gwY3DdP{Xf5+V3-fD=y8tjft%MB! z;>}cMadDC4*e2wyv$K<0TU+Vq=*Z^F(%;?PMcVcDd3$?1PfSd3OG}ILBqH9NXeJ&@ z#MQ>q(vp-OJKr8JH7Lqrv8c`9f>#dmmxI}NiWPtR9}PJy7YI0()7Siay>pJBP|LAP z%$qH)tEi9C#&uv11=!^v1?UjXZcpe@DhC zQ;(D*HRI#s>LIEGz6`5qCX%sZK<+Mlc6R2a1p@)3??9KxNgRE<)lE-NJ0N}(2%>>P zt*n2nWVu=>5W9T+C=iRr%*;$E8YKr}TQis@JJRLc;H#@EXS*sYd6c|H;1p@FW|63_ zuI9bHy~t>kG$Obh+eb1Ok=oi?USD5V5dOMQ#-B&xh}f2t+ZN0HMQ`nOb#;1?mfs1U zoSfubF83)2OeO|mslZQ|(dp?a@9gX_dLu*mfZ8y!F9{H&Vs&*@SA}0tKf%FQARwOz ti0y`ffdPJed{krR7_|@wfPpq3zW`yJxbQeN%9a2C002ovPDHLkV1jJ^=iLAR delta 3162 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

kE3U5-fRf-zrBUssoQ2fz9aDG1l~ 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 rkca?vBN{#i2N$|x0Xz{-<`0W4*p5FZrDPdOw