|
| 1 | +/* |
| 2 | + * extensions/eqn-number.js |
| 3 | + * |
| 4 | + * Part of the jsMath package for mathematics on the web. |
| 5 | + * |
| 6 | + * This file causes jsMath to add equation numbers to displayed |
| 7 | + * equations. These are displayed at the right, but the styles can |
| 8 | + * be controlled through the jsMath.EqnNumber object. Equations |
| 9 | + * are numbered if they include a \label{xxx} call, and the macro |
| 10 | + * \ref{xxx} can be used to refer to the equation number elsewhere |
| 11 | + * in the document (it must appear by itself in a math formula, |
| 12 | + * e.g., $\ref{xxx}$). The "label-ref" CSS style can be used to |
| 13 | + * style the references. |
| 14 | + * |
| 15 | + * If jsMath.EqnNumber.autonumber is set to 1, then ALL displayed |
| 16 | + * equations will be numberd. Use the \nolabel macro to prevent |
| 17 | + * equation numbering on an equation. |
| 18 | + * |
| 19 | + * You can activate eqn-numbering by calling |
| 20 | + * |
| 21 | + * jsMath.Extension.Require('eqn-number'); |
| 22 | + * |
| 23 | + * once jsMath.js has been loaded, or by adding "extensions/eqn-number.js" |
| 24 | + * to the loadFiles array in jsMath/easy/load.js. |
| 25 | + * |
| 26 | + * --------------------------------------------------------------------- |
| 27 | + * |
| 28 | + * Copyright 2008 by Davide P. Cervone |
| 29 | + * |
| 30 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 31 | + * you may not use this file except in compliance with the License. |
| 32 | + * You may obtain a copy of the License at |
| 33 | + * |
| 34 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 35 | + * |
| 36 | + * Unless required by applicable law or agreed to in writing, software |
| 37 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 38 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 39 | + * See the License for the specific language governing permissions and |
| 40 | + * limitations under the License. |
| 41 | + */ |
| 42 | + |
| 43 | +/********************************************************************/ |
| 44 | + |
| 45 | +if (jsMath.EqnNumber) {jsMath.EqnNumber_old = jsMath.EqnNumber} |
| 46 | + |
| 47 | +jsMath.EqnNumber = { |
| 48 | + |
| 49 | + styles: { |
| 50 | + '.jsMath_displayBox, .tex2math_div': {position: 'relative'}, |
| 51 | + '.jsMath_number': { |
| 52 | + position: 'absolute', |
| 53 | + right: '2em', top: '50%', 'margin-top': '-.5em', |
| 54 | + height: 'auto', width: 'auto' |
| 55 | + }, |
| 56 | + '.jsMath_ref': {'text-decoration': 'none'} |
| 57 | + }, |
| 58 | + |
| 59 | + autonumber: 0, // set to 1 to have ALL equations numbered |
| 60 | + |
| 61 | + number: 0, |
| 62 | + format: function (n) {return n}, |
| 63 | + formatLabel: function (n) {return '<A NAME="eqn-'+n+'">('+n+')</A>'}, |
| 64 | + formatRef: function (n) {return '(<A CLASS="jsMath_ref" HREF="#eqn-'+n+'">'+n+'</A>)'}, |
| 65 | + |
| 66 | + _label: null, // flag set when \label{x} is used |
| 67 | + _labels: {}, // stores label-name => label-value pairs |
| 68 | + _refs: {}, // stores elements referring to undefined labels |
| 69 | + _nolabel: 0, // set by \nolabel |
| 70 | + |
| 71 | + nextNumber: function () { |
| 72 | + var ref = this.format(++this.number); |
| 73 | + if (this._label) { |
| 74 | + this._labels[this._label] = ref; |
| 75 | + if (this._refs[this._label]) this.fixRefs(this._label); |
| 76 | + } |
| 77 | + return this.formatLabel(ref); |
| 78 | + }, |
| 79 | + |
| 80 | + isRef: function (element) { |
| 81 | + var tex = element.innerHTML; |
| 82 | + var result = tex.match(/^\s*\\ref\s*\{([^\}]+)\}\s*$/); |
| 83 | + if (!result) {return 0} |
| 84 | + var ref = result[1]; |
| 85 | + if (this._labels[ref]) { |
| 86 | + this.setRef(element,ref); |
| 87 | + } else { |
| 88 | + if (!this._refs[ref]) {this._refs[ref] = []} |
| 89 | + this._refs[ref][this._refs[ref].length] = element; |
| 90 | + } |
| 91 | + return 1; |
| 92 | + }, |
| 93 | + |
| 94 | + setRef: function (element,ref) { |
| 95 | + element.innerHTML = this.formatRef(this._labels[ref]); |
| 96 | + element.className = "label-ref"; |
| 97 | + }, |
| 98 | + |
| 99 | + fixRefs: function (label) { |
| 100 | + for (var i = 0; i < this._refs[label].length; i++) |
| 101 | + {this.setRef(this._refs[label][i],label)} |
| 102 | + delete this._refs[label]; |
| 103 | + }, |
| 104 | + |
| 105 | + badRefs: function () { |
| 106 | + for (var label in this._refs) { |
| 107 | + for (var i = 0; i < this._refs[label].length; i++) { |
| 108 | + var element = this._refs[label][i]; |
| 109 | + element.className = "typeset"; |
| 110 | + element.innerHTML = "<span class='error'>Reference '"+label+"' is undefined</span>"; |
| 111 | + } |
| 112 | + } |
| 113 | + }, |
| 114 | + |
| 115 | + makeDIV: function (element) { |
| 116 | + var div = document.createElement('div'); |
| 117 | + div.className = 'jsMath_displayBox'; |
| 118 | + div.innerHTML = '<div class="jsMath_number">' + this.nextNumber() + '</div>'; |
| 119 | + element.parentNode.insertBefore(div,element); |
| 120 | + element.parentNode.removeChild(element); |
| 121 | + div.appendChild(element); |
| 122 | + }, |
| 123 | + |
| 124 | + makeSPAN: function (element) { |
| 125 | + var span = document.createElement('span'); |
| 126 | + span.className = 'jsMath_number'; |
| 127 | + span.style.display = 'inline-block'; |
| 128 | + span.innerHTML = jsMath.EqnNumber.nextNumber(); |
| 129 | + element.parentNode.insertBefore(span,element); |
| 130 | + }, |
| 131 | + |
| 132 | + ConvertMath: function (style,element,nocache) { |
| 133 | + var EqnNumber = jsMath.EqnNumber; |
| 134 | + if (EqnNumber.isRef(element)) return; |
| 135 | + EqnNumber._label = null; EqnNumber._nolabel = 0; |
| 136 | + this.ConvertMath_old(style,element,nocache); |
| 137 | + if (EqnNumber._label || (EqnNumber.autonumber && !EqnNumber._nolabel)) { |
| 138 | + if (element.tagName.toLowerCase() == 'div') { |
| 139 | + EqnNumber.makeDIV(element); |
| 140 | + } else if (element.parentNode.className == 'tex2math_div') { |
| 141 | + EqnNumber.makeSPAN(element); |
| 142 | + } |
| 143 | + } |
| 144 | + }, |
| 145 | + |
| 146 | + ProcessComplete: function () { |
| 147 | + jsMath.EqnNumber.badRefs(); |
| 148 | + this.ProcessComplete_old.apply(this,arguments); |
| 149 | + }, |
| 150 | + |
| 151 | + Init: function () { |
| 152 | + jsMath.Setup.Styles(this.styles); |
| 153 | + jsMath.Translate.ConvertMath_old = jsMath.Translate.ConvertMath; |
| 154 | + jsMath.Translate.ConvertMath = this.ConvertMath; |
| 155 | + jsMath.Translate.ProcessComplete_old = jsMath.Translate.ProcessComplete; |
| 156 | + jsMath.Translate.ProcessComplete = this.ProcessComplete; |
| 157 | + } |
| 158 | + |
| 159 | +}; |
| 160 | + |
| 161 | +if (jsMath.EqnNumber_old) { |
| 162 | + jsMath.Insert(jsMath.EqnNumber,jsMath.EqnNumber_old); |
| 163 | + delete jsMath.EqnNumber_old; |
| 164 | +} |
| 165 | + |
| 166 | +jsMath.Package(jsMath.Parser,{ |
| 167 | + macros: { |
| 168 | + label: 'Label', |
| 169 | + nolabel: 'NoLabel', |
| 170 | + ref: 'Ref' |
| 171 | + }, |
| 172 | + |
| 173 | + Label: function (name) { |
| 174 | + var label = this.GetArgument(this.cmd+name); if (this.error) return; |
| 175 | + var EqnNumber = jsMath.EqnNumber; |
| 176 | + if (!EqnNumber._label) { |
| 177 | + if (!EqnNumber._labels[label]) { |
| 178 | + EqnNumber._label = label; |
| 179 | + EqnNumber._nolabel = 0; |
| 180 | + } else { |
| 181 | + this.Error("Label '"+label+"' is already defined"); |
| 182 | + } |
| 183 | + } else { |
| 184 | + this.Error(this.cmd+name+' can only be used once in an equation'); |
| 185 | + } |
| 186 | + }, |
| 187 | + |
| 188 | + NoLabel: function (name) { |
| 189 | + var EqnNumber = jsMath.EqnNumber; |
| 190 | + EqnNumber._label = null; EqnNumber._nolabel = 1; |
| 191 | + }, |
| 192 | + |
| 193 | + Ref: function (name) { |
| 194 | + this.Error(this.cmd+name+' must be used by itself'); |
| 195 | + } |
| 196 | + |
| 197 | +}); |
| 198 | + |
| 199 | +jsMath.EqnNumber.Init(); |
0 commit comments