1
0
mirror of http://git.whoc.org.uk/git/password-manager.git synced 2025-10-25 01:37:34 +02:00

First release of /delta version

This commit is contained in:
Giulio Cesare Solaroli
2013-08-30 17:56:53 +02:00
parent bde3c7b985
commit 20bea94ab6
131 changed files with 59632 additions and 79 deletions

View File

@@ -0,0 +1,471 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
/**
* @class Clipperz.ext.DomHelper
* Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
* For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
* @singleton
*/
Clipperz.YUI.DomHelper = new function(){
/**@private*/
var d = document;
var tempTableEl = null;
/** True to force the use of DOM instead of html fragments @type Boolean */
this.useDom = false;
var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i;
/**
* Applies a style specification to an element
* @param {String/HTMLElement} el The element to apply styles to
* @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
* a function which returns such a specification.
*/
this.applyStyles = function(el, styles){
if(styles){
var D = YAHOO.util.Dom;
if (typeof styles == "string"){
var re = /\s?([a-z\-]*)\:([^;]*);?/gi;
var matches;
while ((matches = re.exec(styles)) != null){
D.setStyle(el, matches[1], matches[2]);
}
}else if (typeof styles == "object"){
for (var style in styles){
D.setStyle(el, style, styles[style]);
}
}else if (typeof styles == "function"){
Clipperz.YUI.DomHelper.applyStyles(el, styles.call());
}
}
};
// build as innerHTML where available
/** @ignore */
var createHtml = function(o){
var b = '';
if(typeof(o['html']) != 'undefined') {
o['html'] = Clipperz.Base.sanitizeString(o['html']);
} else if (typeof(o['htmlString']) != 'undefined') {
o['html'] = o['htmlString'];
delete o.htmlString;
}
if (MochiKit.Base.isArrayLike(o)) {
for (var i = 0, l = o.length; i < l; i++) {
b += createHtml(o[i]);
}
return b;
}
b += '<' + o.tag;
for(var attr in o){
if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue;
if(attr == 'style'){
var s = o['style'];
if(typeof s == 'function'){
s = s.call();
}
if(typeof s == 'string'){
b += ' style="' + s + '"';
}else if(typeof s == 'object'){
b += ' style="';
for(var key in s){
if(typeof s[key] != 'function'){
b += key + ':' + s[key] + ';';
}
}
b += '"';
}
}else{
if(attr == 'cls'){
b += ' class="' + o['cls'] + '"';
}else if(attr == 'htmlFor'){
b += ' for="' + o['htmlFor'] + '"';
}else{
b += ' ' + attr + '="' + o[attr] + '"';
}
}
}
if(emptyTags.test(o.tag)){
b += ' />';
}else{
b += '>';
if(o.children){
for(var i = 0, len = o.children.length; i < len; i++) {
b += createHtml(o.children[i], b);
}
}
if(o.html){
b += o.html;
}
b += '</' + o.tag + '>';
}
return b;
}
// build as dom
/** @ignore */
var createDom = function(o, parentNode){
var el = d.createElement(o.tag);
var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
for(var attr in o){
if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue;
if(attr=='cls'){
el.className = o['cls'];
}else{
if(useSet) el.setAttribute(attr, o[attr]);
else el[attr] = o[attr];
}
}
Clipperz.YUI.DomHelper.applyStyles(el, o.style);
if(o.children){
for(var i = 0, len = o.children.length; i < len; i++) {
createDom(o.children[i], el);
}
}
if(o.html){
el.innerHTML = o.html;
}
if(parentNode){
parentNode.appendChild(el);
}
return el;
};
/**
* @ignore
* Nasty code for IE's broken table implementation
*/
var insertIntoTable = function(tag, where, el, html){
if(!tempTableEl){
tempTableEl = document.createElement('div');
}
var nodes;
if(tag == 'table' || tag == 'tbody'){
tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>';
nodes = tempTableEl.firstChild.firstChild.childNodes;
}else{
tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
nodes = tempTableEl.firstChild.firstChild.firstChild.childNodes;
}
if (where == 'beforebegin') {
nodes.reverse();
// el.parentNode.insertBefore(node, el);
MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el)}, nodes);
} else if (where == 'afterbegin') {
nodes.reverse();
// el.insertBefore(node, el.firstChild);
MochiKit.Base.map(function(aNode) {el.insertBefore(aNode, el.firstChild)}, nodes);
} else if (where == 'beforeend') {
// el.appendChild(node);
MochiKit.Base.map(function(aNode) {el.appendChild(aNode)}, nodes);
} else if (where == 'afterend') {
// el.parentNode.insertBefore(node, el.nextSibling);
MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el.nextSibling)}, nodes);
}
return nodes;
}
/**
* Inserts an HTML fragment into the Dom
* @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
* @param {HTMLElement} el The context element
* @param {String} html The HTML fragmenet
* @return {HTMLElement} The new node
*/
this.insertHtml = function(where, el, html){
where = where.toLowerCase();
// if(el.insertAdjacentHTML){
if(Clipperz_IEisBroken){
var tag = el.tagName.toLowerCase();
if(tag == 'table' || tag == 'tbody' || tag == 'tr'){
return insertIntoTable(tag, where, el, html);
}
switch(where){
case 'beforebegin':
el.insertAdjacentHTML(where, html);
return el.previousSibling;
case 'afterbegin':
el.insertAdjacentHTML(where, html);
return el.firstChild;
case 'beforeend':
el.insertAdjacentHTML(where, html);
return el.lastChild;
case 'afterend':
el.insertAdjacentHTML(where, html);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' + where + '"';
}
var range = el.ownerDocument.createRange();
var frag;
switch(where){
case 'beforebegin':
range.setStartBefore(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el);
return el.previousSibling;
case 'afterbegin':
if(el.firstChild){ // faster
range.setStartBefore(el.firstChild);
}else{
range.selectNodeContents(el);
range.collapse(true);
}
frag = range.createContextualFragment(html);
el.insertBefore(frag, el.firstChild);
return el.firstChild;
case 'beforeend':
if(el.lastChild){
range.setStartAfter(el.lastChild); // faster
}else{
range.selectNodeContents(el);
range.collapse(false);
}
frag = range.createContextualFragment(html);
el.appendChild(frag);
return el.lastChild;
case 'afterend':
range.setStartAfter(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el.nextSibling);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' + where + '"';
};
/**
* Creates new Dom element(s) and inserts them before el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} o The Dom object spec (and children)
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
this.insertBefore = function(el, o, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
var newNode;
if(this.useDom){
newNode = createDom(o, null);
el.parentNode.insertBefore(newNode, el);
}else{
var html = createHtml(o);
newNode = this.insertHtml('beforeBegin', el, html);
}
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
};
/**
* Creates new Dom element(s) and inserts them after el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} o The Dom object spec (and children)
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
this.insertAfter = function(el, o, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
var newNode;
if(this.useDom){
newNode = createDom(o, null);
el.parentNode.insertBefore(newNode, el.nextSibling);
}else{
var html = createHtml(o);
newNode = this.insertHtml('afterEnd', el, html);
}
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
};
/**
* Creates new Dom element(s) and appends them to el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} o The Dom object spec (and children)
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
this.append = function(el, o, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
var newNode;
if(this.useDom){
newNode = createDom(o, null);
el.appendChild(newNode);
}else{
var html = createHtml(o);
newNode = this.insertHtml('beforeEnd', el, html);
}
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
};
/**
* Creates new Dom element(s) and overwrites the contents of el with them
* @param {String/HTMLElement/Element} el The context element
* @param {Object} o The Dom object spec (and children)
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
this.overwrite = function(el, o, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
el.innerHTML = createHtml(o);
return returnElement ? YAHOO.Element.get(el.firstChild, true) : el.firstChild;
};
/**
* Creates a new Clipperz.YUI.DomHelper.Template from the Dom object spec
* @param {Object} o The Dom object spec (and children)
* @return {Clipperz.YUI.DomHelper.Template} The new template
*/
this.createTemplate = function(o){
var html = createHtml(o);
return new Clipperz.YUI.DomHelper.Template(html);
};
}();
/**
* @class Clipperz.YUI.DomHelper.Template
* Represents an HTML fragment template.
* For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
* <br>
* <b>This class is also available as Clipperz.YUI.Template</b>.
* @constructor
* @param {String/Array} html The HTML fragment or an array of fragments to join('') or multiple arguments to join('')
*/
Clipperz.YUI.DomHelper.Template = function(html){
if(html instanceof Array){
html = html.join('');
}else if(arguments.length > 1){
html = Array.prototype.join.call(arguments, '');
}
/**@private*/
this.html = html;
};
Clipperz.YUI.DomHelper.Template.prototype = {
/**
* Returns an HTML fragment of this template with the specified values applied
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @return {String}
*/
applyTemplate : function(values){
if(this.compiled){
return this.compiled(values);
}
var empty = '';
var fn = function(match, index){
if(typeof values[index] != 'undefined'){
return values[index];
}else{
return empty;
}
}
return this.html.replace(this.re, fn);
},
/**
* The regular expression used to match template variables
* @type RegExp
* @property
*/
re : /\{([\w|-]+)\}/g,
/**
* Compiles the template into an internal function, eliminating the RegEx overhead
*/
compile : function(){
var body = ["this.compiled = function(values){ return ['"];
body.push(this.html.replace(this.re, "', values['$1'], '"));
body.push("'].join('');};");
eval(body.join(''));
return this;
},
/**
* Applies the supplied values to the template and inserts the new node(s) before el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
insertBefore: function(el, values, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values));
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
},
/**
* Applies the supplied values to the template and inserts the new node(s) after el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
insertAfter : function(el, values, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
var newNode = Clipperz.YUI.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values));
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
},
/**
* Applies the supplied values to the template and append the new node(s) to el
* @param {String/HTMLElement/Element} el The context element
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
append : function(el, values, returnElement){
var sanitizedValues;
var key;
sanitizedValues = {};
for (key in values) {
sanitizedValues[key] = Clipperz.Base.sanitizeString(values[key]);
}
el = (typeof el == 'string') ? YAHOO.util.Dom.get(el) : el;
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(sanitizedValues));
return newNode;
},
/**
* Applies the supplied values to the template and overwrites the content of el with the new node(s)
* @param {String/HTMLElement/Element} el The context element
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
* @return {HTMLElement} The new node
*/
overwrite : function(el, values, returnElement){
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
el.innerHTML = '';
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values));
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
}
};
/**
* Alias for applyTemplate
* @method
*/
Clipperz.YUI.DomHelper.Template.prototype.apply = Clipperz.YUI.DomHelper.Template.prototype.applyTemplate;
Clipperz.YUI.Template = Clipperz.YUI.DomHelper.Template;

View File

@@ -0,0 +1,709 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
/*
* yui-ext 0.40
* Copyright(c) 2006, Jack Slocum.
*/
/**
* @class Clipperz.YUI.DomQuery
* Provides high performance selector/xpath processing by compiling queries into reusable functions.
* New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
* @singleton
*/
Clipperz.YUI.DomQuery = function(){
var cache = {}, simpleCache = {}, valueCache = {};
var nonSpace = /\S/;
var trimRe = /^\s*(.*?)\s*$/;
var tplRe = /\{(\d+)\}/g;
var modeRe = /^(\s?[\/>]\s?|\s|$)/;
var clsRes = {};
function child(p, index){
var i = 0;
var n = p.firstChild;
while(n){
if(n.nodeType == 1){
i++;
if(i == index){
return n;
}
}
n = n.nextSibling;
}
return null;
};
function next(d){
var n = d.nextSibling;
while(n && n.nodeType != 1){
n = n.nextSibling;
}
return n;
};
function prev(d){
var n = d.previousSibling;
while(n && n.nodeType != 1){
n = n.previousSibling;
}
return n;
};
function clean(d){
var n = d.firstChild, ni = -1;
while(n){
var nx = n.nextSibling;
if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
d.removeChild(n);
}else{
n.nodeIndex = ++ni;
}
n = nx;
}
return this;
};
function byClassName(c, a, v){
if(!v){
return c;
}
var re = clsRes[v];
if(!re){
re = new RegExp('(?:^|\\s)(?:' + v + ')(?:\\s|$)');
clsRes[v] = re;
}
var r = [];
for(var i = 0, ci; ci = c[i]; i++){
if(re.test(ci.className)){
r[r.length] = ci;
}
}
return r;
};
function convert(c){
if(c.slice){
return c;
}
var r = [];
for(var i = 0, l = c.length; i < l; i++){
r[r.length] = c[i];
}
return r;
};
function attrValue(n, attr){
if(!n.tagName && typeof n.length != 'undefined'){
n = n[0];
}
if(!n){
return null;
}
if(attr == 'for'){
return n.htmlFor;
}
if(attr == 'class' || attr == 'className'){
return n.className;
}
return n.getAttribute(attr) || n[attr];
};
function getNodes(ns, mode, tagName){
var result = [], cs;
if(!ns){
return result;
}
mode = mode ? mode.replace(trimRe, '$1') : '';
tagName = tagName || '*';
if(ns.tagName || ns == document){
ns = [ns];
}
if(mode != '/' && mode != '>'){
for(var i = 0, ni; ni = ns[i]; i++){
cs = ni.getElementsByTagName(tagName);
result = concat(result, cs);
}
}else{
for(var i = 0, ni; ni = ns[i]; i++){
var cn = ni.getElementsByTagName(tagName);
for(var j = 0, cj; cj = cn[j]; j++){
if(cj.parentNode == ni){
result[result.length] = cj;
}
}
}
}
return result;
};
function concat(a, b){
if(b.slice){
return a.concat(b);
}
for(var i = 0, l = b.length; i < l; i++){
a[a.length] = b[i];
}
return a;
}
function byTag(cs, tagName){
if(cs.tagName || cs == document){
cs = [cs];
}
if(!tagName){
return cs;
}
var r = []; tagName = tagName.toLowerCase();
for(var i = 0, ci; ci = cs[i]; i++){
if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
r[r.length] = ci;
}
}
return r;
};
function byId(cs, attr, id){
if(cs.tagName || cs == document){
cs = [cs];
}
if(!id){
return cs;
}
var r = [];
for(var i = 0, l = cs.length; i < l; i++){
var ci = cs[i];
if(ci && ci.id == id){
r[r.length] = ci;
}
}
return r;
};
function byAttribute(cs, attr, value, op, custom){
var r = [], st = custom=='{';
var f = Clipperz.YUI.DomQuery.operators[op];
for(var i = 0, l = cs.length; i < l; i++){
var a;
if(st){
a = Clipperz.YUI.DomQuery.getStyle(cs[i], attr);
}
else if(attr == 'class' || attr == 'className'){
a = cs[i].className;
}else if(attr == 'for'){
a = cs[i].htmlFor;
}else{
a = cs[i].getAttribute(attr);
}
if((f && f(a, value)) || (!f && a)){
r[r.length] = cs[i];
}
}
return r;
};
function byPseudo(cs, name, value){
return Clipperz.YUI.DomQuery.pseudos[name](cs, value);
};
// This is for IE MSXML which does not support expandos.
// IE runs the same speed using setAttribute, however FF slows way down
// and Safari completely fails so they need to continue to use expandos.
// Branched at load time for faster execution.
var isIE = window.ActiveXObject;
var addAttr = isIE ?
function(n, a, v){
n.setAttribute(a, v);
} :
function(n, a, v){
n[a] = v;
};
var getAttr = isIE ?
function(n, a){
return n.getAttribute(a);
} :
function(n, a){
return n[a];
};
var clearAttr = isIE ?
function(n, a){
n.removeAttribute(a);
} :
function(n, a, v){
delete n[a];
};
function nodup(cs){
if(!cs.length){
return cs;
}
addAttr(cs[0], '_nodup', true);
var r = [cs[0]];
for(var i = 1, len = cs.length; i < len; i++){
var c = cs[i];
if(!getAttr(c, '_nodup')){
addAttr(c, '_nodup', true);
r[r.length] = c;
}
}
for(var i = 0, len = cs.length; i < len; i++){
clearAttr(cs[i], '_nodup');
}
return r;
}
function quickDiff(c1, c2){
if(!c1.length){
return c2;
}
for(var i = 0, len = c1.length; i < len; i++){
addAttr(c1[i], '_qdiff', true);
}
var r = [];
for(var i = 0, len = c2.length; i < len; i++){
if(!getAttr(c2[i], '_qdiff')){
r[r.length] = c2[i];
}
}
for(var i = 0, len = c1.length; i < len; i++){
clearAttr(c1[i], '_qdiff');
}
return r;
}
function quickId(ns, mode, root, id){
if(ns == root){
var d = root.ownerDocument || root;
return d.getElementById(id);
}
ns = getNodes(ns, mode, '*');
return byId(ns, null, id);
}
return {
getStyle : function(el, name){
return YAHOO.util.Dom.getStyle(el, name);
},
/**
* Compiles a selector/xpath query into a reusable function. The returned function
* takes one parameter "root" (optional), which is the context node from where the query should start.
* @param {String} selector The selector/xpath query
* @param {String} type (optional) Either 'select' (the default) or 'simple' for a simple selector match
* @return {Function}
*/
compile : function(path, type){
// strip leading slashes
while(path.substr(0, 1)=='/'){
path = path.substr(1);
}
type = type || 'select';
var fn = ['var f = function(root){\n var mode; var n = root || document;\n'];
var q = path, mode, lq;
var tk = Clipperz.YUI.DomQuery.matchers;
var tklen = tk.length;
var mm;
while(q && lq != q){
lq = q;
var tm = q.match(/^(#)?([\w-\*]+)/);
if(type == 'select'){
if(tm){
if(tm[1] == '#'){
fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
}else{
fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
}
q = q.replace(tm[0], '');
}else{
fn[fn.length] = 'n = getNodes(n, mode, "*");';
}
}else{
if(tm){
if(tm[1] == '#'){
fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
}else{
fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
}
q = q.replace(tm[0], '');
}
}
while(!(mm = q.match(modeRe))){
var matched = false;
for(var j = 0; j < tklen; j++){
var t = tk[j];
var m = q.match(t.re);
if(m){
fn[fn.length] = t.select.replace(tplRe, function(x, i){
return m[i];
});
q = q.replace(m[0], '');
matched = true;
break;
}
}
// prevent infinite loop on bad selector
if(!matched){
throw 'Error parsing selector, parsing failed at "' + q + '"';
}
}
if(mm[1]){
fn[fn.length] = 'mode="'+mm[1]+'";';
q = q.replace(mm[1], '');
}
}
fn[fn.length] = 'return nodup(n);\n}';
eval(fn.join(''));
return f;
},
/**
* Selects a group of elements.
* @param {String} selector The selector/xpath query
* @param {Node} root (optional) The start of the query (defaults to document).
* @return {Array}
*/
select : function(path, root, type){
if(!root || root == document){
root = document;
}
if(typeof root == 'string'){
root = document.getElementById(root);
}
var paths = path.split(',');
var results = [];
for(var i = 0, len = paths.length; i < len; i++){
var p = paths[i].replace(trimRe, '$1');
if(!cache[p]){
cache[p] = Clipperz.YUI.DomQuery.compile(p);
if(!cache[p]){
throw p + ' is not a valid selector';
}
}
var result = cache[p](root);
if(result && result != document){
results = results.concat(result);
}
}
return results;
},
/**
* Selects a single element.
* @param {String} selector The selector/xpath query
* @param {Node} root (optional) The start of the query (defaults to document).
* @return {Element}
*/
selectNode : function(path, root){
return Clipperz.YUI.DomQuery.select(path, root)[0];
},
/**
* Selects the value of a node, optionally replacing null with the defaultValue.
* @param {String} selector The selector/xpath query
* @param {Node} root (optional) The start of the query (defaults to document).
* @param {String} defaultValue
*/
selectValue : function(path, root, defaultValue){
path = path.replace(trimRe, '$1');
if(!valueCache[path]){
valueCache[path] = Clipperz.YUI.DomQuery.compile(path, 'simple');
}
var n = valueCache[path](root);
n = n[0] ? n[0] : n;
var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
return (v === null ? defaultValue : v);
},
/**
* Selects the value of a node, parsing integers and floats.
* @param {String} selector The selector/xpath query
* @param {Node} root (optional) The start of the query (defaults to document).
* @param {Number} defaultValue
* @return {Number}
*/
selectNumber : function(path, root, defaultValue){
var v = Clipperz.YUI.DomQuery.selectValue(path, root, defaultValue || 0);
return parseFloat(v);
},
/**
* Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
* @param {String/HTMLElement/Array} el An element id, element or array of elements
* @param {String} selector The simple selector to test
* @return {Boolean}
*/
is : function(el, ss){
if(typeof el == 'string'){
el = document.getElementById(el);
}
var isArray = (el instanceof Array);
var result = Clipperz.YUI.DomQuery.filter(isArray ? el : [el], ss);
return isArray ? (result.length == el.length) : (result.length > 0);
},
/**
* Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
* @param {Array} el An array of elements to filter
* @param {String} selector The simple selector to test
* @param {Boolean} nonMatches If true, it returns the elements that DON'T match
* the selector instead of the ones that match
* @return {Array}
*/
filter : function(els, ss, nonMatches){
ss = ss.replace(trimRe, '$1');
if(!simpleCache[ss]){
simpleCache[ss] = Clipperz.YUI.DomQuery.compile(ss, 'simple');
}
var result = simpleCache[ss](els);
return nonMatches ? quickDiff(result, els) : result;
},
/**
* Collection of matching regular expressions and code snippets.
*/
matchers : [{
re: /^\.([\w-]+)/,
select: 'n = byClassName(n, null, "{1}");'
}, {
re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
select: 'n = byPseudo(n, "{1}", "{2}");'
},{
re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
}, {
re: /^#([\w-]+)/,
select: 'n = byId(n, null, "{1}");'
},{
re: /^@([\w-]+)/,
select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
}
],
/**
* Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *= and %=.
* New operators can be added as long as the match the format <i>c</i>= where <i>c<i> is any character other than space, &gt; &lt;.
*/
operators : {
'=' : function(a, v){
return a == v;
},
'!=' : function(a, v){
return a != v;
},
'^=' : function(a, v){
return a && a.substr(0, v.length) == v;
},
'$=' : function(a, v){
return a && a.substr(a.length-v.length) == v;
},
'*=' : function(a, v){
return a && a.indexOf(v) !== -1;
},
'%=' : function(a, v){
return (a % v) == 0;
}
},
/**
* Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
* and the argument (if any) supplied in the selector.
*/
pseudos : {
'first-child' : function(c){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i];
if(!prev(ci)){
r[r.length] = ci;
}
}
return r;
},
'last-child' : function(c){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i];
if(!next(ci)){
r[r.length] = ci;
}
}
return r;
},
'nth-child' : function(c, a){
var r = [];
if(a != 'odd' && a != 'even'){
for(var i = 0, ci; ci = c[i]; i++){
var m = child(ci.parentNode, a);
if(m == ci){
r[r.length] = m;
}
}
return r;
}
var p;
// first let's clean up the parent nodes
for(var i = 0, l = c.length; i < l; i++){
var cp = c[i].parentNode;
if(cp != p){
clean(cp);
p = cp;
}
}
// then lets see if we match
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i], m = false;
if(a == 'odd'){
m = ((ci.nodeIndex+1) % 2 == 1);
}else if(a == 'even'){
m = ((ci.nodeIndex+1) % 2 == 0);
}
if(m){
r[r.length] = ci;
}
}
return r;
},
'only-child' : function(c){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i];
if(!prev(ci) && !next(ci)){
r[r.length] = ci;
}
}
return r;
},
'empty' : function(c){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i];
if(!ci.firstChild){
r[r.length] = ci;
}
}
return r;
},
'contains' : function(c, v){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
var ci = c[i];
if(ci.innerHTML.indexOf(v) !== -1){
r[r.length] = ci;
}
}
return r;
},
'checked' : function(c){
var r = [];
for(var i = 0, l = c.length; i < l; i++){
if(c[i].checked == 'checked'){
r[r.length] = c[i];
}
}
return r;
},
'not' : function(c, ss){
return Clipperz.YUI.DomQuery.filter(c, ss, true);
},
'odd' : function(c){
return this['nth-child'](c, 'odd');
},
'even' : function(c){
return this['nth-child'](c, 'even');
},
'nth' : function(c, a){
return c[a-1];
},
'first' : function(c){
return c[0];
},
'last' : function(c){
return c[c.length-1];
},
'has' : function(c, ss){
var s = Clipperz.YUI.DomQuery.select;
var r = [];
for(var i = 0, ci; ci = c[i]; i++){
if(s(ss, ci).length > 0){
r[r.length] = ci;
}
}
return r;
},
'next' : function(c, ss){
var is = Clipperz.YUI.DomQuery.is;
var r = [];
for(var i = 0, ci; ci = c[i]; i++){
var n = next(ci);
if(n && is(n, ss)){
r[r.length] = ci;
}
}
return r;
},
'prev' : function(c, ss){
var is = Clipperz.YUI.DomQuery.is;
var r = [];
for(var i = 0, ci; ci = c[i]; i++){
var n = prev(ci);
if(n && is(n, ss)){
r[r.length] = ci;
}
}
return r;
}
}
};
}();
/**
* Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Clipperz.YUI.DomQuery#select}
* @param {String} path The selector/xpath query
* @param {Node} root (optional) The start of the query (defaults to document).
* @return {Array}
* @member Ext
* @method query
*/
Clipperz.YUI.query = Clipperz.YUI.DomQuery.select;

