I am currently adding a feature to a genealogy website I am currently working on which is based on the Webtrees open source software.
So here is where I am at:
So originally, the software allows the user to press the individual node to expand/compress its content. And that works through the following code:
TreeViewHandler.prototype.expandBox = function(j, i) {
if (jQuery(i.target).hasClass("tv_link")) {
return !1
}
j = jQuery(j, this.treeview);
var p = j.parent(),
o = j.attr("abbr"),
n = this,
l, k;
if (p.hasClass("detailsLoaded")) {
k = p.find(".collapsedContent"), l = p.find(".tv_box:not(.collapsedContent)")
} else {
l = j;
k = j.clone();
p.append(k.addClass("collapsedContent").css("display", "none"));
var m = this.loadingImage.find("img").clone().addClass("tv_box_loading").css("display", "block");
j.prepend(m);
n.updating = !0;
n.setLoading();
j.load(n.ajaxUrl + "getDetails&pid=" + o, function() {
"function" === typeof CB_Init && CB_Init();
j.css("width", n.zoom / 100 * n.boxExpandedWidth + "px");
m.remove();
p.addClass("detailsLoaded");
n.setComplete();
n.updating = !1
})
}
j.hasClass("boxExpanded") ? (l.css("display", "none"), k.css("display", "block"), j.removeClass("boxExpanded")) : (l.css("display", "block"), k.css("display", "none"), l.addClass("boxExpanded"));
this.getSize();
return !1
};
What I'm trying to do is I'm trying to make the button I placed on the top left, which is to expand/compress ALL boxes in one click work. The one in showing/hiding females already work.
$(document).ready(function(){
var female = false
$(".tv_hidefemales").click(function(){
if (female == false) {
$(".tvF").hide();
female = true
} else {
$(".tvF").show();
female = false
}
});
$(".tv_expandCompress").click(function(){
tvHandler.expandBox($(".tv"), 0);
});
});
I figured that I can just take advantage of a looping jQuery .click() function.
Related
I am using the following code
(function(e, t) {
"use strict";
var n = t.selection;
var i = t.getSelection;
var o = i || n;
var r = function(e) {
var t = Object.prototype.toString.call(e);
return typeof e === "object" && /^\[object (HTMLCollection|NodeList|Object)\]$/.test(t) && e.hasOwnProperty("length") && (e.length === 0 || typeof e[0] === "object" && e[0].nodeType > 0)
};
var c = function(e, t) {
var n;
return function() {
var i = this,
o = arguments;
var r = function() {
n = null;
e.apply(i, o)
};
clearTimeout(n);
n = setTimeout(r, t)
}
};
var s = function(t, n) {
this.element = t;
this.callback = n || function() {};
this.isTouch = "ontouchstart" in e;
this.hasLib = e.jQuery && t instanceof e.jQuery || e.Zepto && t instanceof e.Zepto
};
s.prototype = {
events: function() {
var e = this.callback;
var t = this.getText;
this[this.isTouch ? "bindTouch" : "bindMouseUp"](function() {
e(t())
})
},
getText: function() {
var n = "";
if (i) {
n = e.getSelection().toString()
} else if (t.selection && t.selection.type !== "Control") {
n = t.selection.createRange().text
}
return n
},
checkForSelections: function(e, t, n) {
var i;
var o = function(e) {
var n = t();
var i = setInterval(function() {
if (t() !== n) {
e(t());
n = t()
} else if (t() === "") {
clearInterval(i)
}
}, 100)
};
var r = function() {
e.removeEventListener("touchend", c, false);
e.addEventListener("touchend", c, false);
if (i) {
clearInterval(i)
}
i = setInterval(function() {
var e = t();
if (e !== "") {
n(e);
c();
o(n)
}
}, 100)
};
var c = function() {
clearInterval(i);
e.removeEventListener("touchend", c, false)
};
e.addEventListener("touchstart", r, false)
},
bindTouch: function(e) {
var t = this.checkForSelections;
var n = this.getText;
if (this.hasLib) {
this.element.each(function() {
t(this, n, e)
});
return
}
var i = function(i) {
t(i, n, e)
};
if (!r(this.element)) {
i(this.element);
return
} [].forEach.call(this.element, function(e) {
i(e)
})
},
bindMouseUp: function(e) {
if (this.hasLib) {
this.element.on("mouseup", c(e, 150));
return
}
var t = function(t) {
t.addEventListener("mouseup", c(e, 150), false)
};
if (!r(this.element)) {
t(this.element);
return
} [].forEach.call(this.element, function(e) {
t(e)
})
}
};
e.selecting = function(e, t) {
if (!o) {
return
}
new s(e, t).events()
}
})(window, document);
And :
var myElement = document.body;
window.selecting(myElement, function(selector) {
var text = selector;
instance.publishState("text", text);
});
to basically get the selected/highlighted text by the user in the browser. I then use the selected text to work with it, make API calls etc.
Getting the selected text is fine, but unfortunately the number of lines in the returned text is usually incorrect which makes it impossible for me to work with.
Let me give you an example:
The user highlights the following text on the page:
Hello this is a test
Hello this is another test
The returned value from my code however than displays this text but with more line breaks in between. So for example I get returned:
Hello this is a test
Hello this is another test
This completely breaks my functionality, as I have to exactly know how many line breaks there actually are in order to work with the text. Any ideas what could be wrong or how I can access the browsers selected text with the correct number of line breaks?
The code
window.getSelection().toString()
will return the correct selection, which will produce in your case
Hello this is a test\n\nHello this is another test
Notice how you have two \n corresponding to the 2 newlines you have.
So if you do anything like this to display what the user has selected:
console.dir(window.getSelection().toString());
You will see correctly what the user has selected
Hello this is a test
Hello this is another test
By default there is no input in the site im visiting.
There is a script that runs and it is the only place where i am being able to find
<input type='file'/>
;
(function(e) {
var c = {};
c.fileapi = e("<input type='file'/>").get(0).files !== undefined;
c.formdata = window.FormData !== undefined;
e.fn.ajaxSubmit = function(g) {
if (!this.length) {
d("ajaxSubmit: skipping submit process - no element selected");
return this
}
var f, u, j, l = this;
if (typeof g == "function") {
g = {
success: g
}
}
f = this.attr("method");
u = this.attr("action");
j = (typeof u === "string") ? e.trim(u) : "";
j = j || window.location.href || "";
if (j) {
j = (j.match(/^([^#]+)/) || [])[1]
}
g = e.extend(true, {
url: j,
success: e.ajaxSettings.success,
type: f || "GET",
iframeSrc: /^https/i.test(window.location.href || "") ? "javascript:false" : "about:blank"
}, g);
var p = {};
this.trigger("form-pre-serialize", [this, g, p]);
if (p.veto) {
d("ajaxSubmit: submit vetoed via form-pre-serialize trigger");
return this
}
if (g.beforeSerialize && g.beforeSerialize(this, g) === false) {
Do you know how can i send_keys to that element? Is it complex?
I think you can still try to use send_keys on //input[#type='file']. It's a bit weird that they've included the entire JS function for their file upload logic, but not uncommon. The <input> element should accept key strokes regardless.
You might also need to execute some JS to potentially reveal the element if this is hidden -- this is optional, but if just send_keys doesn't work then this might help:
# locate file input
file_input = driver.find_element_by_xpath("//input[#type='file']")
# optional: JS to reveal the element
driver.execute_script("arguments[0].display = 'block';", file_input)
# send keys
file_input.send_keys("C:\Path\To\File")
I have a MultiSelectDropDown, that is, several RadComboBox controls are used in a combined way. For example, I can have a dropdown for regions, another for depots and another for user. The idea is to change the content of lower levels dynamically whenever items are selected or unselected on a higher level. The problem is that in the case when many items are selected, this becomes brutally slow due to some Telerik functions, but I do not understand why. This is a chunk from the client-side of the MultiSelectDropDown prototype:
changeLowerLevels: function (valueIndex, values, value) {
if (!this.canChange) return;
//Get selected values from combobox
var combo = $find(this.ddlIDs[valueIndex - 1]);
var cbItems = combo.get_checkedItems();
var selectedItems = [];
var change = null;
var counter = 0;
if (cbItems.length) this.filterString = "";
for (var i = 0; i < cbItems.length; i++) {
counter++;
if (this.filterString == "") this.filterString = cbItems[i].get_text();
selectedItems.push(cbItems[i].get_value());
}
if (counter > 1) this.filterString += " with " + (counter - 1) + " other" + ((counter > 2) ? "s" : "");
if (JSON.stringify(selectedItems) === JSON.stringify(this.selectedItems[valueIndex - 1]) || selectedItems == [])
return;
this.selectedItems[valueIndex - 1] = selectedItems;
var controlObject = this;
var combo = $find(this.ddlIDs[valueIndex]);
var comboItems = combo.get_items();
if(!this.disabled) combo.enable();
combo.clearItems();
if (valueIndex == 1) this.twoLevelCache = values;
var val = values;
//break if all items are found
var nrOfSelectedItems = this.selectedItems[valueIndex - 1].length;
var nrOfFoundItems = 0;
var index = 0;
var indexes = [];
var found = false;
while (nrOfFoundItems < nrOfSelectedItems && val[index] !== undefined) {
found = (this.selectedItems[valueIndex - 1].indexOf(val[index].Value) != -1);
if (!(found))
index++;
else {
indexes.push(index)
nrOfFoundItems++;
index++;
}
}
//separators from valuesIndex - 1 level
var controlObject = this;
for (var i = 0; i < indexes.length; i++) {
var separator = new Telerik.Web.UI.RadComboBoxItem();
separator.set_text("<span><a class=\"checkAll tt-multi-uncheck-icon\" index=\"" + index + "\">U</a>" + $find(this.ddlIDs[valueIndex - 1]).findItemByValue(val[indexes[i]].Value).get_text() + "</span>");
separator.set_value("");
separator.set_isSeparator(true);
comboItems.add(separator);
this.twoLevelCache.push(val[indexes[i]].Levels);
//valuesIndex level
var valuesArray = val;
var comboItem = new Telerik.Web.UI.RadComboBoxItem();
for (var depot in valuesArray[indexes[i]].Levels) {
comboItem = new Telerik.Web.UI.RadComboBoxItem();
comboItem.set_text(valuesArray[indexes[i]].Levels[depot].Name);
comboItem.set_value(valuesArray[indexes[i]].Levels[depot].Value);
comboItems.add(comboItem);
comboItem = null;
}
$('#' + this.ddlIDs[valueIndex] + '_DropDown a.checkAll').unbind().on("click", function () {
checkAllLowerItems(this, controlObject.ddlIDs[valueIndex]);
});
}
combo.set_emptyMessage(this.allText);
//$("#" + this.ddlIDs[valueIndex]).html(returnValue);
if (this.ddlIDs.length > valueIndex + 1) {
var paramToPass = (((val == undefined) || (val[index] === undefined)) ? ("") : (val[index]));
if (this.allText.length > 0)
this.changeLowerLevels(valueIndex + 1, paramToPass, "");
else {
if (paramToPass !== "")
paramToPass = paramToPass.Levels;
if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
this.changeLowerLevels(valueIndex + 1, paramToPass, "");
}
else {
this.changeLowerLevels(valueIndex + 1, paramToPass, val[index].Levels[0].Value);
}
}
}
else {
if (this.allText.length > 0)
this.selectedItems[valueIndex] = "";
else
if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
this.selectedItems[valueIndex] = "";
}
else {
this.selectedItems[valueIndex] = val[index].Levels[0].Value;
}
}
this.setText();
}
combo.clearItems() is extremeley slow. I have take a look on how it is implemented:
function (){var f=this._parent._getControl();?if(f._checkBoxes){f._checkedIndicesJson="[]";?f._checkedIndices=[];?var g=f.get_items();?for(var d=0,e=g.get_count();?d<e;?d++){var c=f.get_items().getItem(d);?c.set_checked(false);?}f.updateClientState();?}a.RadComboBoxItemCollection.callBaseMethod(this,"clear");?}
How can I make sure that this Javascript function speeds up?
I have finally solved the problem by rewriting Telerik client-side functionalities. It was a long and difficult debugging, but it yielded a large performance boost in the most difficult circumstances. From ~30 000 milliseconds, to ~300. Let's see the parts of the optimization:
The actual rewrite
/* Overriding Telerik functions Start */
var overridenTelerikControls = false;
function overrideTelerikFunctionalities() {
if (!overridenTelerikControls) {
overridenTelerikControls = true;
Telerik.Web.UI.RadComboBox.prototype.clearItems = function (isMultiSelectDropDown) {
this.get_items().clear(isMultiSelectDropDown);
this._itemData = null;
};
Telerik.Web.UI.RadComboBoxItemCollection.prototype.clear = function (isMultiSelectDropDown){
var f=this._parent._getControl();
if(f._checkBoxes){
f._checkedIndicesJson="[]";
f._checkedIndices=[];
var g = f.get_items();
for(var d=0,e=g.get_count();d<e;d++){
var c=f.get_items().getItem(d);
c.set_checked(false, isMultiSelectDropDown);
}
if (isMultiSelectDropDown) {
f._updateComboBoxText();
if (f._checkAllCheckBoxElement != null) {
f._updateCheckAllState();
}
}
f.updateClientState();
}
Telerik.Web.UI.RadComboBoxItemCollection.callBaseMethod(this, "clear");
};
Telerik.Web.UI.RadComboBoxItem.prototype.set_checked = function (d, isMultiSelectDropDown){
if(!this.get_enabled()){
return;
}
this._setChecked(d);
var c=this.get_comboBox();
if(c){
if(d){
c._registerCheckedIndex(this.get_index());
}else{
c._unregisterCheckedIndex(this.get_index());
}
if (!isMultiSelectDropDown) {
c._updateComboBoxText();
}
if((!isMultiSelectDropDown) && (c._checkAllCheckBoxElement!=null)){
c._updateCheckAllState();
}
}
};
}
}
/* Overriding Telerik functions End*/
My approach was to keep the old way of their working by default, but if an isMultiSelectDropDown parameter is passed, then work in the optimized manners. So we have a switch materialized as a parameter and we can turn it on/off. The main difference was that the old way was to change the label text showing the selected elements each time a checkbox is checked/unchecked. The main improvement was to do this change after all the checkboxes were checked/unchecked. This extremely simple idea was the driving force behind the boost of performance.
Actual usage
overrideTelerikFunctionalities();
combo.clearItems(true);
This was the functionalities were overriden if they were not already and the parameter was true, therefore the new approach was chosen.
Test, test, test
I am trying to modify MicrosoftAjaxWebForms.js file which is default ajax file of asp.net 4.5 and ASP.NET AJAX Control Toolkit version is 16.1.0.0
Here an example project to test out : https://github.com/FurkanGozukara/tempSite/
Open project and go to trialpage.aspx and click that button. You will see the error
Here the full MicrosoftAjaxWebForms.js : http://pastebin.com/pU3rBLKW
It also uses functions from MicrosoftAjax.js if you need that : http://pastebin.com/CPCm9BZy
What I want is, delaying the event _onFormSubmitCompleted
I have tried like below but it doesn't work.
MicrosoftAjaxWebForms.js:914 Uncaught TypeError: this._tempCompleted is not a function
It gives the error above
_onFormSubmitCompleted: function (c) {
console.log("_onFormSubmitCompleted");
setTimeout(function () {
this._tempCompleted(c);
}, 1111);
}, _tempCompleted: function (c) {
console.log("testcompleted");
this._processingRequest = true;
if (c.get_timedOut()) {
this._endPostBack(this._createPageRequestManagerTimeoutError(), c, null);
return
}
if (c.get_aborted()) {
this._endPostBack(null, c, null);
return
}
if (!this._request || c.get_webRequest() !== this._request) return;
if (c.get_statusCode() !== 200) {
this._endPostBack(this._createPageRequestManagerServerError(c.get_statusCode()), c, null);
return
}
var a = this._parseDelta(c);
if (!a) return;
var b, e;
if (a.asyncPostBackControlIDsNode && a.postBackControlIDsNode && a.updatePanelIDsNode && a.panelsToRefreshNode && a.childUpdatePanelIDsNode) {
var r = this._updatePanelIDs,
n = this._updatePanelClientIDs,
i = a.childUpdatePanelIDsNode.content,
p = i.length ? i.split(",") : [],
m = this._splitNodeIntoArray(a.asyncPostBackControlIDsNode),
o = this._splitNodeIntoArray(a.postBackControlIDsNode),
q = this._splitNodeIntoArray(a.updatePanelIDsNode),
g = this._splitNodeIntoArray(a.panelsToRefreshNode),
h = a.version4;
for (b = 0, e = g.length; b < e; b += h ? 2 : 1) {
var j = (h ? g[b + 1] : "") || this._uniqueIDToClientID(g[b]);
if (!document.getElementById(j)) {
this._endPostBack(Error.invalidOperation(String.format(Sys.WebForms.Res.PRM_MissingPanel, j)), c, a);
return
}
}
var f = this._processUpdatePanelArrays(q, m, o, h);
f.oldUpdatePanelIDs = r;
f.oldUpdatePanelClientIDs = n;
f.childUpdatePanelIDs = p;
f.panelsToRefreshIDs = g;
a.updatePanelData = f
}
a.dataItems = {};
var d;
for (b = 0, e = a.dataItemNodes.length; b < e; b++) {
d = a.dataItemNodes[b];
a.dataItems[d.id] = d.content
}
for (b = 0, e = a.dataItemJsonNodes.length; b < e; b++) {
d = a.dataItemJsonNodes[b];
a.dataItems[d.id] = Sys.Serialization.JavaScriptSerializer.deserialize(d.content)
}
var l = this._get_eventHandlerList().getHandler("pageLoading");
if (l) l(this, this._getPageLoadingEventArgs(a));
Sys._ScriptLoader.readLoadedScripts();
Sys.Application.beginCreateComponents();
var k = Sys._ScriptLoader.getInstance();
this._queueScripts(k, a.scriptBlockNodes, true, false);
this._processingRequest = true;
k.loadScripts(0, Function.createDelegate(this, Function.createCallback(this._scriptIncludesLoadComplete, a)), Function.createDelegate(this, Function.createCallback(this._scriptIncludesLoadFailed, a)), null)
},
How should i modify the entire javascript or that function to add a custom delay feature?
So i can delay the client update at the client side as i wish after the postback is completed
Here my bounty having related question : How to defer the update at the client side after async postback in updatepanel
Hi All,
I need help customizing this jquery plugin so that the pagination looks like links with text in them instead of like the default.
So basically the output on the page should be: Link1 | Link2 | Link3,etc. I have tried creating an Array and returning that Array to the addPaginationItem() function, however, all attempts have been very unsuccessful.
Any help would be much appreciated as I have been struggling with it.
2 main functions Code that I need to manipulate looks as follows:
addPaginationItem = function(i) {
if (!(i >= 0)) {
i = _this.size() - 1;
}
return $pagination.append($("<a>", {
href: "#" + i,
"class": _this.current === $pagination.children().length ? "current" : void 0
}));
};
addPagination = function() {
var array, last_index;
if (!_this.options.pagination || _this.size() === 1) {
return;
}
if ($(el).find("." + _this.options.classes.pagination).length) {
last_index = $pagination.children().last().index();
array = $children;
} else {
last_index = 0;
array = new Array(_this.size() - last_index);
$pagination = $pagination.appendTo(_this.el);
}
return $.each(array, function(i) {
return addPaginationItem(i);
});
};
Thanks
I have solved my own problem. I think I just needed to walk away from the code for a bit.
Thanks all. I added the following code which solved my problem
addPaginationItem = function(i,linkText) {
if (!(i >= 0)) {
i = _this.size() - 1;
}
return $pagination.append($("<a>", {
href: "#" + i,
text:linkText,
"class": _this.current === $pagination.children().length ? "current" : void 0
}));
};
addPagination = function() {
var array, last_index;
var hrefText = ['test1','test2','test3','test4'];
if (!_this.options.pagination || _this.size() === 1) {
return;
}
if ($(el).find("." + _this.options.classes.pagination).length) {
last_index = $pagination.children().last().index();
array = $children;
} else {
last_index = 0;
array = new Array(_this.size() - last_index);
$pagination = $pagination.appendTo(_this.el);
}
$.each(hrefText,function(intIndex,objValue) {
linkText = objValue;
return addPaginationItem(intIndex,linkText)
});
};