Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpnSense
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
OpnSense
Commits
e082aadc
Commit
e082aadc
authored
Mar 10, 2016
by
Ad Schellevis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(legacy) refactor services_upnp.php
parent
cdb17e69
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
326 additions
and
3445 deletions
+326
-3445
autosuggest.js
src/www/javascript/autosuggest.js
+0
-335
LICENSE
src/www/javascript/domTT/LICENSE
+0
-202
behaviour.js
src/www/javascript/domTT/behaviour.js
+0
-254
domLib.js
src/www/javascript/domTT/domLib.js
+0
-706
domTT.js
src/www/javascript/domTT/domTT.js
+0
-1132
fadomatic.js
src/www/javascript/domTT/fadomatic.js
+0
-180
row_helper_dynamic.js
src/www/javascript/row_helper_dynamic.js
+0
-98
suggestions.js
src/www/javascript/suggestions.js
+0
-33
services_upnp.php
src/www/services_upnp.php
+326
-505
No files found.
src/www/javascript/autosuggest.js
deleted
100644 → 0
View file @
cdb17e69
/**
* An autosuggest textbox control.
* @class
* @scope public
*/
function
AutoSuggestControl
(
oTextbox
/*:HTMLInputElement*/
,
oProvider
/*:SuggestionProvider*/
)
{
/**
* The currently selected suggestions.
* @scope private
*/
this
.
cur
/*:int*/
=
-
1
;
/**
* The dropdown list layer.
* @scope private
*/
this
.
layer
=
null
;
/**
* Suggestion provider for the autosuggest feature.
* @scope private.
*/
this
.
provider
/*:SuggestionProvider*/
=
oProvider
;
/**
* The textbox to capture.
* @scope private
*/
this
.
textbox
/*:HTMLInputElement*/
=
oTextbox
;
//initialize the control
this
.
init
();
}
/**
* Autosuggests one or more suggestions for what the user has typed.
* If no suggestions are passed in, then no autosuggest occurs.
* @scope private
* @param aSuggestions An array of suggestion strings.
* @param bTypeAhead If the control should provide a type ahead suggestion.
*/
AutoSuggestControl
.
prototype
.
autosuggest
=
function
(
aSuggestions
/*:Array*/
,
bTypeAhead
/*:boolean*/
)
{
//make sure there's at least one suggestion
if
(
aSuggestions
.
length
>
0
)
{
if
(
bTypeAhead
)
{
this
.
typeAhead
(
aSuggestions
[
0
]);
}
this
.
showSuggestions
(
aSuggestions
);
}
else
{
this
.
hideSuggestions
();
}
};
/**
* Creates the dropdown layer to display multiple suggestions.
* @scope private
*/
AutoSuggestControl
.
prototype
.
createDropDown
=
function
()
{
var
oThis
=
this
;
//create the layer and assign styles
this
.
layer
=
document
.
createElement
(
"
div
"
);
this
.
layer
.
className
=
"
suggestions
"
;
this
.
layer
.
style
.
visibility
=
"
hidden
"
;
this
.
layer
.
style
.
width
=
this
.
textbox
.
offsetWidth
;
//when the user clicks on the a suggestion, get the text (innerHTML)
//and place it into a textbox
this
.
layer
.
onmousedown
=
this
.
layer
.
onmouseup
=
this
.
layer
.
onmouseover
=
function
(
oEvent
)
{
oEvent
=
oEvent
||
window
.
event
;
oTarget
=
oEvent
.
target
||
oEvent
.
srcElement
;
if
(
oEvent
.
type
==
"
mousedown
"
)
{
oThis
.
textbox
.
value
=
oTarget
.
firstChild
.
nodeValue
;
oThis
.
hideSuggestions
();
}
else
if
(
oEvent
.
type
==
"
mouseover
"
)
{
oThis
.
highlightSuggestion
(
oTarget
);
}
else
{
oThis
.
textbox
.
focus
();
}
};
document
.
body
.
appendChild
(
this
.
layer
);
};
/**
* Gets the left coordinate of the textbox.
* @scope private
* @return The left coordinate of the textbox in pixels.
*/
AutoSuggestControl
.
prototype
.
getLeft
=
function
()
/*:int*/
{
var
oNode
=
this
.
textbox
;
var
iLeft
=
0
;
while
(
oNode
.
tagName
!=
"
BODY
"
)
{
iLeft
+=
oNode
.
offsetLeft
;
oNode
=
oNode
.
offsetParent
;
}
return
iLeft
;
};
/**
* Gets the top coordinate of the textbox.
* @scope private
* @return The top coordinate of the textbox in pixels.
*/
AutoSuggestControl
.
prototype
.
getTop
=
function
()
/*:int*/
{
var
oNode
=
this
.
textbox
;
var
iTop
=
0
;
while
(
oNode
.
tagName
!=
"
BODY
"
)
{
iTop
+=
oNode
.
offsetTop
;
oNode
=
oNode
.
offsetParent
;
}
return
iTop
;
};
/**
* Handles three keydown events.
* @scope private
* @param oEvent The event object for the keydown event.
*/
AutoSuggestControl
.
prototype
.
handleKeyDown
=
function
(
oEvent
/*:Event*/
)
{
switch
(
oEvent
.
keyCode
)
{
case
38
:
//up arrow
this
.
previousSuggestion
();
break
;
case
40
:
//down arrow
this
.
nextSuggestion
();
break
;
case
13
:
//enter
this
.
hideSuggestions
();
break
;
}
};
/**
* Handles keyup events.
* @scope private
* @param oEvent The event object for the keyup event.
*/
AutoSuggestControl
.
prototype
.
handleKeyUp
=
function
(
oEvent
/*:Event*/
)
{
var
iKeyCode
=
oEvent
.
keyCode
;
//for backspace (8) and delete (46), shows suggestions without typeahead
if
(
iKeyCode
==
8
||
iKeyCode
==
46
)
{
this
.
provider
.
requestSuggestions
(
this
,
false
);
//make sure not to interfere with non-character keys
}
else
if
(
iKeyCode
<
32
||
(
iKeyCode
>=
33
&&
iKeyCode
<
46
)
||
(
iKeyCode
>=
112
&&
iKeyCode
<=
123
))
{
//ignore
}
else
{
//request suggestions from the suggestion provider with typeahead
this
.
provider
.
requestSuggestions
(
this
,
true
);
}
};
/**
* Hides the suggestion dropdown.
* @scope private
*/
AutoSuggestControl
.
prototype
.
hideSuggestions
=
function
()
{
this
.
layer
.
style
.
visibility
=
"
hidden
"
;
};
/**
* Highlights the given node in the suggestions dropdown.
* @scope private
* @param oSuggestionNode The node representing a suggestion in the dropdown.
*/
AutoSuggestControl
.
prototype
.
highlightSuggestion
=
function
(
oSuggestionNode
)
{
for
(
var
i
=
0
;
i
<
this
.
layer
.
childNodes
.
length
;
i
++
)
{
var
oNode
=
this
.
layer
.
childNodes
[
i
];
if
(
oNode
==
oSuggestionNode
)
{
oNode
.
className
=
"
current
"
;
}
else
if
(
oNode
.
className
==
"
current
"
)
{
oNode
.
className
=
""
;
}
}
};
/**
* Initializes the textbox with event handlers for
* auto suggest functionality.
* @scope private
*/
AutoSuggestControl
.
prototype
.
init
=
function
()
{
//save a reference to this object
var
oThis
=
this
;
//assign the onkeyup event handler
this
.
textbox
.
onkeyup
=
function
(
oEvent
)
{
//check for the proper location of the event object
if
(
!
oEvent
)
{
oEvent
=
window
.
event
;
}
//call the handleKeyUp() method with the event object
oThis
.
handleKeyUp
(
oEvent
);
};
//assign onkeydown event handler
this
.
textbox
.
onkeydown
=
function
(
oEvent
)
{
//check for the proper location of the event object
if
(
!
oEvent
)
{
oEvent
=
window
.
event
;
}
//call the handleKeyDown() method with the event object
oThis
.
handleKeyDown
(
oEvent
);
};
//assign onblur event handler (hides suggestions)
this
.
textbox
.
onblur
=
function
()
{
oThis
.
hideSuggestions
();
};
//create the suggestions dropdown
this
.
createDropDown
();
};
/**
* Highlights the next suggestion in the dropdown and
* places the suggestion into the textbox.
* @scope private
*/
AutoSuggestControl
.
prototype
.
nextSuggestion
=
function
()
{
var
cSuggestionNodes
=
this
.
layer
.
childNodes
;
if
(
cSuggestionNodes
.
length
>
0
&&
this
.
cur
<
cSuggestionNodes
.
length
-
1
)
{
var
oNode
=
cSuggestionNodes
[
++
this
.
cur
];
this
.
highlightSuggestion
(
oNode
);
this
.
textbox
.
value
=
oNode
.
firstChild
.
nodeValue
;
}
};
/**
* Highlights the previous suggestion in the dropdown and
* places the suggestion into the textbox.
* @scope private
*/
AutoSuggestControl
.
prototype
.
previousSuggestion
=
function
()
{
var
cSuggestionNodes
=
this
.
layer
.
childNodes
;
if
(
cSuggestionNodes
.
length
>
0
&&
this
.
cur
>
0
)
{
var
oNode
=
cSuggestionNodes
[
--
this
.
cur
];
this
.
highlightSuggestion
(
oNode
);
this
.
textbox
.
value
=
oNode
.
firstChild
.
nodeValue
;
}
};
/**
* Selects a range of text in the textbox.
* @scope public
* @param iStart The start index (base 0) of the selection.
* @param iLength The number of characters to select.
*/
AutoSuggestControl
.
prototype
.
selectRange
=
function
(
iStart
/*:int*/
,
iLength
/*:int*/
)
{
//use text ranges for Internet Explorer
if
(
this
.
textbox
.
createTextRange
)
{
var
oRange
=
this
.
textbox
.
createTextRange
();
oRange
.
moveStart
(
"
character
"
,
iStart
);
oRange
.
moveEnd
(
"
character
"
,
iLength
-
this
.
textbox
.
value
.
length
);
oRange
.
select
();
//use setSelectionRange() for Mozilla
}
else
if
(
this
.
textbox
.
setSelectionRange
)
{
this
.
textbox
.
setSelectionRange
(
iStart
,
iLength
);
}
//set focus back to the textbox
this
.
textbox
.
focus
();
};
/**
* Builds the suggestion layer contents, moves it into position,
* and displays the layer.
* @scope private
* @param aSuggestions An array of suggestions for the control.
*/
AutoSuggestControl
.
prototype
.
showSuggestions
=
function
(
aSuggestions
/*:Array*/
)
{
var
oDiv
=
null
;
this
.
layer
.
innerHTML
=
""
;
//clear contents of the layer
for
(
var
i
=
0
;
i
<
aSuggestions
.
length
;
i
++
)
{
oDiv
=
document
.
createElement
(
"
div
"
);
oDiv
.
appendChild
(
document
.
createTextNode
(
aSuggestions
[
i
]));
this
.
layer
.
appendChild
(
oDiv
);
}
this
.
layer
.
style
.
left
=
this
.
getLeft
()
+
"
px
"
;
this
.
layer
.
style
.
top
=
(
this
.
getTop
()
+
this
.
textbox
.
offsetHeight
)
+
"
px
"
;
this
.
layer
.
style
.
visibility
=
"
visible
"
;
};
/**
* Inserts a suggestion into the textbox, highlighting the
* suggested part of the text.
* @scope private
* @param sSuggestion The suggestion for the textbox.
*/
AutoSuggestControl
.
prototype
.
typeAhead
=
function
(
sSuggestion
/*:String*/
)
{
//check for support of typeahead functionality
if
(
this
.
textbox
.
createTextRange
||
this
.
textbox
.
setSelectionRange
){
var
iLen
=
this
.
textbox
.
value
.
length
;
this
.
textbox
.
value
=
sSuggestion
;
this
.
selectRange
(
iLen
,
sSuggestion
.
length
);
}
};
src/www/javascript/domTT/LICENSE
deleted
100644 → 0
View file @
cdb17e69
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
src/www/javascript/domTT/behaviour.js
deleted
100644 → 0
View file @
cdb17e69
/*
Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
of Simon Willison (see comments by Simon below).
Description:
Uses css selectors to apply javascript behaviours to enable
unobtrusive javascript in html documents.
Usage:
var myrules = {
'b.someclass' : function(element){
element.onclick = function(){
alert(this.innerHTML);
}
},
'#someid u' : function(element){
element.onmouseover = function(){
this.innerHTML = "BLAH!";
}
}
};
Behaviour.register(myrules);
// Call Behaviour.apply() to re-apply the rules (if you
// update the dom, etc).
License:
This file is entirely BSD licensed.
More information:
http://ripcord.co.nz/behaviour/
*/
var
Behaviour
=
{
list
:
new
Array
,
register
:
function
(
sheet
){
Behaviour
.
list
.
push
(
sheet
);
},
start
:
function
(){
Behaviour
.
addLoadEvent
(
function
(){
Behaviour
.
apply
();
});
},
apply
:
function
(){
for
(
h
=
0
;
sheet
=
Behaviour
.
list
[
h
];
h
++
){
for
(
selector
in
sheet
){
list
=
document
.
getElementsBySelector
(
selector
);
if
(
!
list
){
continue
;
}
for
(
i
=
0
;
element
=
list
[
i
];
i
++
){
sheet
[
selector
](
element
);
}
}
}
},
addLoadEvent
:
function
(
func
){
var
oldonload
=
window
.
onload
;
if
(
typeof
window
.
onload
!=
'
function
'
)
{
window
.
onload
=
func
;
}
else
{
window
.
onload
=
function
()
{
oldonload
();
func
();
};
}
}
};
Behaviour
.
start
();
/*
The following code is Copyright (C) Simon Willison 2004.
document.getElementsBySelector(selector)
- returns an array of element objects from the current document
matching the CSS selector. Selectors can contain element names,
class names and ids and can be nested. For example:
elements = document.getElementsBySelect('div#main p a.external')
Will return an array of all 'a' elements with 'external' in their
class attribute that are contained inside 'p' elements that are
contained inside the 'div' element which has id="main"
New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
See http://www.w3.org/TR/css3-selectors/#attribute-selectors
Version 0.4 - Simon Willison, March 25th 2003
-- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
-- Opera 7 fails
*/
function
getAllChildren
(
e
)
{
// Returns all children of element. Workaround required for IE5/Windows. Ugh.
return
e
.
all
?
e
.
all
:
e
.
getElementsByTagName
(
'
*
'
);
}
document
.
getElementsBySelector
=
function
(
selector
)
{
// Attempt to fail gracefully in lesser browsers
if
(
!
document
.
getElementsByTagName
)
{
return
new
Array
();
}
// Split selector in to tokens
var
tokens
=
selector
.
split
(
'
'
);
var
currentContext
=
new
Array
(
document
);
for
(
var
i
=
0
;
i
<
tokens
.
length
;
i
++
)
{
token
=
tokens
[
i
].
replace
(
/^
\s
+/
,
''
).
replace
(
/
\s
+$/
,
''
);
if
(
token
.
indexOf
(
'
#
'
)
>
-
1
)
{
// Token is an ID selector
var
bits
=
token
.
split
(
'
#
'
);
var
tagName
=
bits
[
0
];
var
id
=
bits
[
1
];
var
element
=
document
.
getElementById
(
id
);
if
(
tagName
&&
element
.
nodeName
.
toLowerCase
()
!=
tagName
)
{
// tag with that ID not found, return false
return
new
Array
();
}
// Set currentContext to contain just this element
currentContext
=
new
Array
(
element
);
continue
;
// Skip to next token
}
if
(
token
.
indexOf
(
'
.
'
)
>
-
1
)
{
// Token contains a class selector
var
bits
=
token
.
split
(
'
.
'
);
var
tagName
=
bits
[
0
];
var
className
=
bits
[
1
];
if
(
!
tagName
)
{
tagName
=
'
*
'
;
}
// Get elements matching tag, filter them for class selector
var
found
=
new
Array
;
var
foundCount
=
0
;
for
(
var
h
=
0
;
h
<
currentContext
.
length
;
h
++
)
{
var
elements
;
if
(
tagName
==
'
*
'
)
{
elements
=
getAllChildren
(
currentContext
[
h
]);
}
else
{
elements
=
currentContext
[
h
].
getElementsByTagName
(
tagName
);
}
for
(
var
j
=
0
;
j
<
elements
.
length
;
j
++
)
{
found
[
foundCount
++
]
=
elements
[
j
];
}
}
currentContext
=
new
Array
;
var
currentContextIndex
=
0
;
for
(
var
k
=
0
;
k
<
found
.
length
;
k
++
)
{
if
(
found
[
k
].
className
&&
found
[
k
].
className
.
match
(
new
RegExp
(
'
\\
b
'
+
className
+
'
\\
b
'
)))
{
currentContext
[
currentContextIndex
++
]
=
found
[
k
];
}
}
continue
;
// Skip to next token
}
// Code to deal with attribute selectors
if
(
token
.
match
(
/^
(\w
*
)\[(\w
+
)([
=~
\|\^\$\*]?)
=
?
"
?([^\]
"
]
*
)
"
?\]
$/
))
{
var
tagName
=
RegExp
.
$1
;
var
attrName
=
RegExp
.
$2
;
var
attrOperator
=
RegExp
.
$3
;
var
attrValue
=
RegExp
.
$4
;
if
(
!
tagName
)
{
tagName
=
'
*
'
;
}
// Grab all of the tagName elements within current context
var
found
=
new
Array
;
var
foundCount
=
0
;
for
(
var
h
=
0
;
h
<
currentContext
.
length
;
h
++
)
{
var
elements
;
if
(
tagName
==
'
*
'
)
{
elements
=
getAllChildren
(
currentContext
[
h
]);
}
else
{
elements
=
currentContext
[
h
].
getElementsByTagName
(
tagName
);
}
for
(
var
j
=
0
;
j
<
elements
.
length
;
j
++
)
{
found
[
foundCount
++
]
=
elements
[
j
];
}
}
currentContext
=
new
Array
;
var
currentContextIndex
=
0
;
var
checkFunction
;
// This function will be used to filter the elements
switch
(
attrOperator
)
{
case
'
=
'
:
// Equality
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
)
==
attrValue
);
};
break
;
case
'
~
'
:
// Match one of space separated words
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
).
match
(
new
RegExp
(
'
\\
b
'
+
attrValue
+
'
\\
b
'
)));
};
break
;
case
'
|
'
:
// Match start with value followed by optional hyphen
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
).
match
(
new
RegExp
(
'
^
'
+
attrValue
+
'
-?
'
)));
};
break
;
case
'
^
'
:
// Match starts with value
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
).
indexOf
(
attrValue
)
==
0
);
};
break
;
case
'
$
'
:
// Match ends with value - fails with "Warning" in Opera 7
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
).
lastIndexOf
(
attrValue
)
==
e
.
getAttribute
(
attrName
).
length
-
attrValue
.
length
);
};
break
;
case
'
*
'
:
// Match ends with value
checkFunction
=
function
(
e
)
{
return
(
e
.
getAttribute
(
attrName
).
indexOf
(
attrValue
)
>
-
1
);
};
break
;
default
:
// Just test for existence of attribute
checkFunction
=
function
(
e
)
{
return
e
.
getAttribute
(
attrName
);
};
}
currentContext
=
new
Array
;
var
currentContextIndex
=
0
;
for
(
var
k
=
0
;
k
<
found
.
length
;
k
++
)
{
if
(
checkFunction
(
found
[
k
]))
{
currentContext
[
currentContextIndex
++
]
=
found
[
k
];
}
}
// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
continue
;
// Skip to next token
}
if
(
!
currentContext
[
0
]){
return
;
}
// If we get here, token is JUST an element (not a class or ID selector)
tagName
=
token
;
var
found
=
new
Array
;
var
foundCount
=
0
;
for
(
var
h
=
0
;
h
<
currentContext
.
length
;
h
++
)
{
var
elements
=
currentContext
[
h
].
getElementsByTagName
(
tagName
);
for
(
var
j
=
0
;
j
<
elements
.
length
;
j
++
)
{
found
[
foundCount
++
]
=
elements
[
j
];
}
}
currentContext
=
found
;
}
return
currentContext
;
}
/* That revolting regular expression explained
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
\---/ \---/\-------------/ \-------/
| | | |
| | | The value
| | ~,|,^,$,* or =
| Attribute
Tag
*/
src/www/javascript/domTT/domLib.js
deleted
100644 → 0
View file @
cdb17e69
/** $Id: domLib.js 2321 2006-06-12 06:45:41Z dallen $ */
// {{{ license
/*
* Copyright 2002-2005 Dan Allen, Mojavelinux.com (dan.allen@mojavelinux.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// }}}
// {{{ intro
/**
* Title: DOM Library Core
* Version: 0.70
*
* Summary:
* A set of commonly used functions that make it easier to create javascript
* applications that rely on the DOM.
*
* Updated: 2005/05/17
*
* Maintainer: Dan Allen <dan.allen@mojavelinux.com>
* Maintainer: Jason Rust <jrust@rustyparts.com>
*
* License: Apache 2.0
*/
// }}}
// {{{ global constants (DO NOT EDIT)
// -- Browser Detection --
var
domLib_userAgent
=
navigator
.
userAgent
.
toLowerCase
();
var
domLib_isMac
=
navigator
.
appVersion
.
indexOf
(
'
Mac
'
)
!=
-
1
;
var
domLib_isWin
=
domLib_userAgent
.
indexOf
(
'
windows
'
)
!=
-
1
;
// NOTE: could use window.opera for detecting Opera
var
domLib_isOpera
=
domLib_userAgent
.
indexOf
(
'
opera
'
)
!=
-
1
;
var
domLib_isOpera7up
=
domLib_userAgent
.
match
(
/opera.
(
7|8
)
/i
);
var
domLib_isSafari
=
domLib_userAgent
.
indexOf
(
'
safari
'
)
!=
-
1
;
var
domLib_isKonq
=
domLib_userAgent
.
indexOf
(
'
konqueror
'
)
!=
-
1
;
// Both konqueror and safari use the khtml rendering engine
var
domLib_isKHTML
=
(
domLib_isKonq
||
domLib_isSafari
||
domLib_userAgent
.
indexOf
(
'
khtml
'
)
!=
-
1
);
var
domLib_isIE
=
(
!
domLib_isKHTML
&&
!
domLib_isOpera
&&
(
domLib_userAgent
.
indexOf
(
'
msie 5
'
)
!=
-
1
||
domLib_userAgent
.
indexOf
(
'
msie 6
'
)
!=
-
1
||
domLib_userAgent
.
indexOf
(
'
msie 7
'
)
!=
-
1
||
domLib_userAgent
.
indexOf
(
'
msie 8
'
)
!=
-
1
));
var
domLib_isIE5up
=
domLib_isIE
;
var
domLib_isIE50
=
(
domLib_isIE
&&
domLib_userAgent
.
indexOf
(
'
msie 5.0
'
)
!=
-
1
);
var
domLib_isIE55
=
(
domLib_isIE
&&
domLib_userAgent
.
indexOf
(
'
msie 5.5
'
)
!=
-
1
);
var
domLib_isIE5
=
(
domLib_isIE50
||
domLib_isIE55
);
// safari and konq may use string "khtml, like gecko", so check for destinctive /
var
domLib_isGecko
=
domLib_userAgent
.
indexOf
(
'
gecko/
'
)
!=
-
1
;
var
domLib_isMacIE
=
(
domLib_isIE
&&
domLib_isMac
);
var
domLib_isIE55up
=
domLib_isIE5up
&&
!
domLib_isIE50
&&
!
domLib_isMacIE
;
var
domLib_isIE6up
=
domLib_isIE55up
&&
!
domLib_isIE55
;
// -- Browser Abilities --
var
domLib_standardsMode
=
(
document
.
compatMode
&&
document
.
compatMode
==
'
CSS1Compat
'
);
var
domLib_useLibrary
=
(
domLib_isOpera7up
||
domLib_isKHTML
||
domLib_isIE5up
||
domLib_isGecko
||
domLib_isMacIE
||
document
.
defaultView
);
// fixed in Konq3.2
var
domLib_hasBrokenTimeout
=
(
domLib_isMacIE
||
(
domLib_isKonq
&&
domLib_userAgent
.
match
(
/konqueror
\/
3.
([
2-9
])
/
)
==
null
));
var
domLib_canFade
=
(
domLib_isGecko
||
domLib_isIE
||
domLib_isSafari
||
domLib_isOpera
);
var
domLib_canDrawOverSelect
=
(
domLib_isMac
||
domLib_isOpera
||
domLib_isGecko
);
var
domLib_canDrawOverFlash
=
(
domLib_isMac
||
domLib_isWin
);
// -- Event Variables --
var
domLib_eventTarget
=
domLib_isIE
?
'
srcElement
'
:
'
currentTarget
'
;
var
domLib_eventButton
=
domLib_isIE
?
'
button
'
:
'
which
'
;
var
domLib_eventTo
=
domLib_isIE
?
'
toElement
'
:
'
relatedTarget
'
;
var
domLib_stylePointer
=
domLib_isIE
?
'
hand
'
:
'
pointer
'
;
// NOTE: a bug exists in Opera that prevents maxWidth from being set to 'none', so we make it huge
var
domLib_styleNoMaxWidth
=
domLib_isOpera
?
'
10000px
'
:
'
none
'
;
var
domLib_hidePosition
=
'
-1000px
'
;
var
domLib_scrollbarWidth
=
14
;
var
domLib_autoId
=
1
;
var
domLib_zIndex
=
1010
;
// -- Detection --
var
domLib_collisionElements
;
var
domLib_collisionsCached
=
false
;
var
domLib_timeoutStateId
=
0
;
var
domLib_timeoutStates
=
new
domTT_Hash
();
// }}}
// {{{ DOM enhancements
if
(
!
document
.
ELEMENT_NODE
)
{
document
.
ELEMENT_NODE
=
1
;
document
.
ATTRIBUTE_NODE
=
2
;
document
.
TEXT_NODE
=
3
;
document
.
DOCUMENT_NODE
=
9
;
document
.
DOCUMENT_FRAGMENT_NODE
=
11
;
}
function
domLib_clone
(
obj
)
{
var
copy
=
{};
for
(
var
i
in
obj
)
{
var
value
=
obj
[
i
];
try
{
if
(
value
!=
null
&&
typeof
(
value
)
==
'
object
'
&&
value
!=
window
&&
!
value
.
nodeType
)
{
copy
[
i
]
=
domLib_clone
(
value
);
}
else
{
copy
[
i
]
=
value
;
}
}
catch
(
e
)
{
copy
[
i
]
=
value
;
}
}
return
copy
;
}
// }}}
// {{{ class domTT_Hash()
function
domTT_Hash
()
{
this
.
length
=
0
;
this
.
numericLength
=
0
;
this
.
elementData
=
[];
for
(
var
i
=
0
;
i
<
arguments
.
length
;
i
+=
2
)
{
if
(
typeof
(
arguments
[
i
+
1
])
!=
'
undefined
'
)
{
this
.
elementData
[
arguments
[
i
]]
=
arguments
[
i
+
1
];
this
.
length
++
;
if
(
arguments
[
i
]
==
parseInt
(
arguments
[
i
]))
{
this
.
numericLength
++
;
}
}
}
}
// using prototype as opposed to inner functions saves on memory
domTT_Hash
.
prototype
.
get
=
function
(
in_key
)
{
if
(
typeof
(
this
.
elementData
[
in_key
])
!=
'
undefined
'
)
{
return
this
.
elementData
[
in_key
];
}
return
null
;
};
domTT_Hash
.
prototype
.
set
=
function
(
in_key
,
in_value
)
{
if
(
typeof
(
in_value
)
!=
'
undefined
'
)
{
if
(
typeof
(
this
.
elementData
[
in_key
])
==
'
undefined
'
)
{
this
.
length
++
;
if
(
in_key
==
parseInt
(
in_key
))
{
this
.
numericLength
++
;
}
}
return
this
.
elementData
[
in_key
]
=
in_value
;
}
return
false
;
};
domTT_Hash
.
prototype
.
remove
=
function
(
in_key
)
{
var
tmp_value
;
if
(
typeof
(
this
.
elementData
[
in_key
])
!=
'
undefined
'
)
{
this
.
length
--
;
if
(
in_key
==
parseInt
(
in_key
))
{
this
.
numericLength
--
;
}
tmp_value
=
this
.
elementData
[
in_key
];
delete
this
.
elementData
[
in_key
];
}
return
tmp_value
;
};
domTT_Hash
.
prototype
.
size
=
function
()
{
return
this
.
length
;
};
domTT_Hash
.
prototype
.
has
=
function
(
in_key
)
{
return
typeof
(
this
.
elementData
[
in_key
])
!=
'
undefined
'
;
};
domTT_Hash
.
prototype
.
find
=
function
(
in_obj
)
{
for
(
var
tmp_key
in
this
.
elementData
)
{
if
(
this
.
elementData
[
tmp_key
]
==
in_obj
)
{
return
tmp_key
;
}
}
return
null
;
};
domTT_Hash
.
prototype
.
merge
=
function
(
in_hash
)
{
for
(
var
tmp_key
in
in_hash
.
elementData
)
{
if
(
typeof
(
this
.
elementData
[
tmp_key
])
==
'
undefined
'
)
{
this
.
length
++
;
if
(
tmp_key
==
parseInt
(
tmp_key
))
{
this
.
numericLength
++
;
}
}
this
.
elementData
[
tmp_key
]
=
in_hash
.
elementData
[
tmp_key
];
}
};
domTT_Hash
.
prototype
.
compare
=
function
(
in_hash
)
{
if
(
this
.
length
!=
in_hash
.
length
)
{
return
false
;
}
for
(
var
tmp_key
in
this
.
elementData
)
{
if
(
this
.
elementData
[
tmp_key
]
!=
in_hash
.
elementData
[
tmp_key
])
{
return
false
;
}
}
return
true
;
};
// }}}
// {{{ domLib_isDescendantOf()
function
domLib_isDescendantOf
(
in_object
,
in_ancestor
,
in_bannedTags
)
{
if
(
in_object
==
null
)
{
return
false
;
}
if
(
in_object
==
in_ancestor
)
{
return
true
;
}
if
(
typeof
(
in_bannedTags
)
!=
'
undefined
'
&&
(
'
,
'
+
in_bannedTags
.
join
(
'
,
'
)
+
'
,
'
).
indexOf
(
'
,
'
+
in_object
.
tagName
+
'
,
'
)
!=
-
1
)
{
return
false
;
}
while
(
in_object
!=
document
.
documentElement
)
{
try
{
if
((
tmp_object
=
in_object
.
offsetParent
)
&&
tmp_object
==
in_ancestor
)
{
return
true
;
}
else
if
((
tmp_object
=
in_object
.
parentNode
)
==
in_ancestor
)
{
return
true
;
}
else
{
in_object
=
tmp_object
;
}
}
// in case we get some wierd error, assume we left the building
catch
(
e
)
{
return
false
;
}
}
return
false
;
}
// }}}
// {{{ domLib_detectCollisions()
/**
* For any given target element, determine if elements on the page
* are colliding with it that do not obey the rules of z-index.
*/
function
domLib_detectCollisions
(
in_object
,
in_recover
,
in_useCache
)
{
// the reason for the cache is that if the root menu is built before
// the page is done loading, then it might not find all the elements.
// so really the only time you don't use cache is when building the
// menu as part of the page load
if
(
!
domLib_collisionsCached
)
{
var
tags
=
[];
if
(
!
domLib_canDrawOverFlash
)
{
tags
[
tags
.
length
]
=
'
object
'
;
}
if
(
!
domLib_canDrawOverSelect
)
{
tags
[
tags
.
length
]
=
'
select
'
;
}
domLib_collisionElements
=
domLib_getElementsByTagNames
(
tags
,
true
);
domLib_collisionsCached
=
in_useCache
;
}
// if we don't have a tip, then unhide selects
if
(
in_recover
)
{
for
(
var
cnt
=
0
;
cnt
<
domLib_collisionElements
.
length
;
cnt
++
)
{
var
thisElement
=
domLib_collisionElements
[
cnt
];
if
(
!
thisElement
.
hideList
)
{
thisElement
.
hideList
=
new
domTT_Hash
();
}
thisElement
.
hideList
.
remove
(
in_object
.
id
);
if
(
!
thisElement
.
hideList
.
length
)
{
domLib_collisionElements
[
cnt
].
style
.
visibility
=
'
visible
'
;
if
(
domLib_isKonq
)
{
domLib_collisionElements
[
cnt
].
style
.
display
=
''
;
}
}
}
return
;
}
else
if
(
domLib_collisionElements
.
length
==
0
)
{
return
;
}
// okay, we have a tip, so hunt and destroy
var
objectOffsets
=
domLib_getOffsets
(
in_object
);
for
(
var
cnt
=
0
;
cnt
<
domLib_collisionElements
.
length
;
cnt
++
)
{
var
thisElement
=
domLib_collisionElements
[
cnt
];
// if collision element is in active element, move on
// WARNING: is this too costly?
if
(
domLib_isDescendantOf
(
thisElement
,
in_object
))
{
continue
;
}
// konqueror only has trouble with multirow selects
if
(
domLib_isKonq
&&
thisElement
.
tagName
==
'
SELECT
'
&&
(
thisElement
.
size
<=
1
&&
!
thisElement
.
multiple
))
{
continue
;
}
if
(
!
thisElement
.
hideList
)
{
thisElement
.
hideList
=
new
domTT_Hash
();
}
var
selectOffsets
=
domLib_getOffsets
(
thisElement
);
var
center2centerDistance
=
Math
.
sqrt
(
Math
.
pow
(
selectOffsets
.
get
(
'
leftCenter
'
)
-
objectOffsets
.
get
(
'
leftCenter
'
),
2
)
+
Math
.
pow
(
selectOffsets
.
get
(
'
topCenter
'
)
-
objectOffsets
.
get
(
'
topCenter
'
),
2
));
var
radiusSum
=
selectOffsets
.
get
(
'
radius
'
)
+
objectOffsets
.
get
(
'
radius
'
);
// the encompassing circles are overlapping, get in for a closer look
if
(
center2centerDistance
<
radiusSum
)
{
// tip is left of select
if
((
objectOffsets
.
get
(
'
leftCenter
'
)
<=
selectOffsets
.
get
(
'
leftCenter
'
)
&&
objectOffsets
.
get
(
'
right
'
)
<
selectOffsets
.
get
(
'
left
'
))
||
// tip is right of select
(
objectOffsets
.
get
(
'
leftCenter
'
)
>
selectOffsets
.
get
(
'
leftCenter
'
)
&&
objectOffsets
.
get
(
'
left
'
)
>
selectOffsets
.
get
(
'
right
'
))
||
// tip is above select
(
objectOffsets
.
get
(
'
topCenter
'
)
<=
selectOffsets
.
get
(
'
topCenter
'
)
&&
objectOffsets
.
get
(
'
bottom
'
)
<
selectOffsets
.
get
(
'
top
'
))
||
// tip is below select
(
objectOffsets
.
get
(
'
topCenter
'
)
>
selectOffsets
.
get
(
'
topCenter
'
)
&&
objectOffsets
.
get
(
'
top
'
)
>
selectOffsets
.
get
(
'
bottom
'
)))
{
thisElement
.
hideList
.
remove
(
in_object
.
id
);
if
(
!
thisElement
.
hideList
.
length
)
{
thisElement
.
style
.
visibility
=
'
visible
'
;
if
(
domLib_isKonq
)
{
thisElement
.
style
.
display
=
''
;
}
}
}
else
{
thisElement
.
hideList
.
set
(
in_object
.
id
,
true
);
thisElement
.
style
.
visibility
=
'
hidden
'
;
if
(
domLib_isKonq
)
{
thisElement
.
style
.
display
=
'
none
'
;
}
}
}
}
}
// }}}
// {{{ domLib_getOffsets()
function
domLib_getOffsets
(
in_object
,
in_preserveScroll
)
{
if
(
typeof
(
in_preserveScroll
)
==
'
undefined
'
)
{
in_preserveScroll
=
false
;
}
var
originalObject
=
in_object
;
var
originalWidth
=
in_object
.
offsetWidth
;
var
originalHeight
=
in_object
.
offsetHeight
;
var
offsetLeft
=
0
;
var
offsetTop
=
0
;
while
(
in_object
)
{
offsetLeft
+=
in_object
.
offsetLeft
;
offsetTop
+=
in_object
.
offsetTop
;
in_object
=
in_object
.
offsetParent
;
// consider scroll offset of parent elements
if
(
in_object
&&
!
in_preserveScroll
)
{
offsetLeft
-=
in_object
.
scrollLeft
;
offsetTop
-=
in_object
.
scrollTop
;
}
}
// MacIE misreports the offsets (even with margin: 0 in body{}), still not perfect
if
(
domLib_isMacIE
)
{
offsetLeft
+=
10
;
offsetTop
+=
10
;
}
return
new
domTT_Hash
(
'
left
'
,
offsetLeft
,
'
top
'
,
offsetTop
,
'
right
'
,
offsetLeft
+
originalWidth
,
'
bottom
'
,
offsetTop
+
originalHeight
,
'
leftCenter
'
,
offsetLeft
+
originalWidth
/
2
,
'
topCenter
'
,
offsetTop
+
originalHeight
/
2
,
'
radius
'
,
Math
.
max
(
originalWidth
,
originalHeight
)
);
}
// }}}
// {{{ domLib_setTimeout()
function
domLib_setTimeout
(
in_function
,
in_timeout
,
in_args
)
{
if
(
typeof
(
in_args
)
==
'
undefined
'
)
{
in_args
=
[];
}
if
(
in_timeout
==
-
1
)
{
// timeout event is disabled
return
0
;
}
else
if
(
in_timeout
==
0
)
{
in_function
(
in_args
);
return
0
;
}
// must make a copy of the arguments so that we release the reference
var
args
=
domLib_clone
(
in_args
);
if
(
!
domLib_hasBrokenTimeout
)
{
return
setTimeout
(
function
()
{
in_function
(
args
);
},
in_timeout
);
}
else
{
var
id
=
domLib_timeoutStateId
++
;
var
data
=
new
domTT_Hash
();
data
.
set
(
'
function
'
,
in_function
);
data
.
set
(
'
args
'
,
args
);
domLib_timeoutStates
.
set
(
id
,
data
);
data
.
set
(
'
timeoutId
'
,
setTimeout
(
'
domLib_timeoutStates.get(
'
+
id
+
'
).get(
\'
function
\'
)(domLib_timeoutStates.get(
'
+
id
+
'
).get(
\'
args
\'
)); domLib_timeoutStates.remove(
'
+
id
+
'
);
'
,
in_timeout
));
return
id
;
}
}
// }}}
// {{{ domLib_clearTimeout()
function
domLib_clearTimeout
(
in_id
)
{
if
(
!
domLib_hasBrokenTimeout
)
{
if
(
in_id
>
0
)
{
clearTimeout
(
in_id
);
}
}
else
{
if
(
domLib_timeoutStates
.
has
(
in_id
))
{
clearTimeout
(
domLib_timeoutStates
.
get
(
in_id
).
get
(
'
timeoutId
'
));
domLib_timeoutStates
.
remove
(
in_id
);
}
}
}
// }}}
// {{{ domLib_getEventPosition()
function
domLib_getEventPosition
(
in_eventObj
)
{
var
eventPosition
=
new
domTT_Hash
(
'
x
'
,
0
,
'
y
'
,
0
,
'
scrollX
'
,
0
,
'
scrollY
'
,
0
);
// IE varies depending on standard compliance mode
if
(
domLib_isIE
)
{
var
doc
=
(
domLib_standardsMode
?
document
.
documentElement
:
document
.
body
);
// NOTE: events may fire before the body has been loaded
if
(
doc
)
{
eventPosition
.
set
(
'
x
'
,
in_eventObj
.
clientX
+
doc
.
scrollLeft
);
eventPosition
.
set
(
'
y
'
,
in_eventObj
.
clientY
+
doc
.
scrollTop
);
eventPosition
.
set
(
'
scrollX
'
,
doc
.
scrollLeft
);
eventPosition
.
set
(
'
scrollY
'
,
doc
.
scrollTop
);
}
}
else
{
eventPosition
.
set
(
'
x
'
,
in_eventObj
.
pageX
);
eventPosition
.
set
(
'
y
'
,
in_eventObj
.
pageY
);
eventPosition
.
set
(
'
scrollX
'
,
in_eventObj
.
pageX
-
in_eventObj
.
clientX
);
eventPosition
.
set
(
'
scrollY
'
,
in_eventObj
.
pageY
-
in_eventObj
.
clientY
);
}
return
eventPosition
;
}
// }}}
// {{{ domLib_cancelBubble()
function
domLib_cancelBubble
(
in_event
)
{
var
eventObj
=
in_event
?
in_event
:
window
.
event
;
eventObj
.
cancelBubble
=
true
;
}
// }}}
// {{{ domLib_getIFrameReference()
function
domLib_getIFrameReference
(
in_frame
)
{
if
(
domLib_isGecko
||
domLib_isIE
)
{
return
in_frame
.
frameElement
;
}
else
{
// we could either do it this way or require an id on the frame
// equivalent to the name
var
name
=
in_frame
.
name
;
if
(
!
name
||
!
in_frame
.
parent
)
{
return
null
;
}
var
candidates
=
in_frame
.
parent
.
document
.
getElementsByTagName
(
'
iframe
'
);
for
(
var
i
=
0
;
i
<
candidates
.
length
;
i
++
)
{
if
(
candidates
[
i
].
name
==
name
)
{
return
candidates
[
i
];
}
}
return
null
;
}
}
// }}}
// {{{ domLib_getElementsByClass()
function
domLib_getElementsByClass
(
in_class
)
{
var
elements
=
domLib_isIE5
?
document
.
all
:
document
.
getElementsByTagName
(
'
*
'
);
var
matches
=
[];
var
cnt
=
0
;
for
(
var
i
=
0
;
i
<
elements
.
length
;
i
++
)
{
if
((
"
"
+
elements
[
i
].
className
+
"
"
).
indexOf
(
"
"
+
in_class
+
"
"
)
!=
-
1
)
{
matches
[
cnt
++
]
=
elements
[
i
];
}
}
return
matches
;
}
// }}}
// {{{ domLib_getElementsByTagNames()
function
domLib_getElementsByTagNames
(
in_list
,
in_excludeHidden
)
{
var
elements
=
[];
for
(
var
i
=
0
;
i
<
in_list
.
length
;
i
++
)
{
var
matches
=
document
.
getElementsByTagName
(
in_list
[
i
]);
for
(
var
j
=
0
;
j
<
matches
.
length
;
j
++
)
{
// skip objects that have nested embeds, or else we get "flashing"
if
(
matches
[
j
].
tagName
==
'
OBJECT
'
&&
domLib_isGecko
)
{
var
kids
=
matches
[
j
].
childNodes
;
var
skip
=
false
;
for
(
var
k
=
0
;
k
<
kids
.
length
;
k
++
)
{
if
(
kids
[
k
].
tagName
==
'
EMBED
'
)
{
skip
=
true
;
break
;
}
}
if
(
skip
)
continue
;
}
if
(
in_excludeHidden
&&
domLib_getComputedStyle
(
matches
[
j
],
'
visibility
'
)
==
'
hidden
'
)
{
continue
;
}
elements
[
elements
.
length
]
=
matches
[
j
];
}
}
return
elements
;
}
// }}}
// {{{ domLib_getComputedStyle()
function
domLib_getComputedStyle
(
in_obj
,
in_property
)
{
if
(
domLib_isIE
)
{
var
humpBackProp
=
in_property
.
replace
(
/-
(
.
)
/
,
function
(
a
,
b
)
{
return
b
.
toUpperCase
();
});
return
eval
(
'
in_obj.currentStyle.
'
+
humpBackProp
);
}
// getComputedStyle() is broken in konqueror, so let's go for the style object
else
if
(
domLib_isKonq
)
{
//var humpBackProp = in_property.replace(/-(.)/, function (a, b) { return b.toUpperCase(); });
return
eval
(
'
in_obj.style.
'
+
in_property
);
}
else
{
return
document
.
defaultView
.
getComputedStyle
(
in_obj
,
null
).
getPropertyValue
(
in_property
);
}
}
// }}}
// {{{ makeTrue()
function
makeTrue
()
{
return
true
;
}
// }}}
// {{{ makeFalse()
function
makeFalse
()
{
return
false
;
}
// }}}
src/www/javascript/domTT/domTT.js
deleted
100644 → 0
View file @
cdb17e69
/** $Id: domTT.js 2324 2006-06-12 07:06:39Z dallen $ */
// {{{ license
/*
* Copyright 2002-2005 Dan Allen, Mojavelinux.com (dan.allen@mojavelinux.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// }}}
// {{{ intro
/**
* Title: DOM Tooltip Library
* Version: 0.7.3
*
* Summary:
* Allows developers to add custom tooltips to the webpages. Tooltips are
* generated using the domTT_activate() function and customized by setting
* a handful of options.
*
* Maintainer: Dan Allen <dan.allen@mojavelinux.com>
* Contributors:
* Josh Gross <josh@jportalhome.com>
* Jason Rust <jason@rustyparts.com>
*
* License: Apache 2.0
* However, if you use this library, you earn the position of official bug
* reporter :) Please post questions or problem reports to the newsgroup:
*
* http://groups-beta.google.com/group/dom-tooltip
*
* If you are doing this for commercial work, perhaps you could send me a few
* Starbucks Coffee gift dollars or PayPal bucks to encourage future
* developement (NOT REQUIRED). E-mail me for my snail mail address.
*
* Homepage: http://www.mojavelinux.com/projects/domtooltip/
*
* Newsgroup: http://groups-beta.google.com/group/dom-tooltip
*
* Freshmeat Project: http://freshmeat.net/projects/domtt/?topic_id=92
*
* Updated: 2005/07/16
*
* Supported Browsers:
* Mozilla (Gecko), IE 5.5+, IE on Mac, Safari, Konqueror, Opera 7
*
* Usage:
* Please see the HOWTO documentation.
**/
// }}}
// {{{ settings (editable)
// IE mouse events seem to be off by 2 pixels
var
domTT_offsetX
=
(
domLib_isIE
?
-
2
:
0
);
var
domTT_offsetY
=
(
domLib_isIE
?
4
:
2
);
var
domTT_direction
=
'
southeast
'
;
var
domTT_mouseHeight
=
domLib_isIE
?
13
:
19
;
var
domTT_closeLink
=
'
X
'
;
var
domTT_closeAction
=
'
hide
'
;
var
domTT_activateDelay
=
500
;
var
domTT_maxWidth
=
false
;
var
domTT_styleClass
=
'
domTT
'
;
var
domTT_fade
=
'
neither
'
;
var
domTT_lifetime
=
0
;
var
domTT_grid
=
0
;
var
domTT_trailDelay
=
200
;
var
domTT_useGlobalMousePosition
=
true
;
var
domTT_postponeActivation
=
false
;
var
domTT_tooltipIdPrefix
=
'
[domTT]
'
;
var
domTT_screenEdgeDetection
=
true
;
var
domTT_screenEdgePadding
=
4
;
var
domTT_oneOnly
=
false
;
var
domTT_cloneNodes
=
false
;
var
domTT_detectCollisions
=
true
;
var
domTT_bannedTags
=
[
'
OPTION
'
];
var
domTT_draggable
=
false
;
if
(
typeof
(
domTT_dragEnabled
)
==
'
undefined
'
)
{
domTT_dragEnabled
=
false
;
}
// }}}
// {{{ globals (DO NOT EDIT)
var
domTT_predefined
=
new
domTT_Hash
();
// tooltips are keyed on both the tip id and the owner id,
// since events can originate on either object
var
domTT_tooltips
=
new
domTT_Hash
();
var
domTT_lastOpened
=
0
;
var
domTT_documentLoaded
=
false
;
var
domTT_mousePosition
=
null
;
// }}}
// {{{ document.onmousemove
if
(
domLib_useLibrary
&&
domTT_useGlobalMousePosition
)
{
document
.
onmousemove
=
function
(
in_event
)
{
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
domTT_mousePosition
=
domLib_getEventPosition
(
in_event
);
if
(
domTT_dragEnabled
&&
domTT_dragMouseDown
)
{
domTT_dragUpdate
(
in_event
);
}
};
}
// }}}
// {{{ domTT_activate()
function
domTT_activate
(
in_this
,
in_event
)
{
if
(
!
domLib_useLibrary
||
(
domTT_postponeActivation
&&
!
domTT_documentLoaded
))
{
return
false
;
}
// make sure in_event is set (for IE, some cases we have to use window.event)
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
// don't allow tooltips on banned tags (such as OPTION)
if
(
in_event
!=
null
)
{
var
target
=
in_event
.
srcElement
?
in_event
.
srcElement
:
in_event
.
target
;
if
(
target
!=
null
&&
(
'
,
'
+
domTT_bannedTags
.
join
(
'
,
'
)
+
'
,
'
).
indexOf
(
'
,
'
+
target
.
tagName
+
'
,
'
)
!=
-
1
)
{
return
false
;
}
}
var
owner
=
document
.
body
;
// we have an active event so get the owner
if
(
in_event
!=
null
&&
in_event
.
type
.
match
(
/key|mouse|click|contextmenu/i
))
{
// make sure we have nothing higher than the body element
if
(
in_this
.
nodeType
&&
in_this
.
nodeType
!=
document
.
DOCUMENT_NODE
)
{
owner
=
in_this
;
}
}
// non active event (make sure we were passed a string id)
else
{
if
(
typeof
(
in_this
)
!=
'
object
'
&&
!
(
owner
=
domTT_tooltips
.
get
(
in_this
)))
{
// NOTE: two steps to avoid "flashing" in gecko
var
embryo
=
document
.
createElement
(
'
div
'
);
owner
=
document
.
body
.
appendChild
(
embryo
);
owner
.
style
.
display
=
'
none
'
;
owner
.
id
=
in_this
;
}
}
// make sure the owner has a unique id
if
(
!
owner
.
id
)
{
owner
.
id
=
'
__autoId
'
+
domLib_autoId
++
;
}
// see if we should only be opening one tip at a time
// NOTE: this is not "perfect" yet since it really steps on any other
// tip working on fade out or delayed close, but it get's the job done
if
(
domTT_oneOnly
&&
domTT_lastOpened
)
{
domTT_deactivate
(
domTT_lastOpened
);
}
domTT_lastOpened
=
owner
.
id
;
var
tooltip
=
domTT_tooltips
.
get
(
owner
.
id
);
if
(
tooltip
)
{
if
(
tooltip
.
get
(
'
eventType
'
)
!=
in_event
.
type
)
{
if
(
tooltip
.
get
(
'
type
'
)
==
'
greasy
'
)
{
tooltip
.
set
(
'
closeAction
'
,
'
destroy
'
);
domTT_deactivate
(
owner
.
id
);
}
else
if
(
tooltip
.
get
(
'
status
'
)
!=
'
inactive
'
)
{
return
owner
.
id
;
}
}
else
{
if
(
tooltip
.
get
(
'
status
'
)
==
'
inactive
'
)
{
tooltip
.
set
(
'
status
'
,
'
pending
'
);
tooltip
.
set
(
'
activateTimeout
'
,
domLib_setTimeout
(
domTT_runShow
,
tooltip
.
get
(
'
delay
'
),
[
owner
.
id
,
in_event
]));
return
owner
.
id
;
}
// either pending or active, let it be
else
{
return
owner
.
id
;
}
}
}
// setup the default options hash
var
options
=
new
domTT_Hash
(
'
caption
'
,
''
,
'
content
'
,
''
,
'
clearMouse
'
,
true
,
'
closeAction
'
,
domTT_closeAction
,
'
closeLink
'
,
domTT_closeLink
,
'
delay
'
,
domTT_activateDelay
,
'
direction
'
,
domTT_direction
,
'
draggable
'
,
domTT_draggable
,
'
fade
'
,
domTT_fade
,
'
fadeMax
'
,
100
,
'
grid
'
,
domTT_grid
,
'
id
'
,
domTT_tooltipIdPrefix
+
owner
.
id
,
'
inframe
'
,
false
,
'
lifetime
'
,
domTT_lifetime
,
'
offsetX
'
,
domTT_offsetX
,
'
offsetY
'
,
domTT_offsetY
,
'
parent
'
,
document
.
body
,
'
position
'
,
'
absolute
'
,
'
styleClass
'
,
domTT_styleClass
,
'
type
'
,
'
greasy
'
,
'
trail
'
,
false
,
'
lazy
'
,
false
);
// load in the options from the function call
for
(
var
i
=
2
;
i
<
arguments
.
length
;
i
+=
2
)
{
// load in predefined
if
(
arguments
[
i
]
==
'
predefined
'
)
{
var
predefinedOptions
=
domTT_predefined
.
get
(
arguments
[
i
+
1
]);
for
(
var
j
in
predefinedOptions
.
elementData
)
{
options
.
set
(
j
,
predefinedOptions
.
get
(
j
));
}
}
// set option
else
{
options
.
set
(
arguments
[
i
],
arguments
[
i
+
1
]);
}
}
options
.
set
(
'
eventType
'
,
in_event
!=
null
?
in_event
.
type
:
null
);
// immediately set the status text if provided
if
(
options
.
has
(
'
statusText
'
))
{
try
{
window
.
status
=
options
.
get
(
'
statusText
'
);
}
catch
(
e
)
{}
}
// if we didn't give content...assume we just wanted to change the status and return
if
(
!
options
.
has
(
'
content
'
)
||
options
.
get
(
'
content
'
)
==
''
||
options
.
get
(
'
content
'
)
==
null
)
{
if
(
typeof
(
owner
.
onmouseout
)
!=
'
function
'
)
{
owner
.
onmouseout
=
function
(
in_event
)
{
domTT_mouseout
(
this
,
in_event
);
};
}
return
owner
.
id
;
}
options
.
set
(
'
owner
'
,
owner
);
domTT_create
(
options
);
// determine the show delay
options
.
set
(
'
delay
'
,
(
in_event
!=
null
&&
in_event
.
type
.
match
(
/click|mousedown|contextmenu/i
))
?
0
:
parseInt
(
options
.
get
(
'
delay
'
)));
domTT_tooltips
.
set
(
owner
.
id
,
options
);
domTT_tooltips
.
set
(
options
.
get
(
'
id
'
),
options
);
options
.
set
(
'
status
'
,
'
pending
'
);
options
.
set
(
'
activateTimeout
'
,
domLib_setTimeout
(
domTT_runShow
,
options
.
get
(
'
delay
'
),
[
owner
.
id
,
in_event
]));
return
owner
.
id
;
}
// }}}
// {{{ domTT_create()
function
domTT_create
(
in_options
)
{
var
tipOwner
=
in_options
.
get
(
'
owner
'
);
var
parentObj
=
in_options
.
get
(
'
parent
'
);
var
parentDoc
=
parentObj
.
ownerDocument
||
parentObj
.
document
;
// create the tooltip and hide it
// NOTE: two steps to avoid "flashing" in gecko
var
embryo
=
parentDoc
.
createElement
(
'
div
'
);
var
tipObj
=
parentObj
.
appendChild
(
embryo
);
tipObj
.
style
.
position
=
'
absolute
'
;
tipObj
.
style
.
left
=
'
0px
'
;
tipObj
.
style
.
top
=
'
0px
'
;
tipObj
.
style
.
visibility
=
'
hidden
'
;
tipObj
.
id
=
in_options
.
get
(
'
id
'
);
tipObj
.
className
=
in_options
.
get
(
'
styleClass
'
);
var
contentBlock
;
var
tableLayout
=
false
;
if
(
in_options
.
get
(
'
caption
'
)
||
(
in_options
.
get
(
'
type
'
)
==
'
sticky
'
&&
in_options
.
get
(
'
caption
'
)
!==
false
))
{
tableLayout
=
true
;
// layout the tip with a hidden formatting table
var
tipLayoutTable
=
tipObj
.
appendChild
(
parentDoc
.
createElement
(
'
table
'
));
tipLayoutTable
.
style
.
borderCollapse
=
'
collapse
'
;
if
(
domLib_isKHTML
)
{
tipLayoutTable
.
cellSpacing
=
0
;
}
var
tipLayoutTbody
=
tipLayoutTable
.
appendChild
(
parentDoc
.
createElement
(
'
tbody
'
));
var
numCaptionCells
=
0
;
var
captionRow
=
tipLayoutTbody
.
appendChild
(
parentDoc
.
createElement
(
'
tr
'
));
var
captionCell
=
captionRow
.
appendChild
(
parentDoc
.
createElement
(
'
td
'
));
captionCell
.
style
.
padding
=
'
0px
'
;
var
caption
=
captionCell
.
appendChild
(
parentDoc
.
createElement
(
'
div
'
));
caption
.
className
=
'
caption
'
;
if
(
domLib_isIE50
)
{
caption
.
style
.
height
=
'
100%
'
;
}
if
(
in_options
.
get
(
'
caption
'
).
nodeType
)
{
caption
.
appendChild
(
domTT_cloneNodes
?
in_options
.
get
(
'
caption
'
).
cloneNode
(
1
)
:
in_options
.
get
(
'
caption
'
));
}
else
{
caption
.
innerHTML
=
in_options
.
get
(
'
caption
'
);
}
if
(
in_options
.
get
(
'
type
'
)
==
'
sticky
'
)
{
var
numCaptionCells
=
2
;
var
closeLinkCell
=
captionRow
.
appendChild
(
parentDoc
.
createElement
(
'
td
'
));
closeLinkCell
.
style
.
padding
=
'
0px
'
;
var
closeLink
=
closeLinkCell
.
appendChild
(
parentDoc
.
createElement
(
'
div
'
));
closeLink
.
className
=
'
caption
'
;
if
(
domLib_isIE50
)
{
closeLink
.
style
.
height
=
'
100%
'
;
}
closeLink
.
style
.
textAlign
=
'
right
'
;
closeLink
.
style
.
cursor
=
domLib_stylePointer
;
// merge the styles of the two cells
closeLink
.
style
.
borderLeftWidth
=
caption
.
style
.
borderRightWidth
=
'
0px
'
;
closeLink
.
style
.
paddingLeft
=
caption
.
style
.
paddingRight
=
'
0px
'
;
closeLink
.
style
.
marginLeft
=
caption
.
style
.
marginRight
=
'
0px
'
;
if
(
in_options
.
get
(
'
closeLink
'
).
nodeType
)
{
closeLink
.
appendChild
(
in_options
.
get
(
'
closeLink
'
).
cloneNode
(
1
));
}
else
{
closeLink
.
innerHTML
=
in_options
.
get
(
'
closeLink
'
);
}
closeLink
.
onclick
=
function
()
{
domTT_deactivate
(
tipOwner
.
id
);
};
closeLink
.
onmousedown
=
function
(
in_event
)
{
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
in_event
.
cancelBubble
=
true
;
};
// MacIE has to have a newline at the end and must be made with createTextNode()
if
(
domLib_isMacIE
)
{
closeLinkCell
.
appendChild
(
parentDoc
.
createTextNode
(
"
\n
"
));
}
}
// MacIE has to have a newline at the end and must be made with createTextNode()
if
(
domLib_isMacIE
)
{
captionCell
.
appendChild
(
parentDoc
.
createTextNode
(
"
\n
"
));
}
var
contentRow
=
tipLayoutTbody
.
appendChild
(
parentDoc
.
createElement
(
'
tr
'
));
var
contentCell
=
contentRow
.
appendChild
(
parentDoc
.
createElement
(
'
td
'
));
contentCell
.
style
.
padding
=
'
0px
'
;
if
(
numCaptionCells
)
{
if
(
domLib_isIE
||
domLib_isOpera
)
{
contentCell
.
colSpan
=
numCaptionCells
;
}
else
{
contentCell
.
setAttribute
(
'
colspan
'
,
numCaptionCells
);
}
}
contentBlock
=
contentCell
.
appendChild
(
parentDoc
.
createElement
(
'
div
'
));
if
(
domLib_isIE50
)
{
contentBlock
.
style
.
height
=
'
100%
'
;
}
}
else
{
contentBlock
=
tipObj
.
appendChild
(
parentDoc
.
createElement
(
'
div
'
));
}
contentBlock
.
className
=
'
contents
'
;
var
content
=
in_options
.
get
(
'
content
'
);
// allow content has a function to return the actual content
if
(
typeof
(
content
)
==
'
function
'
)
{
content
=
content
(
in_options
.
get
(
'
id
'
));
}
if
(
content
!=
null
&&
content
.
nodeType
)
{
contentBlock
.
appendChild
(
domTT_cloneNodes
?
content
.
cloneNode
(
1
)
:
content
);
}
else
{
contentBlock
.
innerHTML
=
content
;
}
// adjust the width if specified
if
(
in_options
.
has
(
'
width
'
))
{
tipObj
.
style
.
width
=
parseInt
(
in_options
.
get
(
'
width
'
))
+
'
px
'
;
}
// check if we are overridding the maxWidth
// if the browser supports maxWidth, the global setting will be ignored (assume stylesheet)
var
maxWidth
=
domTT_maxWidth
;
if
(
in_options
.
has
(
'
maxWidth
'
))
{
if
((
maxWidth
=
in_options
.
get
(
'
maxWidth
'
))
===
false
)
{
tipObj
.
style
.
maxWidth
=
domLib_styleNoMaxWidth
;
}
else
{
maxWidth
=
parseInt
(
in_options
.
get
(
'
maxWidth
'
));
tipObj
.
style
.
maxWidth
=
maxWidth
+
'
px
'
;
}
}
// HACK: fix lack of maxWidth in CSS for KHTML and IE
if
(
maxWidth
!==
false
&&
(
domLib_isIE
||
domLib_isKHTML
)
&&
tipObj
.
offsetWidth
>
maxWidth
)
{
tipObj
.
style
.
width
=
maxWidth
+
'
px
'
;
}
in_options
.
set
(
'
offsetWidth
'
,
tipObj
.
offsetWidth
);
in_options
.
set
(
'
offsetHeight
'
,
tipObj
.
offsetHeight
);
// konqueror miscalcuates the width of the containing div when using the layout table based on the
// border size of the containing div
if
(
domLib_isKonq
&&
tableLayout
&&
!
tipObj
.
style
.
width
)
{
var
left
=
document
.
defaultView
.
getComputedStyle
(
tipObj
,
''
).
getPropertyValue
(
'
border-left-width
'
);
var
right
=
document
.
defaultView
.
getComputedStyle
(
tipObj
,
''
).
getPropertyValue
(
'
border-right-width
'
);
left
=
left
.
substring
(
left
.
indexOf
(
'
:
'
)
+
2
,
left
.
indexOf
(
'
;
'
));
right
=
right
.
substring
(
right
.
indexOf
(
'
:
'
)
+
2
,
right
.
indexOf
(
'
;
'
));
var
correction
=
2
*
((
left
?
parseInt
(
left
)
:
0
)
+
(
right
?
parseInt
(
right
)
:
0
));
tipObj
.
style
.
width
=
(
tipObj
.
offsetWidth
-
correction
)
+
'
px
'
;
}
// if a width is not set on an absolutely positioned object, both IE and Opera
// will attempt to wrap when it spills outside of body...we cannot have that
if
(
domLib_isIE
||
domLib_isOpera
)
{
if
(
!
tipObj
.
style
.
width
)
{
// HACK: the correction here is for a border
tipObj
.
style
.
width
=
(
tipObj
.
offsetWidth
-
2
)
+
'
px
'
;
}
// HACK: the correction here is for a border
tipObj
.
style
.
height
=
(
tipObj
.
offsetHeight
-
2
)
+
'
px
'
;
}
// store placement offsets from event position
var
offsetX
,
offsetY
;
// tooltip floats
if
(
in_options
.
get
(
'
position
'
)
==
'
absolute
'
&&
!
(
in_options
.
has
(
'
x
'
)
&&
in_options
.
has
(
'
y
'
)))
{
// determine the offset relative to the pointer
switch
(
in_options
.
get
(
'
direction
'
))
{
case
'
northeast
'
:
offsetX
=
in_options
.
get
(
'
offsetX
'
);
offsetY
=
0
-
tipObj
.
offsetHeight
-
in_options
.
get
(
'
offsetY
'
);
break
;
case
'
northwest
'
:
offsetX
=
0
-
tipObj
.
offsetWidth
-
in_options
.
get
(
'
offsetX
'
);
offsetY
=
0
-
tipObj
.
offsetHeight
-
in_options
.
get
(
'
offsetY
'
);
break
;
case
'
north
'
:
offsetX
=
0
-
parseInt
(
tipObj
.
offsetWidth
/
2
);
offsetY
=
0
-
tipObj
.
offsetHeight
-
in_options
.
get
(
'
offsetY
'
);
break
;
case
'
southwest
'
:
offsetX
=
0
-
tipObj
.
offsetWidth
-
in_options
.
get
(
'
offsetX
'
);
offsetY
=
in_options
.
get
(
'
offsetY
'
);
break
;
case
'
southeast
'
:
offsetX
=
in_options
.
get
(
'
offsetX
'
);
offsetY
=
in_options
.
get
(
'
offsetY
'
);
break
;
case
'
south
'
:
offsetX
=
0
-
parseInt
(
tipObj
.
offsetWidth
/
2
);
offsetY
=
in_options
.
get
(
'
offsetY
'
);
break
;
}
// if we are in an iframe, get the offsets of the iframe in the parent document
if
(
in_options
.
get
(
'
inframe
'
))
{
var
iframeObj
=
domLib_getIFrameReference
(
window
);
if
(
iframeObj
)
{
var
frameOffsets
=
domLib_getOffsets
(
iframeObj
);
offsetX
+=
frameOffsets
.
get
(
'
left
'
);
offsetY
+=
frameOffsets
.
get
(
'
top
'
);
}
}
}
// tooltip is fixed
else
{
offsetX
=
0
;
offsetY
=
0
;
in_options
.
set
(
'
trail
'
,
false
);
}
// set the direction-specific offsetX/Y
in_options
.
set
(
'
offsetX
'
,
offsetX
);
in_options
.
set
(
'
offsetY
'
,
offsetY
);
if
(
in_options
.
get
(
'
clearMouse
'
)
&&
in_options
.
get
(
'
direction
'
).
indexOf
(
'
south
'
)
!=
-
1
)
{
in_options
.
set
(
'
mouseOffset
'
,
domTT_mouseHeight
);
}
else
{
in_options
.
set
(
'
mouseOffset
'
,
0
);
}
if
(
domLib_canFade
&&
typeof
(
Fadomatic
)
==
'
function
'
)
{
if
(
in_options
.
get
(
'
fade
'
)
!=
'
neither
'
)
{
var
fadeHandler
=
new
Fadomatic
(
tipObj
,
10
,
0
,
0
,
in_options
.
get
(
'
fadeMax
'
));
in_options
.
set
(
'
fadeHandler
'
,
fadeHandler
);
}
}
else
{
in_options
.
set
(
'
fade
'
,
'
neither
'
);
}
// setup mouse events
if
(
in_options
.
get
(
'
trail
'
)
&&
typeof
(
tipOwner
.
onmousemove
)
!=
'
function
'
)
{
tipOwner
.
onmousemove
=
function
(
in_event
)
{
domTT_mousemove
(
this
,
in_event
);
};
}
if
(
typeof
(
tipOwner
.
onmouseout
)
!=
'
function
'
)
{
tipOwner
.
onmouseout
=
function
(
in_event
)
{
domTT_mouseout
(
this
,
in_event
);
};
}
if
(
in_options
.
get
(
'
type
'
)
==
'
sticky
'
)
{
if
(
in_options
.
get
(
'
position
'
)
==
'
absolute
'
&&
domTT_dragEnabled
&&
in_options
.
get
(
'
draggable
'
))
{
if
(
domLib_isIE
)
{
captionRow
.
onselectstart
=
function
()
{
return
false
;
};
}
// setup drag
captionRow
.
onmousedown
=
function
(
in_event
)
{
domTT_dragStart
(
tipObj
,
in_event
);
};
captionRow
.
onmousemove
=
function
(
in_event
)
{
domTT_dragUpdate
(
in_event
);
};
captionRow
.
onmouseup
=
function
()
{
domTT_dragStop
();
};
}
}
else
if
(
in_options
.
get
(
'
type
'
)
==
'
velcro
'
)
{
/* can use once we have deactivateDelay
tipObj.onmouseover = function(in_event)
{
if (typeof(in_event) == 'undefined') { in_event = window.event; }
var tooltip = domTT_tooltips.get(tipObj.id);
if (in_options.get('lifetime')) {
domLib_clearTimeout(in_options.get('lifetimeTimeout');
}
};
*/
tipObj
.
onmouseout
=
function
(
in_event
)
{
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
if
(
!
domLib_isDescendantOf
(
in_event
[
domLib_eventTo
],
tipObj
,
domTT_bannedTags
))
{
domTT_deactivate
(
tipOwner
.
id
);
}
};
// NOTE: this might interfere with links in the tip
tipObj
.
onclick
=
function
(
in_event
)
{
domTT_deactivate
(
tipOwner
.
id
);
};
}
if
(
in_options
.
get
(
'
position
'
)
==
'
relative
'
)
{
tipObj
.
style
.
position
=
'
relative
'
;
}
in_options
.
set
(
'
node
'
,
tipObj
);
in_options
.
set
(
'
status
'
,
'
inactive
'
);
}
// }}}
// {{{ domTT_show()
// in_id is either tip id or the owner id
function
domTT_show
(
in_id
,
in_event
)
{
// should always find one since this call would be cancelled if tip was killed
var
tooltip
=
domTT_tooltips
.
get
(
in_id
);
var
status
=
tooltip
.
get
(
'
status
'
);
var
tipObj
=
tooltip
.
get
(
'
node
'
);
if
(
tooltip
.
get
(
'
position
'
)
==
'
absolute
'
)
{
var
mouseX
,
mouseY
;
if
(
tooltip
.
has
(
'
x
'
)
&&
tooltip
.
has
(
'
y
'
))
{
mouseX
=
tooltip
.
get
(
'
x
'
);
mouseY
=
tooltip
.
get
(
'
y
'
);
}
else
if
(
!
domTT_useGlobalMousePosition
||
domTT_mousePosition
==
null
||
status
==
'
active
'
||
tooltip
.
get
(
'
delay
'
)
==
0
)
{
var
eventPosition
=
domLib_getEventPosition
(
in_event
);
var
eventX
=
eventPosition
.
get
(
'
x
'
);
var
eventY
=
eventPosition
.
get
(
'
y
'
);
if
(
tooltip
.
get
(
'
inframe
'
))
{
eventX
-=
eventPosition
.
get
(
'
scrollX
'
);
eventY
-=
eventPosition
.
get
(
'
scrollY
'
);
}
// only move tip along requested trail axis when updating position
if
(
status
==
'
active
'
&&
tooltip
.
get
(
'
trail
'
)
!==
true
)
{
var
trail
=
tooltip
.
get
(
'
trail
'
);
if
(
trail
==
'
x
'
)
{
mouseX
=
eventX
;
mouseY
=
tooltip
.
get
(
'
mouseY
'
);
}
else
if
(
trail
==
'
y
'
)
{
mouseX
=
tooltip
.
get
(
'
mouseX
'
);
mouseY
=
eventY
;
}
}
else
{
mouseX
=
eventX
;
mouseY
=
eventY
;
}
}
else
{
mouseX
=
domTT_mousePosition
.
get
(
'
x
'
);
mouseY
=
domTT_mousePosition
.
get
(
'
y
'
);
if
(
tooltip
.
get
(
'
inframe
'
))
{
mouseX
-=
domTT_mousePosition
.
get
(
'
scrollX
'
);
mouseY
-=
domTT_mousePosition
.
get
(
'
scrollY
'
);
}
}
// we are using a grid for updates
if
(
tooltip
.
get
(
'
grid
'
))
{
// if this is not a mousemove event or it is a mousemove event on an active tip and
// the movement is bigger than the grid
if
(
in_event
.
type
!=
'
mousemove
'
||
(
status
==
'
active
'
&&
(
Math
.
abs
(
tooltip
.
get
(
'
lastX
'
)
-
mouseX
)
>
tooltip
.
get
(
'
grid
'
)
||
Math
.
abs
(
tooltip
.
get
(
'
lastY
'
)
-
mouseY
)
>
tooltip
.
get
(
'
grid
'
))))
{
tooltip
.
set
(
'
lastX
'
,
mouseX
);
tooltip
.
set
(
'
lastY
'
,
mouseY
);
}
// did not satisfy the grid movement requirement
else
{
return
false
;
}
}
// mouseX and mouseY store the last acknowleged mouse position,
// good for trailing on one axis
tooltip
.
set
(
'
mouseX
'
,
mouseX
);
tooltip
.
set
(
'
mouseY
'
,
mouseY
);
var
coordinates
;
if
(
domTT_screenEdgeDetection
)
{
coordinates
=
domTT_correctEdgeBleed
(
tooltip
.
get
(
'
offsetWidth
'
),
tooltip
.
get
(
'
offsetHeight
'
),
mouseX
,
mouseY
,
tooltip
.
get
(
'
offsetX
'
),
tooltip
.
get
(
'
offsetY
'
),
tooltip
.
get
(
'
mouseOffset
'
),
tooltip
.
get
(
'
inframe
'
)
?
window
.
parent
:
window
);
}
else
{
coordinates
=
{
'
x
'
:
mouseX
+
tooltip
.
get
(
'
offsetX
'
),
'
y
'
:
mouseY
+
tooltip
.
get
(
'
offsetY
'
)
+
tooltip
.
get
(
'
mouseOffset
'
)
};
}
// update the position
tipObj
.
style
.
left
=
coordinates
.
x
+
'
px
'
;
tipObj
.
style
.
top
=
coordinates
.
y
+
'
px
'
;
// increase the tip zIndex so it goes over previously shown tips
tipObj
.
style
.
zIndex
=
domLib_zIndex
++
;
}
// if tip is not active, active it now and check for a fade in
if
(
status
==
'
pending
'
)
{
// unhide the tooltip
tooltip
.
set
(
'
status
'
,
'
active
'
);
tipObj
.
style
.
display
=
''
;
tipObj
.
style
.
visibility
=
'
visible
'
;
var
fade
=
tooltip
.
get
(
'
fade
'
);
if
(
fade
!=
'
neither
'
)
{
var
fadeHandler
=
tooltip
.
get
(
'
fadeHandler
'
);
if
(
fade
==
'
out
'
||
fade
==
'
both
'
)
{
fadeHandler
.
haltFade
();
if
(
fade
==
'
out
'
)
{
fadeHandler
.
halt
();
}
}
if
(
fade
==
'
in
'
||
fade
==
'
both
'
)
{
fadeHandler
.
fadeIn
();
}
}
if
(
tooltip
.
get
(
'
type
'
)
==
'
greasy
'
&&
tooltip
.
get
(
'
lifetime
'
)
!=
0
)
{
tooltip
.
set
(
'
lifetimeTimeout
'
,
domLib_setTimeout
(
domTT_runDeactivate
,
tooltip
.
get
(
'
lifetime
'
),
[
tipObj
.
id
]));
}
}
if
(
tooltip
.
get
(
'
position
'
)
==
'
absolute
'
&&
domTT_detectCollisions
)
{
// utilize original collision element cache
domLib_detectCollisions
(
tipObj
,
false
,
true
);
}
}
// }}}
// {{{ domTT_close()
// in_handle can either be an child object of the tip, the tip id or the owner id
function
domTT_close
(
in_handle
)
{
var
id
;
if
(
typeof
(
in_handle
)
==
'
object
'
&&
in_handle
.
nodeType
)
{
var
obj
=
in_handle
;
while
(
!
obj
.
id
||
!
domTT_tooltips
.
get
(
obj
.
id
))
{
obj
=
obj
.
parentNode
;
if
(
obj
.
nodeType
!=
document
.
ELEMENT_NODE
)
{
return
;
}
}
id
=
obj
.
id
;
}
else
{
id
=
in_handle
;
}
domTT_deactivate
(
id
);
}
// }}}
// {{{ domTT_closeAll()
// run through the tooltips and close them all
function
domTT_closeAll
()
{
// NOTE: this will iterate 2x # of tooltips
for
(
var
id
in
domTT_tooltips
.
elementData
)
{
domTT_close
(
id
);
}
}
// }}}
// {{{ domTT_deactivate()
// in_id is either the tip id or the owner id
function
domTT_deactivate
(
in_id
)
{
var
tooltip
=
domTT_tooltips
.
get
(
in_id
);
if
(
tooltip
)
{
var
status
=
tooltip
.
get
(
'
status
'
);
if
(
status
==
'
pending
'
)
{
// cancel the creation of this tip if it is still pending
domLib_clearTimeout
(
tooltip
.
get
(
'
activateTimeout
'
));
tooltip
.
set
(
'
status
'
,
'
inactive
'
);
}
else
if
(
status
==
'
active
'
)
{
if
(
tooltip
.
get
(
'
lifetime
'
))
{
domLib_clearTimeout
(
tooltip
.
get
(
'
lifetimeTimeout
'
));
}
var
tipObj
=
tooltip
.
get
(
'
node
'
);
if
(
tooltip
.
get
(
'
closeAction
'
)
==
'
hide
'
)
{
var
fade
=
tooltip
.
get
(
'
fade
'
);
if
(
fade
!=
'
neither
'
)
{
var
fadeHandler
=
tooltip
.
get
(
'
fadeHandler
'
);
if
(
fade
==
'
out
'
||
fade
==
'
both
'
)
{
fadeHandler
.
fadeOut
();
}
else
{
fadeHandler
.
hide
();
}
}
else
{
tipObj
.
style
.
display
=
'
none
'
;
}
}
else
{
tooltip
.
get
(
'
parent
'
).
removeChild
(
tipObj
);
domTT_tooltips
.
remove
(
tooltip
.
get
(
'
owner
'
).
id
);
domTT_tooltips
.
remove
(
tooltip
.
get
(
'
id
'
));
}
tooltip
.
set
(
'
status
'
,
'
inactive
'
);
if
(
domTT_detectCollisions
)
{
// unhide all of the selects that are owned by this object
// utilize original collision element cache
domLib_detectCollisions
(
tipObj
,
true
,
true
);
}
}
}
}
// }}}
// {{{ domTT_mouseout()
function
domTT_mouseout
(
in_owner
,
in_event
)
{
if
(
!
domLib_useLibrary
)
{
return
false
;
}
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
var
toChild
=
domLib_isDescendantOf
(
in_event
[
domLib_eventTo
],
in_owner
,
domTT_bannedTags
);
var
tooltip
=
domTT_tooltips
.
get
(
in_owner
.
id
);
if
(
tooltip
&&
(
tooltip
.
get
(
'
type
'
)
==
'
greasy
'
||
tooltip
.
get
(
'
status
'
)
!=
'
active
'
))
{
// deactivate tip if exists and we moved away from the owner
if
(
!
toChild
)
{
domTT_deactivate
(
in_owner
.
id
);
try
{
window
.
status
=
window
.
defaultStatus
;
}
catch
(
e
)
{}
}
}
else
if
(
!
toChild
)
{
try
{
window
.
status
=
window
.
defaultStatus
;
}
catch
(
e
)
{}
}
}
// }}}
// {{{ domTT_mousemove()
function
domTT_mousemove
(
in_owner
,
in_event
)
{
if
(
!
domLib_useLibrary
)
{
return
false
;
}
if
(
typeof
(
in_event
)
==
'
undefined
'
)
{
in_event
=
window
.
event
;
}
var
tooltip
=
domTT_tooltips
.
get
(
in_owner
.
id
);
if
(
tooltip
&&
tooltip
.
get
(
'
trail
'
)
&&
tooltip
.
get
(
'
status
'
)
==
'
active
'
)
{
// see if we are trailing lazy
if
(
tooltip
.
get
(
'
lazy
'
))
{
domLib_setTimeout
(
domTT_runShow
,
domTT_trailDelay
,
[
in_owner
.
id
,
in_event
]);
}
else
{
domTT_show
(
in_owner
.
id
,
in_event
);
}
}
}
// }}}
// {{{ domTT_addPredefined()
function
domTT_addPredefined
(
in_id
)
{
var
options
=
new
domTT_Hash
();
for
(
var
i
=
1
;
i
<
arguments
.
length
;
i
+=
2
)
{
options
.
set
(
arguments
[
i
],
arguments
[
i
+
1
]);
}
domTT_predefined
.
set
(
in_id
,
options
);
}
// }}}
// {{{ domTT_correctEdgeBleed()
function
domTT_correctEdgeBleed
(
in_width
,
in_height
,
in_x
,
in_y
,
in_offsetX
,
in_offsetY
,
in_mouseOffset
,
in_window
)
{
var
win
,
doc
;
var
bleedRight
,
bleedBottom
;
var
pageHeight
,
pageWidth
,
pageYOffset
,
pageXOffset
;
var
x
=
in_x
+
in_offsetX
;
var
y
=
in_y
+
in_offsetY
+
in_mouseOffset
;
win
=
(
typeof
(
in_window
)
==
'
undefined
'
?
window
:
in_window
);
// Gecko and IE swaps values of clientHeight, clientWidth properties when
// in standards compliance mode from documentElement to document.body
doc
=
((
domLib_standardsMode
&&
(
domLib_isIE
||
domLib_isGecko
))
?
win
.
document
.
documentElement
:
win
.
document
.
body
);
// for IE in compliance mode
if
(
domLib_isIE
)
{
pageHeight
=
doc
.
clientHeight
;
pageWidth
=
doc
.
clientWidth
;
pageYOffset
=
doc
.
scrollTop
;
pageXOffset
=
doc
.
scrollLeft
;
}
else
{
pageHeight
=
doc
.
clientHeight
;
pageWidth
=
doc
.
clientWidth
;
if
(
domLib_isKHTML
)
{
pageHeight
=
win
.
innerHeight
;
}
pageYOffset
=
win
.
pageYOffset
;
pageXOffset
=
win
.
pageXOffset
;
}
// we are bleeding off the right, move tip over to stay on page
// logic: take x position, add width and subtract from effective page width
if
((
bleedRight
=
(
x
-
pageXOffset
)
+
in_width
-
(
pageWidth
-
domTT_screenEdgePadding
))
>
0
)
{
x
-=
bleedRight
;
}
// we are bleeding to the left, move tip over to stay on page
// if tip doesn't fit, we will go back to bleeding off the right
// logic: take x position and check if less than edge padding
if
((
x
-
pageXOffset
)
<
domTT_screenEdgePadding
)
{
x
=
domTT_screenEdgePadding
+
pageXOffset
;
}
// if we are bleeding off the bottom, flip to north
// logic: take y position, add height and subtract from effective page height
if
((
bleedBottom
=
(
y
-
pageYOffset
)
+
in_height
-
(
pageHeight
-
domTT_screenEdgePadding
))
>
0
)
{
y
=
in_y
-
in_height
-
in_offsetY
;
}
// if we are bleeding off the top, flip to south
// if tip doesn't fit, we will go back to bleeding off the bottom
// logic: take y position and check if less than edge padding
if
((
y
-
pageYOffset
)
<
domTT_screenEdgePadding
)
{
y
=
in_y
+
domTT_mouseHeight
+
in_offsetY
;
}
return
{
'
x
'
:
x
,
'
y
'
:
y
};
}
// }}}
// {{{ domTT_isActive()
// in_id is either the tip id or the owner id
function
domTT_isActive
(
in_id
)
{
var
tooltip
=
domTT_tooltips
.
get
(
in_id
);
if
(
!
tooltip
||
tooltip
.
get
(
'
status
'
)
!=
'
active
'
)
{
return
false
;
}
else
{
return
true
;
}
}
// }}}
// {{{ domTT_runXXX()
// All of these domMenu_runXXX() methods are used by the event handling sections to
// avoid the circular memory leaks caused by inner functions
function
domTT_runDeactivate
(
args
)
{
domTT_deactivate
(
args
[
0
]);
}
function
domTT_runShow
(
args
)
{
domTT_show
(
args
[
0
],
args
[
1
]);
}
// }}}
// {{{ domTT_replaceTitles()
function
domTT_replaceTitles
(
in_decorator
)
{
var
elements
=
domLib_getElementsByClass
(
'
tooltip
'
);
for
(
var
i
=
0
;
i
<
elements
.
length
;
i
++
)
{
if
(
elements
[
i
].
title
)
{
var
content
;
if
(
typeof
(
in_decorator
)
==
'
function
'
)
{
content
=
in_decorator
(
elements
[
i
]);
}
else
{
content
=
elements
[
i
].
title
;
}
content
=
content
.
replace
(
new
RegExp
(
'
\'
'
,
'
g
'
),
'
\\\'
'
);
elements
[
i
].
onmouseover
=
new
Function
(
'
in_event
'
,
"
domTT_activate(this, in_event, 'content', '
"
+
content
+
"
')
"
);
elements
[
i
].
title
=
''
;
}
}
}
// }}}
// {{{ domTT_update()
// Allow authors to update the contents of existing tips using the DOM
// Unfortunately, the tip must already exist, or else no work is done.
// TODO: make getting at content or caption cleaner
function
domTT_update
(
handle
,
content
,
type
)
{
// type defaults to 'content', can also be 'caption'
if
(
typeof
(
type
)
==
'
undefined
'
)
{
type
=
'
content
'
;
}
var
tip
=
domTT_tooltips
.
get
(
handle
);
if
(
!
tip
)
{
return
;
}
var
tipObj
=
tip
.
get
(
'
node
'
);
var
updateNode
;
if
(
type
==
'
content
'
)
{
// <div class="contents">...
updateNode
=
tipObj
.
firstChild
;
if
(
updateNode
.
className
!=
'
contents
'
)
{
// <table><tbody><tr>...</tr><tr><td><div class="contents">...
updateNode
=
updateNode
.
firstChild
.
firstChild
.
nextSibling
.
firstChild
.
firstChild
;
}
}
else
{
updateNode
=
tipObj
.
firstChild
;
if
(
updateNode
.
className
==
'
contents
'
)
{
// missing caption
return
;
}
// <table><tbody><tr><td><div class="caption">...
updateNode
=
updateNode
.
firstChild
.
firstChild
.
firstChild
.
firstChild
;
}
// TODO: allow for a DOM node as content
updateNode
.
innerHTML
=
content
;
}
// }}}
src/www/javascript/domTT/fadomatic.js
deleted
100644 → 0
View file @
cdb17e69
/** $Id$ */
// Title: Fadomatic
// Version: 1.2
// Homepage: http://chimpen.com/fadomatic
// Author: Philip McCarthy <fadomatic@chimpen.com>
// Fade interval in milliseconds
// Make this larger if you experience performance issues
Fadomatic
.
INTERVAL_MILLIS
=
50
;
// Creates a fader
// element - The element to fade
// speed - The speed to fade at, from 0.0 to 100.0
// initialOpacity (optional, default 100) - element's starting opacity, 0 to 100
// minOpacity (optional, default 0) - element's minimum opacity, 0 to 100
// maxOpacity (optional, default 0) - element's minimum opacity, 0 to 100
function
Fadomatic
(
element
,
rate
,
initialOpacity
,
minOpacity
,
maxOpacity
)
{
this
.
_element
=
element
;
this
.
_intervalId
=
null
;
this
.
_rate
=
rate
;
this
.
_isFadeOut
=
true
;
// Set initial opacity and bounds
// NB use 99 instead of 100 to avoid flicker at start of fade
this
.
_minOpacity
=
0
;
this
.
_maxOpacity
=
99
;
this
.
_opacity
=
99
;
if
(
typeof
minOpacity
!=
'
undefined
'
)
{
if
(
minOpacity
<
0
)
{
this
.
_minOpacity
=
0
;
}
else
if
(
minOpacity
>
99
)
{
this
.
_minOpacity
=
99
;
}
else
{
this
.
_minOpacity
=
minOpacity
;
}
}
if
(
typeof
maxOpacity
!=
'
undefined
'
)
{
if
(
maxOpacity
<
0
)
{
this
.
_maxOpacity
=
0
;
}
else
if
(
maxOpacity
>
99
)
{
this
.
_maxOpacity
=
99
;
}
else
{
this
.
_maxOpacity
=
maxOpacity
;
}
if
(
this
.
_maxOpacity
<
this
.
_minOpacity
)
{
this
.
_maxOpacity
=
this
.
_minOpacity
;
}
}
if
(
typeof
initialOpacity
!=
'
undefined
'
)
{
if
(
initialOpacity
>
this
.
_maxOpacity
)
{
this
.
_opacity
=
this
.
_maxOpacity
;
}
else
if
(
initialOpacity
<
this
.
_minOpacity
)
{
this
.
_opacity
=
this
.
_minOpacity
;
}
else
{
this
.
_opacity
=
initialOpacity
;
}
}
// See if we're using W3C opacity, MSIE filter, or just
// toggling visiblity
if
(
typeof
element
.
style
.
opacity
!=
'
undefined
'
)
{
this
.
_updateOpacity
=
this
.
_updateOpacityW3c
;
}
else
if
(
typeof
element
.
style
.
filter
!=
'
undefined
'
)
{
// If there's not an alpha filter on the element already,
// add one
if
(
element
.
style
.
filter
.
indexOf
(
"
alpha
"
)
==
-
1
)
{
// Attempt to preserve existing filters
var
existingFilters
=
""
;
if
(
element
.
style
.
filter
)
{
existingFilters
=
element
.
style
.
filter
+
"
"
;
}
element
.
style
.
filter
=
existingFilters
+
"
alpha(opacity=
"
+
this
.
_opacity
+
"
)
"
;
}
this
.
_updateOpacity
=
this
.
_updateOpacityMSIE
;
}
else
{
this
.
_updateOpacity
=
this
.
_updateVisibility
;
}
this
.
_updateOpacity
();
}
// Initiates a fade out
Fadomatic
.
prototype
.
fadeOut
=
function
()
{
this
.
_isFadeOut
=
true
;
this
.
_beginFade
();
};
// Initiates a fade in
Fadomatic
.
prototype
.
fadeIn
=
function
()
{
this
.
_isFadeOut
=
false
;
this
.
_beginFade
();
};
// Makes the element completely opaque, stops any fade in progress
Fadomatic
.
prototype
.
show
=
function
()
{
this
.
haltFade
();
this
.
_opacity
=
this
.
_maxOpacity
;
this
.
_updateOpacity
();
};
// Makes the element completely transparent, stops any fade in progress
Fadomatic
.
prototype
.
hide
=
function
()
{
this
.
haltFade
();
this
.
_opacity
=
0
;
this
.
_updateOpacity
();
};
// Halts any fade in progress
Fadomatic
.
prototype
.
haltFade
=
function
()
{
clearInterval
(
this
.
_intervalId
);
};
// Resumes a fade where it was halted
Fadomatic
.
prototype
.
resumeFade
=
function
()
{
this
.
_beginFade
();
};
// Pseudo-private members
Fadomatic
.
prototype
.
_beginFade
=
function
()
{
this
.
haltFade
();
var
objref
=
this
;
this
.
_intervalId
=
setInterval
(
function
()
{
objref
.
_tickFade
();
},
Fadomatic
.
INTERVAL_MILLIS
);
};
Fadomatic
.
prototype
.
_tickFade
=
function
()
{
if
(
this
.
_isFadeOut
)
{
this
.
_opacity
-=
this
.
_rate
;
if
(
this
.
_opacity
<
this
.
_minOpacity
)
{
this
.
_opacity
=
this
.
_minOpacity
;
this
.
haltFade
();
}
}
else
{
this
.
_opacity
+=
this
.
_rate
;
if
(
this
.
_opacity
>
this
.
_maxOpacity
)
{
this
.
_opacity
=
this
.
_maxOpacity
;
this
.
haltFade
();
}
}
this
.
_updateOpacity
();
};
Fadomatic
.
prototype
.
_updateVisibility
=
function
()
{
if
(
this
.
_opacity
>
0
)
{
this
.
_element
.
style
.
visibility
=
'
visible
'
;
}
else
{
this
.
_element
.
style
.
visibility
=
'
hidden
'
;
}
};
Fadomatic
.
prototype
.
_updateOpacityW3c
=
function
()
{
this
.
_element
.
style
.
opacity
=
this
.
_opacity
/
100
;
this
.
_updateVisibility
();
};
Fadomatic
.
prototype
.
_updateOpacityMSIE
=
function
()
{
this
.
_element
.
filters
.
alpha
.
opacity
=
this
.
_opacity
;
this
.
_updateVisibility
();
};
Fadomatic
.
prototype
.
_updateOpacity
=
null
;
src/www/javascript/row_helper_dynamic.js
deleted
100644 → 0
View file @
cdb17e69
// Global Variables
var
rowname
=
new
Array
(
99
);
var
rowtype
=
new
Array
(
99
);
var
newrow
=
new
Array
(
99
);
var
rowsize
=
new
Array
(
99
);
// Global variables. Set to javascript code
// that will be eval() after change, add & delete.
var
rowhelper_onChange
=
''
;
var
rowhelper_onAdd
=
''
;
var
rowhelper_onDelete
=
''
;
for
(
i
=
0
;
i
<
99
;
i
++
)
{
rowname
[
i
]
=
''
;
rowtype
[
i
]
=
''
;
newrow
[
i
]
=
''
;
rowsize
[
i
]
=
'
25
'
;
}
var
field_counter_js
=
0
;
var
loaded
=
0
;
var
is_streaming_progress_bar
=
0
;
var
temp_streaming_text
=
""
;
var
addRowTo
=
(
function
()
{
return
(
function
(
tableId
,
objectSize
)
{
var
$
=
jQuery
;
var
d
,
tbody
,
tr
,
td
,
bgc
,
i
,
ii
,
j
,
size
,
className
;
d
=
document
;
tbody
=
d
.
getElementById
(
tableId
).
getElementsByTagName
(
"
tbody
"
).
item
(
0
);
tr
=
d
.
createElement
(
"
tr
"
);
totalrows
++
;
size
=
objectSize
;
for
(
i
=
0
;
i
<
field_counter_js
;
i
++
)
{
if
(
!
objectSize
)
size
=
rowsize
[
i
];
td
=
d
.
createElement
(
"
td
"
);
if
(
typeof
(
rowtype
[
i
])
==
'
function
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' />
"
+
rowtype
[
i
](
rowname
[
i
],
size
,
totalrows
)
+
"
"
;
}
else
if
(
rowtype
[
i
]
==
'
textbox
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><input
"
+
rowhelper_onChange
+
"
size='
"
+
rowsize
[
i
]
+
"
' name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
' />
"
;
}
else
if
(
rowtype
[
i
]
==
'
textbox,ipv4v6
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><input
"
+
rowhelper_onChange
+
"
size='
"
+
rowsize
[
i
]
+
"
' name='
"
+
rowname
[
i
]
+
totalrows
+
"
' class='ipv4v6' id='
"
+
rowname
[
i
]
+
totalrows
+
"
' />
"
;
}
else
if
(
rowtype
[
i
]
==
'
select
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><select
"
+
rowhelper_onChange
+
"
name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
'>
"
+
newrow
[
i
]
+
"
</select>
"
;
}
else
if
(
rowtype
[
i
]
==
'
select,ipv4v6
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><select
"
+
rowhelper_onChange
+
"
name='
"
+
rowname
[
i
]
+
totalrows
+
"
' class='ipv4v6' id='
"
+
rowname
[
i
]
+
totalrows
+
"
'>
"
+
newrow
[
i
]
+
"
</select>
"
;
}
else
if
(
rowtype
[
i
]
==
'
interfaces_selection
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><select
"
+
rowhelper_onChange
+
"
name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
'>
"
+
newrow
[
i
]
+
"
</select>
"
;
}
else
if
(
rowtype
[
i
]
==
'
select_source
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><select
"
+
rowhelper_onChange
+
"
name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
'>
"
+
newrow
[
i
]
+
"
</select>
"
;
}
else
if
(
rowtype
[
i
]
==
'
checkbox
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><input
"
+
rowhelper_onChange
+
"
type='checkbox'name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
' />
"
;
}
else
if
(
rowtype
[
i
]
==
'
input
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><input
"
+
rowhelper_onChange
+
"
class='formfld unknown' size='
"
+
size
+
"
' name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
' />
"
;
}
else
if
(
rowtype
[
i
]
==
'
password
'
)
{
td
.
innerHTML
=
"
<input type='hidden' value='
"
+
totalrows
+
"
' name='
"
+
rowname
[
i
]
+
"
_row-
"
+
totalrows
+
"
' /><input
"
+
rowhelper_onChange
+
"
class='formfld pwd' type='password' name='
"
+
rowname
[
i
]
+
totalrows
+
"
' id='
"
+
rowname
[
i
]
+
totalrows
+
"
' />
"
;
}
tr
.
appendChild
(
td
);
}
td
=
d
.
createElement
(
"
td
"
);
td
.
rowSpan
=
"
1
"
;
td
.
innerHTML
=
'
<a onclick="removeRow(this); return false;" href="#"><span class="fa fa-trash"></span></a>
'
;
tr
.
appendChild
(
td
);
tbody
.
appendChild
(
tr
);
if
(
rowhelper_onAdd
!=
''
)
eval
(
rowhelper_onAdd
);
if
(
$
(
tr
).
ipv4v6ify
)
$
(
tr
).
ipv4v6ify
();
});
})();
function
removeRow
(
el
)
{
var
cel
;
while
(
el
&&
el
.
nodeName
.
toLowerCase
()
!=
"
tr
"
)
el
=
el
.
parentNode
;
if
(
el
&&
el
.
parentNode
)
{
cel
=
el
.
getElementsByTagName
(
"
td
"
).
item
(
0
);
el
.
parentNode
.
removeChild
(
el
);
}
if
(
rowhelper_onDelete
!=
''
)
eval
(
rowhelper_onDelete
);
}
function
find_unique_field_name
(
field_name
)
{
// loop through field_name and strip off -NUMBER
var
last_found_dash
=
0
;
for
(
var
i
=
0
;
i
<
field_name
.
length
;
i
++
)
{
// is this a dash, if so, update
// last_found_dash
if
(
field_name
.
substr
(
i
,
1
)
==
"
-
"
)
last_found_dash
=
i
;
}
if
(
last_found_dash
<
1
)
return
field_name
;
return
(
field_name
.
substr
(
0
,
last_found_dash
));
}
src/www/javascript/suggestions.js
deleted
100644 → 0
View file @
cdb17e69
/**
* Provides suggestions for state names (USA).
* @class
* @scope public
*/
function
StateSuggestions
(
text
)
{
this
.
states
=
text
;
}
/**
* Request suggestions for the given autosuggest control.
* @scope protected
* @param oAutoSuggestControl The autosuggest control to provide suggestions for.
*/
StateSuggestions
.
prototype
.
requestSuggestions
=
function
(
oAutoSuggestControl
/*:AutoSuggestControl*/
,
bTypeAhead
/*:boolean*/
)
{
var
aSuggestions
=
[];
var
sTextboxValue
=
oAutoSuggestControl
.
textbox
.
value
;
if
(
sTextboxValue
.
length
>
0
){
//search for matching states
for
(
var
i
=
0
;
i
<
this
.
states
.
length
;
i
++
)
{
if
(
this
.
states
[
i
].
toLowerCase
().
indexOf
(
sTextboxValue
.
toLowerCase
())
==
0
)
{
aSuggestions
.
push
(
this
.
states
[
i
]);
}
}
}
//provide suggestions to the control
oAutoSuggestControl
.
autosuggest
(
aSuggestions
,
bTypeAhead
);
};
src/www/services_upnp.php
View file @
e082aadc
<?php
/*
Copyright (C) 2014-201
5
Deciso B.V.
Copyright (C) 2014-201
6
Deciso B.V.
Copyright (C) 2004-2012 Scott Ullrich <sullrich@gmail.com>
All rights reserved.
...
...
@@ -27,524 +27,345 @@
POSSIBILITY OF SUCH DAMAGE.
*/
ini_set
(
'max_execution_time'
,
'0'
);
$service_hook
=
'miniupnpd'
;
require_once
(
"guiconfig.inc"
);
require_once
(
"services.inc"
);
require_once
(
"interfaces.inc"
);
require_once
(
"services.inc"
);
require_once
(
"system.inc"
);
function
upnp_validate_ip
(
$ip
,
$check_cdir
)
{
function
upnp_validate_ip
(
$ip
)
{
/* validate cidr */
$ip_array
=
array
();
if
(
$check_cdir
)
{
$ip_array
=
explode
(
'/'
,
$ip
);
if
(
count
(
$ip_array
)
==
2
)
{
if
(
$ip_array
[
1
]
<
1
||
$ip_array
[
1
]
>
32
)
if
(
count
(
$ip_array
)
==
2
)
{
if
(
$ip_array
[
1
]
<
1
||
$ip_array
[
1
]
>
32
)
{
return
false
;
}
else
if
(
count
(
$ip_array
)
!=
1
)
}
}
elseif
(
count
(
$ip_array
)
!=
1
)
{
return
false
;
}
else
$ip_array
[]
=
$ip
;
}
/* validate ip */
if
(
!
is_ipaddr
(
$ip_array
[
0
]))
if
(
!
is_ipaddr
(
$ip_array
[
0
]))
{
return
false
;
}
return
true
;
}
function
upnp_validate_port
(
$port
)
{
foreach
(
explode
(
'-'
,
$port
)
as
$sub
)
if
(
$sub
<
0
||
$sub
>
65535
)
foreach
(
explode
(
'-'
,
$port
)
as
$sub
)
{
if
(
$sub
<
0
||
$sub
>
65535
||
!
is_numeric
(
$sub
))
{
return
false
;
}
}
return
true
;
}
function
validate_form_miniupnpd
(
$post
,
&
$input_errors
)
{
if
(
!
empty
(
$post
[
'enable'
])
&&
(
empty
(
$post
[
'enable_upnp'
])
&&
empty
(
$post
[
'enable_natpmp'
])))
if
(
$_SERVER
[
'REQUEST_METHOD'
]
===
'GET'
)
{
$pconfig
=
array
();
$copy_fields
=
array
(
'enable'
,
'enable_upnp'
,
'enable_natpmp'
,
'ext_iface'
,
'iface_array'
,
'download'
,
'upload'
,
'overridewanip'
,
'logpackets'
,
'sysuptime'
,
'permdefault'
,
'permuser1'
,
'permuser2'
,
'permuser3'
,
'permuser4'
);
foreach
(
$copy_fields
as
$fieldname
)
{
if
(
isset
(
$config
[
'installedpackages'
][
'miniupnpd'
][
'config'
][
0
][
$fieldname
]))
{
$pconfig
[
$fieldname
]
=
$config
[
'installedpackages'
][
'miniupnpd'
][
'config'
][
0
][
$fieldname
];
}
}
// parse array
$pconfig
[
'iface_array'
]
=
explode
(
','
,
$pconfig
[
'iface_array'
]);
}
elseif
(
$_SERVER
[
'REQUEST_METHOD'
]
===
'POST'
)
{
$input_errors
=
array
();
$pconfig
=
$_POST
;
// validate form data
if
(
!
empty
(
$pconfig
[
'enable'
])
&&
(
empty
(
$pconfig
[
'enable_upnp'
])
&&
empty
(
$pconfig
[
'enable_natpmp'
])))
{
$input_errors
[]
=
gettext
(
'At least one of \'UPnP\' or \'NAT-PMP\' must be allowed'
);
if
(
$post
[
'iface_array'
])
foreach
(
$post
[
'iface_array'
]
as
$iface
)
{
if
(
$iface
==
'wan'
)
}
foreach
(
$pconfig
[
'iface_array'
]
as
$iface
)
{
if
(
$iface
==
'wan'
)
{
$input_errors
[]
=
gettext
(
'It is a security risk to specify WAN in the \'Interface\' field'
);
elseif
(
$iface
==
$post
[
'ext_iface'
])
}
elseif
(
$iface
==
$pconfig
[
'ext_iface'
])
{
$input_errors
[]
=
gettext
(
'You cannot select the external interface as an internal interface.'
);
}
if
(
!
empty
(
$post
[
'overridewanip'
])
&&
!
upnp_validate_ip
(
$post
[
'overridewanip'
],
false
))
}
if
(
!
empty
(
$pconfig
[
'overridewanip'
])
&&
!
is_ipaddr
(
$pconfig
[
'overridewanip'
]))
{
$input_errors
[]
=
gettext
(
'You must specify a valid ip address in the \'Override WAN address\' field'
);
if
((
!
empty
(
$post
[
'download'
])
&&
empty
(
$post
[
'upload'
]))
||
(
!
empty
(
$post
[
'upload'
])
&&
empty
(
$post
[
'download'
])))
}
if
((
!
empty
(
$pconfig
[
'download'
])
&&
empty
(
$pconfig
[
'upload'
]))
||
(
!
empty
(
$pconfig
[
'upload'
])
&&
empty
(
$pconfig
[
'download'
])))
{
$input_errors
[]
=
gettext
(
'You must fill in both \'Maximum Download Speed\' and \'Maximum Upload Speed\' fields'
);
if
(
!
empty
(
$post
[
'download'
])
&&
$post
[
'download'
]
<=
0
)
}
if
(
!
empty
(
$pconfig
[
'download'
])
&&
(
$pconfig
[
'download'
]
<=
0
||
!
is_numeric
(
$pconfig
[
'download'
])))
{
$input_errors
[]
=
gettext
(
'You must specify a value greater than 0 in the \'Maximum Download Speed\' field'
);
if
(
!
empty
(
$post
[
'upload'
])
&&
$post
[
'upload'
]
<=
0
)
}
if
(
!
empty
(
$pconfig
[
'upload'
])
&&
(
$pconfig
[
'upload'
]
<=
0
||
!
is_numeric
(
$pconfig
[
'upload'
])))
{
$input_errors
[]
=
gettext
(
'You must specify a value greater than 0 in the \'Maximum Upload Speed\' field'
);
}
/* user permissions validation */
for
(
$i
=
1
;
$i
<=
4
;
$i
++
)
{
if
(
!
empty
(
$post
[
"permuser
{
$i
}
"
]))
{
$perm
=
explode
(
' '
,
$post
[
"permuser
{
$i
}
"
]);
if
(
!
empty
(
$pconfig
[
"permuser
{
$i
}
"
]))
{
$perm
=
explode
(
' '
,
$pconfig
[
"permuser
{
$i
}
"
]);
/* should explode to 4 args */
if
(
count
(
$perm
)
!=
4
)
{
if
(
count
(
$perm
)
!=
4
)
{
$input_errors
[]
=
sprintf
(
gettext
(
"You must follow the specified format in the 'User specified permissions %s' field"
),
$i
);
}
else
{
/* must with allow or deny */
if
(
!
(
$perm
[
0
]
==
'allow'
||
$perm
[
0
]
==
'deny'
))
if
(
!
(
$perm
[
0
]
==
'allow'
||
$perm
[
0
]
==
'deny'
))
{
$input_errors
[]
=
sprintf
(
gettext
(
"You must begin with allow or deny in the 'User specified permissions %s' field"
),
$i
);
}
/* verify port or port range */
if
(
!
upnp_validate_port
(
$perm
[
1
])
||
!
upnp_validate_port
(
$perm
[
3
]))
if
(
!
upnp_validate_port
(
$perm
[
1
])
||
!
upnp_validate_port
(
$perm
[
3
]))
{
$input_errors
[]
=
sprintf
(
gettext
(
"You must specify a port or port range between 0 and 65535 in the 'User specified permissions %s' field"
),
$i
);
}
/* verify ip address */
if
(
!
upnp_validate_ip
(
$perm
[
2
],
true
))
if
(
!
upnp_validate_ip
(
$perm
[
2
]))
{
$input_errors
[]
=
sprintf
(
gettext
(
"You must specify a valid ip address in the 'User specified permissions %s' field"
),
$i
);
}
}
}
}
/* return a fieldname that is safe for xml usage */
function
xml_safe_fieldname
(
$fieldname
)
{
$replace
=
array
(
'/'
,
'-'
,
' '
,
'!'
,
'@'
,
'#'
,
'$'
,
'%'
,
'^'
,
'&'
,
'*'
,
'('
,
')'
,
'_'
,
'+'
,
'='
,
'{'
,
'}'
,
'['
,
']'
,
'|'
,
'/'
,
'<'
,
'>'
,
'?'
,
':'
,
','
,
'.'
,
'\''
,
'\\'
);
return
strtolower
(
str_replace
(
$replace
,
""
,
$fieldname
));
}
function
get_pkg_interfaces_select_source
(
$include_localhost
=
false
)
{
$interfaces
=
get_configured_interface_with_descr
();
$ssifs
=
array
();
foreach
(
$interfaces
as
$iface
=>
$ifacename
)
{
$tmp
[
"name"
]
=
$ifacename
;
$tmp
[
"value"
]
=
$iface
;
$ssifs
[]
=
$tmp
;
}
if
(
$include_localhost
)
{
$tmp
[
"name"
]
=
"Localhost"
;
$tmp
[
"value"
]
=
"lo0"
;
$ssifs
[]
=
$tmp
;
}
return
$ssifs
;
}
global
$listtags
;
$listtags
=
array_flip
(
array
(
'build_port_path'
,
'onetoone'
,
'queue'
,
'rule'
,
'servernat'
,
'alias'
,
'additional_files_needed'
,
'tab'
,
'menu'
,
'rowhelperfield'
,
'service'
,
'step'
,
'package'
,
'columnitem'
,
'option'
,
'item'
,
'field'
,
'package'
,
'file'
));
$pkg
=
parse_xml_config_raw
(
'/usr/local/pkg/miniupnpd.xml'
,
'packagegui'
,
false
);
if
(
$config
[
'installedpackages'
]
&&
!
is_array
(
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
]))
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
]
=
array
();
if
(
$config
[
'installedpackages'
]
&&
(
count
(
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
])
>
0
)
&&
(
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
][
0
]
==
""
))
array_shift
(
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
]);
$a_pkg
=
&
$config
[
'installedpackages'
][
xml_safe_fieldname
(
$pkg
[
'name'
])][
'config'
];
global
$config
;
if
(
$_POST
)
{
$firstfield
=
''
;
$rows
=
0
;
$input_errors
=
array
();
$reqfields
=
array
();
$reqfieldsn
=
array
();
foreach
(
$pkg
[
'fields'
][
'field'
]
as
$field
)
{
if
((
$field
[
'type'
]
==
'input'
)
&&
isset
(
$field
[
'required'
]))
{
if
(
$field
[
'fieldname'
])
{
$reqfields
[]
=
$field
[
'fieldname'
];
}
if
(
$field
[
'fielddescr'
])
{
$reqfieldsn
[]
=
$field
[
'fielddescr'
];
}
}
}
do_input_validation
(
$_POST
,
$reqfields
,
$reqfieldsn
,
$input_errors
);
validate_form_miniupnpd
(
$_POST
,
$input_errors
);
if
(
!
$input_errors
)
{
$pkgarr
=
array
();
foreach
(
$pkg
[
'fields'
][
'field'
]
as
$fields
)
{
$fieldvalue
=
null
;
$fieldname
=
null
;
if
(
isset
(
$fields
[
'fieldname'
]))
{
$fieldname
=
$fields
[
'fieldname'
];
}
if
(
$fieldname
==
'interface_array'
)
{
$fieldvalue
=
$_POST
[
$fieldname
];
}
elseif
(
isset
(
$_POST
[
$fieldname
])
&&
is_array
(
$_POST
[
$fieldname
]))
{
$fieldvalue
=
implode
(
','
,
$_POST
[
$fieldname
]);
}
else
{
if
(
isset
(
$_POST
[
$fieldname
]))
{
$fieldvalue
=
trim
(
$_POST
[
$fieldname
]);
if
(
count
(
$input_errors
)
==
0
)
{
// save form data
$upnp
=
array
();
// boolean types
foreach
(
array
(
'enable'
,
'enable_upnp'
,
'enable_natpmp'
,
'logpackets'
,
'sysuptime'
,
'permdefault'
)
as
$fieldname
)
{
$upnp
[
$fieldname
]
=
!
empty
(
$pconfig
[
$fieldname
]);
}
// text field types
foreach
(
array
(
'ext_iface'
,
'download'
,
'upload'
,
'overridewanip'
,
'permuser1'
,
'permuser2'
,
'permuser3'
,
'permuser4'
)
as
$fieldname
)
{
$upnp
[
$fieldname
]
=
$pconfig
[
$fieldname
];
}
if
(
$fieldname
)
{
$pkgarr
[
$fieldname
]
=
$fieldvalue
;
}
}
if
(
count
(
$a_pkg
))
{
/* we are going to overwrite anyway */
$a_pkg
=
array
();
}
$a_pkg
[]
=
$pkgarr
;
// array types
$upnp
[
'iface_array'
]
=
implode
(
','
,
$pconfig
[
'iface_array'
]);
// sync to config
$config
[
'installedpackages'
][
'miniupnpd'
][
'config'
]
=
$upnp
;
write_config
(
gettext
(
'Modified Universal Plug and Play settings.'
));
sync_package_miniupnpd
();
}
else
{
$get_from_post
=
true
;
header
(
"Location: services_upnp.php"
);
exit
;
}
}
include
(
"head.inc"
);
$service_hook
=
'miniupnpd'
;
legacy_html_escape_form_data
(
$pconfig
);
include
(
"head.inc"
);
?>
<body>
<?php
include
(
"fbegin.inc"
);
?>
<script
type=
"text/javascript"
src=
"/javascript/autosuggest.js"
></script>
<script
type=
"text/javascript"
src=
"/javascript/suggestions.js"
></script>
<?php
if
(
$pkg
[
'fields'
][
'field'
]
<>
""
)
{
?>
<script
type=
"text/javascript"
>
//
<!
[
CDATA
[
//Everything inside it will load as soon as the DOM is loaded and before the page contents are loaded
jQuery
(
document
).
ready
(
function
()
{
//Sortable function
jQuery
(
'
#mainarea table tbody
'
).
sortable
({
items
:
'
tr.sortable
'
,
cursor
:
'
move
'
,
distance
:
10
,
opacity
:
0.8
,
helper
:
function
(
e
,
ui
){
ui
.
children
().
each
(
function
(){
jQuery
(
this
).
width
(
jQuery
(
this
).
width
());
});
return
ui
;
},
});
//delete current line jQuery function
jQuery
(
'
#maintable td .delete
'
).
live
(
'
click
'
,
function
()
{
//do not remove first line
if
(
jQuery
(
"
#maintable tr
"
).
length
>
2
){
jQuery
(
this
).
parent
().
parent
().
remove
();
return
false
;
}
});
//add new line jQuery function
jQuery
(
'
#mainarea table .add
'
).
click
(
function
()
{
//get table size and assign as new id
var
c_id
=
jQuery
(
"
#maintable tr
"
).
length
;
var
new_row
=
jQuery
(
"
table#maintable tr:last
"
).
html
().
replace
(
/
(
name|id
)
="
(\w
+
)(\d
+
)
"/g
,
"
$1='$2
"
+
c_id
+
"
'
"
);
//apply new id to created line rowhelperid
jQuery
(
"
table#maintable tr:last
"
).
after
(
"
<tr>
"
+
new_row
+
"
<
\
/tr>
"
);
return
false
;
});
// Call enablechange function
enablechange
();
});
function
enablechange
()
{
<?php
foreach
(
$pkg
[
'fields'
][
'field'
]
as
$field
)
{
if
(
isset
(
$field
[
'enablefields'
])
or
isset
(
$field
[
'checkenablefields'
]))
{
if
(
isset
(
$field
[
'fieldname'
]))
{
$fieldname
=
$field
[
'fieldname'
];
}
else
{
$fieldname
=
""
;
}
echo
"
\t
if (jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$fieldname
}
\"
]').prop('checked') == false) {\n"
;
if
(
isset
(
$field
[
'enablefields'
]))
{
foreach
(
explode
(
','
,
$field
[
'enablefields'
])
as
$enablefield
)
{
echo
"
\t\t
if (jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$enablefield
}
\"
]').length > 0) {\n"
;
echo
"
\t\t\t
jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$enablefield
}
\"
]').prop('disabled',true);
\n
"
;
echo
"
\t\t
}
\n
"
;
}
}
if
(
isset
(
$field
[
'checkenablefields'
]))
{
foreach
(
explode
(
','
,
$field
[
'checkenablefields'
])
as
$checkenablefield
)
{
echo
"
\t\t
if (jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$checkenablefield
}
\"
]').length > 0) {\n"
;
echo
"
\t\t\t
jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$checkenablefield
}
\"
]').prop('checked',true);
\n
"
;
echo
"
\t\t
}
\n
"
;
}
}
echo
"
\t
}
\n\t
else {\n"
;
if
(
isset
(
$field
[
'enablefields'
]))
{
foreach
(
explode
(
','
,
$field
[
'enablefields'
])
as
$enablefield
)
{
echo
"
\t\t
if (jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$enablefield
}
\"
]').length > 0) {\n"
;
echo
"
\t\t\t
jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$enablefield
}
\"
]').prop('disabled',false);
\n
"
;
echo
"
\t\t
}
\n
"
;
}
}
if
(
isset
(
$field
[
'checkenablefields'
]))
{
foreach
(
explode
(
','
,
$field
[
'checkenablefields'
])
as
$checkenablefield
)
{
echo
"
\t\t
if (jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$checkenablefield
}
\"
]').length > 0) {\n"
;
echo
"
\t\t\t
jQuery('form[name=
\"
iform
\"
] input[name=
\"
{
$checkenablefield
}
\"
]').prop('checked',false);
\n
"
;
echo
"
\t\t
}
\n
"
;
}
}
echo
"
\t
}
\n
"
;
}
}
?>
}
//]]>
</script>
<?php
}
?>
<script
type=
"text/javascript"
src=
"javascript/domTT/domLib.js"
></script>
<script
type=
"text/javascript"
src=
"javascript/domTT/domTT.js"
></script>
<script
type=
"text/javascript"
src=
"javascript/domTT/behaviour.js"
></script>
<script
type=
"text/javascript"
src=
"javascript/domTT/fadomatic.js"
></script>
<script
type=
"text/javascript"
src=
"/javascript/row_helper_dynamic.js"
></script>
<section
class=
"page-content-main"
>
<div
class=
"container-fluid"
>
<div
class=
"row"
>
<?php
if
(
!
empty
(
$input_errors
)
)
print_input_errors
(
$input_errors
);
?>
<?php
if
(
isset
(
$input_errors
)
&&
count
(
$input_errors
)
>
0
)
print_input_errors
(
$input_errors
);
?>
<form
method=
"post"
name=
"iform"
id=
"iform"
>
<section
class=
"col-xs-12"
>
<div
class=
"content-box"
>
<form
name=
"iform"
action=
"services_upnp.php"
method=
"post"
>
<div
class=
"table-responsive"
>
<table
class=
"table table-striped table-sort"
>
<table
class=
"table table-striped"
>
<thead>
<tr>
<td
width=
"22%"
>
<strong>
<?=
gettext
(
"UPnP & NAT-PMP Settings"
);
?>
</strong>
</td>
<td
width=
"78%"
align=
"right"
>
<small>
<?=
gettext
(
"full help"
);
?>
</small>
<i
class=
"fa fa-toggle-off text-danger"
style=
"cursor: pointer;"
id=
"show_all_help_page"
type=
"button"
></i>
</td>
</tr>
</thead>
<tbody>
<tr>
<td><i
class=
"fa fa-info-circle text-muted"
></i>
<?=
gettext
(
"Enable"
);
?>
</td>
<td>
<input
name=
"enable"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'enable'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
</td>
</tr>
<tr>
<td><a
id=
"help_for_enable_upnp"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Allow UPnP Port Mapping"
);
?>
</td>
<td>
<input
name=
"enable_upnp"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'enable_upnp'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
<div
class=
"hidden"
for=
"help_for_enable_upnp"
>
<?=
gettext
(
"This protocol is often used by Microsoft-compatible systems."
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_enable_natpmp"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Allow NAT-PMP Port Mapping"
);
?>
</td>
<td>
<input
name=
"enable_natpmp"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'enable_natpmp'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
<div
class=
"hidden"
for=
"help_for_enable_natpmp"
>
<?=
gettext
(
"This protocol is often used by Apple-compatible systems."
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_ext_iface"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"External Interface"
);
?>
</td>
<td>
<select
class=
"selectpicker"
name=
"ext_iface"
>
<?php
$cols
=
0
;
$savevalue
=
gettext
(
"Save"
);
$pkg_buttons
=
""
;
foreach
(
$pkg
[
'fields'
][
'field'
]
as
$pkga
)
{
if
(
isset
(
$pkga
[
'fieldname'
]))
{
$fieldname
=
$pkga
[
'fieldname'
];
}
else
{
$fieldname
=
""
;
}
if
(
isset
(
$pkga
[
'description'
]))
{
$description
=
$pkga
[
'description'
];
}
else
{
$description
=
""
;
}
$colspan
=
''
;
if
(
$pkga
[
'type'
]
==
"sorting"
)
continue
;
if
(
$pkga
[
'type'
]
==
"listtopic"
)
{
$input
.=
"<tr id='tr_
{
$fieldname
}
'><td colspan=
\"
2
\"
class=
\"
listtopic
\"
><strong>
{
$pkga
[
'name'
]
}
</strong></td></tr>
\n
"
;
echo
$input
;
continue
;
}
if
(
isset
(
$pkga
[
'combinefields'
])
&&
$pkga
[
'combinefields'
]
==
"begin"
){
$input
=
"<tr valign='top' id='tr_
{
$pkga
[
'fieldname'
]
}
'>"
;
echo
$input
;
$size
=
""
;
if
(
isset
(
$pkga
[
'dontdisplayname'
])){
$input
=
""
;
if
(
!
isset
(
$pkga
[
'combinefields'
]))
$input
.=
"<tr valign='top' id='tr_
{
$pkga
[
'fieldname'
]
}
'>"
;
if
(
isset
(
$pkga
[
'usecolspan2'
]))
$colspan
=
"colspan='2'"
;
else
$input
.=
"<td width='22%' class='vncell
{
$req
}
'> </td>"
;
$advanced
.=
$input
;
$adv_filed_count
++
;
}
else
echo
$input
;
}
else
if
(
!
isset
(
$pkga
[
'placeonbottom'
])){
unset
(
$req
);
if
(
isset
(
$pkga
[
'required'
]))
{
$req
=
'req'
;
}
else
{
$req
=
''
;
}
$input
=
"<tr><td valign='top' width=
\"
22%
\"
class=
\"
vncell
{
$req
}
\"
>"
;
$input
.=
fixup_string
(
$pkga
[
'fielddescr'
]);
$input
.=
"</td>"
;
echo
$input
;
}
if
(
isset
(
$pkga
[
'combinefields'
])
&&
$pkga
[
'combinefields'
]
==
"begin"
){
$input
=
"<td class=
\"
vncell
\"
><table summary=
\"
advanced
\"
>"
;
echo
$input
;
}
$class
=
(
isset
(
$pkga
[
'combinefields'
])
?
''
:
'class="vtable"'
);
if
(
!
isset
(
$pkga
[
'placeonbottom'
])){
$input
=
"<td valign='top'
{
$colspan
}
{
$class
}
>"
;
echo
$input
;
}
// if user is editing a record, load in the data.
if
(
isset
(
$get_from_post
))
{
$value
=
$_POST
[
$fieldname
];
if
(
is_array
(
$value
))
{
$value
=
implode
(
','
,
$value
);
}
}
elseif
(
$a_pkg
[
0
])
{
$value
=
$a_pkg
[
0
][
$fieldname
];
}
else
{
$value
=
$pkga
[
'default_value'
];
}
switch
(
$pkga
[
'type'
]){
case
"input"
:
$size
=
(
!
empty
(
$pkga
[
'size'
])
?
" size='
{
$pkga
[
'size'
]
}
' "
:
""
);
$input
=
"<input
{
$size
}
id='
{
$pkga
[
'fieldname'
]
}
' name='
{
$pkga
[
'fieldname'
]
}
' class='formfld unknown' type='text' value=
\"
"
.
htmlspecialchars
(
$value
)
.
"
\"
/>
\n
"
;
$input
.=
"<br />"
.
fixup_string
(
$description
)
.
"
\n
"
;
echo
$input
;
break
;
case
"select_source"
:
$fieldname
=
$pkga
[
'fieldname'
];
if
(
isset
(
$pkga
[
'multiple'
]))
{
$multiple
=
'multiple="multiple"'
;
$items
=
explode
(
','
,
$value
);
$fieldname
.=
"[]"
;
}
else
{
$multiple
=
''
;
$items
=
array
(
$value
);
}
$size
=
(
isset
(
$pkga
[
'size'
])
?
"size=
\"
{
$pkga
[
'size'
]
}
\"
"
:
''
);
$onchange
=
(
isset
(
$pkga
[
'onchange'
])
?
"onchange=
\"
{
$pkga
[
'onchange'
]
}
\"
"
:
''
);
$input
=
"<select id='
{
$pkga
[
'fieldname'
]
}
'
{
$multiple
}
{
$size
}
{
$onchange
}
name=
\"
{
$fieldname
}
\"
>
\n
"
;
echo
$input
;
$source_url
=
$pkga
[
'source'
];
eval
(
"
\$
pkg_source_txt = &
$source_url
;"
);
$input
=
""
;
#check if show disable option is present on xml
if
(
isset
(
$pkga
[
'show_disable_value'
])){
array_push
(
$pkg_source_txt
,
array
((
$pkga
[
'source_name'
]
?
$pkga
[
'source_name'
]
:
$pkga
[
'name'
])
=>
$pkga
[
'show_disable_value'
],
(
$pkga
[
'source_value'
]
?
$pkga
[
'source_value'
]
:
$pkga
[
'value'
])
=>
$pkga
[
'show_disable_value'
]));
}
foreach
(
$pkg_source_txt
as
$opt
)
{
$source_name
=
(
$pkga
[
'source_name'
]
?
$opt
[
$pkga
[
'source_name'
]]
:
$opt
[
$pkga
[
'name'
]]);
$source_value
=
(
$pkga
[
'source_value'
]
?
$opt
[
$pkga
[
'source_value'
]]
:
$opt
[
$pkga
[
'value'
]]);
$selected
=
(
in_array
(
$source_value
,
$items
)
?
'selected="selected"'
:
''
);
$input
.=
"
\t
<option value=
\"
{
$source_value
}
\"
$selected
>
{
$source_name
}
</option>
\n
"
;
}
$input
.=
"</select>
\n
<br />
\n
"
.
fixup_string
(
$description
)
.
"
\n
"
;
echo
$input
;
break
;
case
"checkbox"
:
$checkboxchecked
=
(
$value
==
"on"
?
" checked=
\"
checked
\"
"
:
""
);
$onchange
=
(
isset
(
$pkga
[
'onchange'
])
?
"onchange=
\"
{
$pkga
[
'onchange'
]
}
\"
"
:
''
);
if
(
isset
(
$pkga
[
'enablefields'
])
||
isset
(
$pkga
[
'checkenablefields'
]))
$onclick
=
' onclick="javascript:enablechange();"'
;
$input
=
"<input id='
{
$pkga
[
'fieldname'
]
}
' type='checkbox' name='
{
$pkga
[
'fieldname'
]
}
'
{
$checkboxchecked
}
{
$onclick
}
{
$onchange
}
/>
\n
"
;
$input
.=
"<br />"
.
fixup_string
(
$description
)
.
"
\n
"
;
echo
$input
;
break
;
}
#check typehint value
if
(
isset
(
$pkga
[
'typehint'
]))
echo
" "
.
$pkga
[
'typehint'
];
#check combinefields options
if
(
isset
(
$pkga
[
'combinefields'
])){
$input
=
"</td>"
;
if
(
$pkga
[
'combinefields'
]
==
"end"
)
$input
.=
"</table></td></tr>"
;
}
else
{
$input
=
"</td></tr>"
;
if
(
isset
(
$pkga
[
'usecolspan2'
]))
$input
.=
"</tr><br />"
;
}
echo
"
{
$input
}
\n
"
;
}
?>
foreach
(
get_configured_interface_with_descr
()
as
$iface
=>
$ifacename
)
:?>
<
option
value
=
"<?=
$iface
;?>"
<?=
$pconfig
[
'ext_iface'
]
==
$iface
?
"selected=
\"
selected
\"
"
:
""
;
?>
>
<?=
htmlspecialchars
(
$ifacename
);
?>
</option>
<?php
endforeach
;
?>
</select>
<div
class=
"hidden"
for=
"help_for_ext_iface"
>
<?=
gettext
(
"Select only your primary WAN interface (interface with your default route). Only one interface is allowed here, not multiple."
);
?>
</div>
</td>
</tr>
<tr>
<td
width=
"22%"
valign=
"top"
>
</td>
<td><a
id=
"help_for_iface_array"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Interfaces (generally LAN)"
);
?>
</td>
<td>
<select
class=
"selectpicker"
name=
"iface_array[]"
multiple=
"multiple"
>
<option
value=
"lo0"
<?=
in_array
(
'lo0'
,
$pconfig
[
'iface_array'
])
?
"selected=
\"
selected
\"
"
:
""
;
?>
>
<?=
gettext
(
"Localhost"
);
?>
</option>
<?php
foreach
(
get_configured_interface_with_descr
()
as
$iface
=>
$ifacename
)
:?>
<
option
value
=
"<?=
$iface
;?>"
<?=
in_array
(
$iface
,
$pconfig
[
'iface_array'
])
?
"selected=
\"
selected
\"
"
:
""
;
?>
>
<?=
htmlspecialchars
(
$ifacename
);
?>
</option>
<?php
endforeach
;
?>
</select>
<div
class=
"hidden"
for=
"help_for_ext_iface"
>
<?=
gettext
(
"You can select multiple interfaces here."
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_download"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Maximum Download Speed"
);
?>
</td>
<td>
<input
name=
"download"
type=
"text"
value=
"
<?=
$pconfig
[
'download'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_download"
>
<?=
gettext
(
"(Kbits/second)"
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_upload"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Maximum Upload Speed"
);
?>
</td>
<td>
<input
name=
"upload"
type=
"text"
value=
"
<?=
$pconfig
[
'upload'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_upload"
>
<?=
gettext
(
"(Kbits/second)"
);
?>
</div>
</td>
</tr>
<tr>
<td><i
class=
"fa fa-info-circle text-muted"
></i>
<?=
gettext
(
"Override WAN address"
);
?>
</td>
<td>
<input
name=
"overridewanip"
type=
"text"
value=
"
<?=
$pconfig
[
'overridewanip'
];
?>
"
/>
</td>
</tr>
<tr>
<td><a
id=
"help_for_logpackets"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Log NAT-PMP"
);
?>
</td>
<td>
<input
name=
"logpackets"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'logpackets'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
<div
class=
"hidden"
for=
"help_for_logpackets"
>
<?=
gettext
(
"Log packets handled by UPnP & NAT-PMP rules?"
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_sysuptime"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Use system time"
);
?>
</td>
<td>
<input
name=
"sysuptime"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'sysuptime'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
<div
class=
"hidden"
for=
"help_for_sysuptime"
>
<?=
gettext
(
"Use system uptime instead of UPnP & NAT-PMP service uptime?"
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_permdefault"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Default deny"
);
?>
</td>
<td>
<input
name=
"permdefault"
type=
"checkbox"
value=
"yes"
<?=
!
empty
(
$pconfig
[
'permdefault'
])
?
"checked=
\"
checked
\"
"
:
""
;
?>
/>
<div
class=
"hidden"
for=
"help_for_permdefault"
>
<?=
gettext
(
"By default deny access to UPnP & NAT-PMP?"
);
?>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section
class=
"col-xs-12"
>
<div
class=
"content-box"
>
<div
class=
"table-responsive"
>
<table
class=
"table table-striped"
>
<thead>
<tr>
<th
colspan=
"2"
>
<?=
gettext
(
"User specified permissions"
);
?>
</th>
</tr>
</thead>
<tbody>
<tr>
<td
width=
"22%"
><a
id=
"help_for_permuser1"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Set 1"
);
?>
</td>
<td
width=
"78%"
>
<div
id=
"buttons"
>
<?php
echo
"<input name='Submit' type='submit' class='btn btn-primary formbtn' value=
\"
"
.
htmlspecialchars
(
$savevalue
)
.
"
\"
/>
\n
{
$pkg_buttons
}
\n
"
;
?>
<input
name=
"permuser1"
type=
"text"
value=
"
<?=
$pconfig
[
'permuser1'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_permuser1"
>
<?=
gettext
(
"Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]<br />Example: allow 1024-65535 192.168.0.0/24 1024-65535"
);
?>
</div>
</td>
</tr>
</table>
</div>
</form>
<tr>
<td><a
id=
"help_for_permuser2"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Set 2"
);
?>
</td>
<td>
<input
name=
"permuser2"
type=
"text"
value=
"
<?=
$pconfig
[
'permuser2'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_permuser2"
>
<?=
gettext
(
"Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]"
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_permuser3"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Set 3"
);
?>
</td>
<td>
<input
name=
"permuser3"
type=
"text"
value=
"
<?=
$pconfig
[
'permuser3'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_permuser3"
>
<?=
gettext
(
"Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]"
);
?>
</div>
</td>
</tr>
<tr>
<td><a
id=
"help_for_permuser4"
href=
"#"
class=
"showhelp"
><i
class=
"fa fa-info-circle"
></i></a>
<?=
gettext
(
"Set 4"
);
?>
</td>
<td>
<input
name=
"permuser4"
type=
"text"
value=
"
<?=
$pconfig
[
'permuser4'
];
?>
"
/>
<div
class=
"hidden"
for=
"help_for_permuser4"
>
<?=
gettext
(
"Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]"
);
?>
</div>
</td>
</tr>
</tbody>
</tbody>
</table>
</div>
</div>
</section>
<section
class=
"col-xs-12"
>
<div
class=
"content-box"
>
<div
class=
"table-responsive"
>
<table
class=
"table table-striped"
>
<tbody>
<tr>
<td
width=
"22%"
valign=
"top"
>
</td>
<td
width=
"78%"
>
<input
name=
"Submit"
type=
"submit"
class=
"btn btn-primary"
value=
"
<?=
gettext
(
"Save"
);
?>
"
/>
</td>
</tr>
</table>
</div>
</div>
</section>
</form>
</div>
</div>
</section>
<?php
include
(
"foot.inc"
);
?>
<?php
function
fixup_string
(
$string
)
{
global
$config
;
// fixup #1: $myurl -> http[s]://ip_address:port/
$https
=
""
;
if
(
!
empty
(
$config
[
'system'
][
'webguiport'
]))
{
$port
=
$config
[
'system'
][
'webguiport'
];
}
else
{
$port
=
null
;
}
if
(
$port
<>
"443"
and
$port
<>
"80"
)
$urlport
=
":"
.
$port
;
else
$urlport
=
""
;
if
(
$config
[
'system'
][
'webgui'
][
'protocol'
]
==
"https"
)
$https
=
"s"
;
$myurl
=
"http"
.
$https
.
"://"
.
getenv
(
"HTTP_HOST"
)
.
$urlport
;
$newstring
=
str_replace
(
"
\$
myurl"
,
$myurl
,
$string
);
$string
=
$newstring
;
// fixup #2: $wanip
$curwanip
=
get_interface_ip
();
$newstring
=
str_replace
(
"
\$
wanip"
,
$curwanip
,
$string
);
$string
=
$newstring
;
// fixup #3: $lanip
$lancfg
=
$config
[
'interfaces'
][
'lan'
];
$lanip
=
$lancfg
[
'ipaddr'
];
$newstring
=
str_replace
(
"
\$
lanip"
,
$lanip
,
$string
);
$string
=
$newstring
;
// fixup #4: fix'r'up here.
return
$newstring
;
}
/* Return html div fields */
function
display_advanced_field
(
$fieldname
)
{
$div
=
"<div id='showadv_
{
$fieldname
}
'>
\n
"
;
$div
.=
"<input type='button' onclick='show_
{
$fieldname
}
()' value='"
.
gettext
(
"Advanced"
)
.
"' /> - "
.
gettext
(
"Show advanced option"
)
.
"</div>
\n
"
;
$div
.=
"<div id='show_
{
$fieldname
}
' style='display:none'>
\n
"
;
return
$div
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment