This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyforks.org/scripts/20131/128690/html-utils.js
// extend HtmlFactory
var HtmlFactoryExtension = (function() {
/**
* Creates a 'button' Html Element.
* The initial class attribute is <code>class='smallbutton'</code>.
* @param {function} [callback] - The callback function for the <code>onClick<code> event
* @param {string} [text] - The content text of the element (text shown on the button)
* @param {string} [id] - The value for the <code>id</code> attribute
* @returns {ElType} The 'button' HTML element
*/
var createButtonSmall = function(callback, text, id) {
return HtmlFactory.newButton('smallbutton', callback, text, id);
};
/**
* Creates a 'button' Html Element.
* The initial class attribute is <code>class='tinybutton'</code>.
* @param {function} [callback] - The callback function for the <code>onClick<code> event
* @param {string} [text] - The content text of the element (text shown on the button)
* @param {string} [id] - The value for the <code>id</code> attribute
* @returns {ElType} The 'button' HTML element
*/
var createButtonTiny = function ButtonTiny(callback, text, id) {
var elBtn = HtmlFactory.newButton('tinybutton', callback, text, id);
elBtn.style = 'margin:0;padding:0;width:auto;';
return elBtn;
};
/**
* Creates a 'Select' HTML element for selecting camamba users.
* The options will be generated by the list of users.
* The initial class attribute is <code>class='smallselect'</code>.
* @param {Object<string, User>[]} users - The list of users shown as options
* @param {string} [id] - The value for the <code>id</code> attribute
* @returns {ElType} The 'select' HTML element
*/
var createSelectUsers = function(users, id) {
var elSelect = HtmlFactory.newSelect('smallselect', id);
var _onchangeCallback;
/**
* Returns the user of the selected option
* @returns {User} The current selected user
*/
elSelect.getSelectedUser = function() {
return elSelect.options[elSelect.selectedIndex].user;
};
/**
* Sets a callback function triggered by the events <code>OnChange</code>, <code>OnKeyUp</code> and <code>OnFocus</code>.
* Removes any former callback function registered to these events.
* @param {function} callback
*/
elSelect.setOnChangeKeyUpFocus = function(callback) {
if (_onchangeCallback) {
elSelect.removeEventListener("focus", _onchangeCallback);
elSelect.removeEventListener("change", _onchangeCallback);
elSelect.removeEventListener("keyup", _onchangeCallback);
}
if (typeof callback === 'function') {
_onchangeCallback = callback;
elSelect.addEventListener("focus", callback);
elSelect.addEventListener("change", callback);
elSelect.addEventListener("keyup", callback);
}
};
/**
* The options will be regenerated by the list of users.
* @param {Object<string, User>[]} users - The list of users shown as options
*/
elSelect.updateUsers = function(users) {
var sortUsers = [];
var remainingUsers = {};
for (var i = 0; i <= elSelect.length - 1; i++) {
var userInSelect = elSelect[i].user;
if (!users[userInSelect.uid]) { // deleted users
elSelect.remove(i);
} else { // remaining users
remainingUsers[userInSelect.uid] = true;
sortUsers.push({ user:userInSelect, selected:elSelect[i].selected });
}
}
Object.keys(users).forEach(function(uid){
if (!remainingUsers[uid]) { // additional users
var user = users[uid];
sortUsers.push({ user:user, selected:false });
/**
* Html 'Option' Child of a Html 'Select' Element that holds a User
* @type {HTMLOptionElement}
* @property {User} user - The User related to the option
*/
elSelect.add(document.createElement('OPTION'));
}
});
elSelect.length = sortUsers.length;
sortUsers.sort(function (a, b) {
if (a.user.uname < b.user.uname) { return -1; }
if (a.user.uname > b.user.uname) { return 1; }
return 0;
});
sortUsers.forEach(function (opt, i) {
elSelect[i].text = opt.user.uname;
elSelect[i].value = opt.user.uid;
elSelect[i].user = opt.user;
elSelect[i].selected = opt.selected;
});
};
elSelect.updateUsers(users);
return elSelect;
};
return {
newButtonSmall : createButtonSmall,
newButtonTiny : createButtonTiny,
newSelectUsers : createSelectUsers
}
})();
Object.keys(HtmlFactoryExtension).forEach(function (propName) {
HtmlFactory[propName] = HtmlFactoryExtension[propName];
});
//extend Page
var PageExtension = (function() {
var isGerman = window.location.hostname.indexOf("de.camamba.com") >= 0;
var uriRoute = /^\/(.+?)(?:_de)?\.php.*/g.exec(location.pathname)[1];
/**
* Verifies an uri, if it loads the German version of camamba.
* @param {string} uri The uri for a camamba Page.
* @returns {boolean} <code>true</code> if the uri will request a camamba Page in German.
*/
var uriIsGerman = function(uri) {
return (uri.indexOf('www.de.camamba.com') >= 0);
};
/**
* Transforms the uri of a camamba Page wether to request that Page in English or German, depending the language of the current Page.
* @param {string} uri - The uri for a cammaba Page.
* @param {Object.<string,string>[]} [queryParamsObj] - A key-value Object for additional query parameter to be attached to the uri.
* @returns {string} The localized uri
*/
var uriLocalized = function(uri, queryParamsObj) {
var localizedUri = uri;
if (isGerman && !uriIsGerman(uri)) {
localizedUri = uri
.replace("www.camamba.com", "www.de.camamba.com")
.replace(".php", "_de.php");
} else if (!isGerman && uriIsGerman(uri)) {
localizedUri = uri
.replace("www.de.camamba.com", "www.camamba.com")
.replace("_de.php", "php");
}
var queryParams = '';
if (queryParamsObj) {
var hasParams = uri.indexOf('.php?') >= 1;
Object.keys(queryParamsObj).forEach(function (key) {
var sep = (hasParams ? '&' : '?');
var value = queryParamsObj[key];
queryParams += sep + key + '=' + value;
hasParams = true;
});
}
return localizedUri + queryParams;
};
return {
/**
* Indicates the localization of the current camamba Page.
* @returns {boolean} <code>true</code> if the current Page is in German
* <code>false</code> the current Page is in English
*/
isGerman : isGerman,
/**
* The current path in camamba according to the uri.
* @returns {string} The current path.
*/
route : uriRoute,
localizeUri : uriLocalized
};
})();
Object.keys(PageExtension).forEach(function (propName) {
Page[propName] = PageExtension[propName];
});
/**
* @name uidType
* @type string|number
*/
/**
* Represents a camamba user.
* Intitially tries to load the User from the database that has the given uid.
* @constructor
* @param {uidType} uid Identifies the User with its camaba uid.
*/
function User(uid) {
var _uid = parseInt(uid, 10); // camamba user ID (readonly)
var _key = 'uid' + _uid, // key for storing (readonly)
_uname = "", // camamba username
_name = "", // custom username
_note = "", // custom annotation
_hasChanged = true; // is any value is unsaved (readonly)
/**
* @name User#uid
* @type number
* @readonly
*/
/**
* @name User#key
* @type String
* @readonly
*/
/**
* @name User#hasChanged
* @type Boolean
* @readonly
*/
/**
* @name User#note
* @type String
*/
Object.defineProperties(this, {
uid : { value : _uid, writable : false },
key : { value : _key, writable : false },
hasChanged : { get : function() { return _hasChanged; } },
uname : {
get : function() { return _uname; },
set : function(val) {
if (_uname != val) {
_uname = val;
_hasChanged = true;
}
}
},
name : {
get : function() { return _name || _uname || _uid.toString(); },
set : function(val) {
if (_name != val) {
_name = val;
_hasChanged = true;
}
}
},
note : {
get : function() { return _note; },
set : function(val) {
if (_note != val) {
_note = val;
_hasChanged = true;
}
}
}
});
/**
* Saves or updates the user in the database of this script.
* Overwrites an existing entry or creates a new entry if it doesn't alread exist.
*/
this.save = function() {
User.prototype.save.call(this);
_hasChanged = false;
};
/**
* Loads the User from the database of this script.
* @returns {Boolean} <code>true</code> if the user was found and could be sucessfully loaded from db
*/
this.load = function() {
var isSuccess = User.prototype.load.call(this);
if (isSuccess) {_hasChanged = false; }
return isSuccess;
};
/**
* Removes the User from the database of this script.
*/
this.remove = function () {
User.prototype.remove.call(this);
_hasChanged = true;
};
this.load();
}
User.prototype = {
constructor : User,
save : function() {
if (this.hasChanged) {
GM_setValue("uid" + this.uid, JSON.stringify({
uname : this.uname,
name : this.name,
note : this.note
}));
}
},
load : function() {
var isScuccess = false;
var loadedString = GM_getValue("uid" + this.uid);
if (loadedString) {
var loadedObj = JSON.parse(loadedString);
var uname = loadedObj.uname;
var name = loadedObj.name;
var note = loadedObj.note;
if (uname !== undefined && name !== undefined && note !== undefined){
this.uname = uname;
this.name = name;
this.note = note;
isScuccess = true;
}
}
return isScuccess;
},
remove : function() {
GM_deleteValue("uid" + this.uid);
},
/**
* Gets all users stored from the database determined for this Script.
* @returns {{}<uidType,User>[]} List with all Stored Users
*/
loadAllUsers : function() {
var users = {};
var storedKeys = GM_listValues();
for (var i = 0; i <= storedKeys.length - 1; i++) {
var key = storedKeys[i].toString();
if (key.indexOf('uid') === 0) {
var uid = key.substr(3);
users[uid] = new User(uid);
}
}
return users;
},
/**
* Has the browser open the profile Page of this user.
* @param {boolean} [asNewTab=false]
* <code>true</code>, Page is opened in a new tab.
* <code>false</code>, replaces the current Page.
*/
openProfilePage : function (asNewTab) {
var profPageLocPath = location.protocol + '//www.camamba.com/profile_view.php';
var queryParamsObj = { uid : this.uid, m : 'start' };
var uri = Page.localizeUri(profPageLocPath, queryParamsObj);
var target = asNewTab ? '_blank' : '_self';
window.open(uri, target);
}
};