View File

@@ -0,0 +1,93 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof YAHOO == 'undefined') { YAHOO = {}; };
if (typeof YAHOO.util == 'undefined') { YAHOO.util = {}; };
if (typeof YAHOO.util.Dom == 'undefined') { YAHOO.util.Dom = {}; };
YAHOO.extend = function(subc, superc, overrides) {
var F = function() {};
F.prototype=superc.prototype;
subc.prototype=new F();
subc.prototype.constructor=subc;
subc.superclass=superc.prototype;
if (superc.prototype.constructor == Object.prototype.constructor) {
superc.prototype.constructor=superc;
}
if (overrides) {
for (var i in overrides) {
subc.prototype[i]=overrides[i];
}
}
};
YAHOO.override = function(origclass, overrides){
if(overrides){
var p = origclass.prototype;
for(var method in overrides){
p[method] = overrides[method];
}
}
};
YAHOO.extendX = function(subclass, superclass, overrides){
YAHOO.extend(subclass, superclass);
subclass.override = function(o){
YAHOO.override(subclass, o);
};
if(!subclass.prototype.override){
subclass.prototype.override = function(o){
for(var method in o){
this[method] = o[method];
}
};
}
if(overrides){
subclass.override(overrides);
};
};
YAHOO.util.Dom.get = function(el) {
if (!el) { return null; } // nothing to work with
if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is
return el;
}
if (typeof el == 'string') { // ID
return document.getElementById(el);
}
else { // array of ID's and/or elements
var collection = [];
for (var i = 0, len = el.length; i < len; ++i) {
collection[collection.length] = YAHOO.util.Dom.get(el[i]);
}
return collection;
}
return null; // safety, should never happen
};