source: gs3-extensions/seaweed-debug/trunk/src/Changes.js@ 25160

Last change on this file since 25160 was 25160, checked in by sjm84, 12 years ago

Initial cut at a version of seaweed for debugging purposes. Check it out live into the web/ext folder

File size: 7.7 KB
Line 
1/*
2 * file: Changes.js
3 *
4 * @BEGINLICENSE
5 * Copyright 2010 Brook Novak (email : [email protected])
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 * @ENDLICENSE
18 */
19bootstrap.provides("Changes");
20
21(function() {
22
23 /* All editable sections and their initial states since startup or the last clear. */
24 var esStartStates = [];
25
26 $enqueueInit("Changes", function() {
27
28 de.Changes.clear();
29 de.doc.addObserver({
30 onSectionAdded : function(editSection) {
31
32 // Safety check: make sure editSection is not already registered
33 // @DEBUG ON
34 for (var i in esStartStates) {
35 debug.assert(esStartStates[i].esNode != editSection);
36 }
37 // @DEBUG OFF
38
39 // Add the new section to the state array
40 esStartStates.push({
41 esNode : editSection,
42 initHTML : editSection.innerHTML
43 });
44
45 }
46 });
47
48 }, "Doc");
49
50 /**
51 * @class A singleton that records the editable sections that have been changed/added/removed over time
52 */
53 de.Changes = {
54
55 /**
56 * Gets all changes since last clear
57 *
58 * @return {[Element]} A list of changed editable section nodes. NOTE:
59 * Does not include removed editable sections .. it only checks the
60 * editable section contents.
61 *
62 * @see de.Changes.clear
63 */
64 getChangedEditableSections : function() {
65
66 var changedSections = [],
67 stipEmptiesRE = /(<\s*\w+\s[^>]*?)(?:style|class|id|value)\s*=\s*(?:""|'')([^<]*?>)/i,
68 stipEmptiesREPresto = /(<\s*\w+\s[^>]*?)\s*(?:style|class|id|value)\s*(>|(?:[^=][^<]*?>))/i,
69 stripAttribWSRE = /<[^\/][^<>]*?\s[^<>]*>/,
70 wsRE = /(?:[\t\n\r ]|&nbsp;)/g;
71
72 // Don't consider highlighting as part of HTML
73 _toggleSectionHighlight(false);
74
75 // Look for changes
76 for (var i in esStartStates) {
77 var esSection = esStartStates[i];
78 if (stripIrrelevants(esSection.esNode.innerHTML) != stripIrrelevants(esSection.initHTML) || esSection.dirty)
79 changedSections.push(esSection.esNode);
80 }
81
82 _toggleSectionHighlight(true);
83
84 return changedSections;
85
86 /**
87 * Strip irrelevent html from markup when comparing differences.
88 * E.G. Empty attibutes or different whitespace encodings.
89 * @param {String} str The html to stip irrelevent data from
90 */
91 function stripIrrelevants(str) {
92
93 // Make all whitespaces normal whitespace
94 str = str.replace(wsRE, " ");
95
96 var match, i, re, newStr = "";
97
98 // Strip empty attributes
99 // One regexp matching pass for all browsers except for opera...
100 // Opera can leave empty attrbiutes without ="".
101 for (i = 0; i < (_engine == _Platform.PRESTO ? 2 : 1); i++) {
102
103 // Select the regexp according to pass
104 re = i==0 ? stipEmptiesRE : stipEmptiesREPresto;
105
106 while(match = re.exec(str)) {
107 str = str.substr(0, match.index) + match[1] + match[2] + str.substr(match.index + match[0].length);
108 }
109
110 }
111
112 if (match) {
113
114 // Due to attributes from being stripped must clear whitespaces which separate attibutes in html tags..
115 // since whitespaces may only be present for the empty tags
116 while (match = stripAttribWSRE.exec(str)) {
117 newStr += str.substr(0, match.index) + match[0].replace(wsRE, "");
118 str = str.substr(match.index + match[0].length);
119 }
120 newStr += str;
121
122 } else newStr = str;
123
124 return de.spell.stripSpellWrapperHTML(newStr);
125 }
126
127 },
128
129 /**
130 * Wipes all recorded changes and prepares for recording new changes for all or a specific edit section.
131 *
132 * @param {Element} es (Optional) The edit section to wipe. If not provided then all edit sections will be wiped
133 *
134 * @see de.Changes.reset
135 */
136 clear : function(es) {
137
138 // Exclude highlighting in HTML snapshots
139 _toggleSectionHighlight(false);
140
141 if (es) {
142
143 // Locate specific editable section to wipe changes
144 for (var i in esStartStates) {
145 if (esStartStates[i].esNode == es) {
146 esStartStates[i].initHTML = es.innerHTML;
147 esStartStates[i].dirty = 0;
148 break;
149 }
150 }
151
152 } else {
153
154 // Wipe all previous state information
155 esStartStates = [];
156
157 // Build up the state information based on the current document state
158 var editableSections = de.doc.getAllEditSections();
159
160 for (var i in editableSections) {
161 var domNode = editableSections[i];
162
163 esStartStates.push({
164 esNode: domNode,
165 initHTML: domNode.innerHTML
166 });
167 }
168 }
169
170 _toggleSectionHighlight(true);
171 },
172
173
174
175 /**
176 * Use to mark all or a specific editable section as being dirty.
177 *
178 * If marked as dirty, then the next request for changed editable sections will also return the
179 * editable section marked dirty even if they have not changed / have been cleared.
180 *
181 * The next time the edit section is cleared it will be unmarked as being dirty.
182 *
183 * @param {Object} es (Optional) The edit section to dirty. If not provided then all edit sections will be made dirty.
184 */
185 dirty : function(es) {
186
187 for (var i in esStartStates) {
188 if (!es || esStartStates[i].esNode == es) {
189 esStartStates[i].dirty = 1;
190 }
191 }
192
193 },
194
195 /**
196 * Clears the changes, and resets all edit sections html to their initial state since
197 * start up or the last clear/reset operation. All undo/redo history will be cleared;
198 *
199 * @see de.Changes.clear
200 */
201 reset : function() {
202
203 // Clear undo/redo history
204 de.UndoMan.clear();
205
206 // Reset edit section html back to their last captured start states
207 for (var i in esStartStates) {
208 esStartStates[i].esNode.innerHTML = esStartStates[i].initHTML;
209 }
210
211 // Setup changes again
212 this.clear();
213 }
214
215 }; // End de.Changes singleton
216
217})();
218
Note: See TracBrowser for help on using the repository browser.