Different jQuery UI behavior in different browsers - javascript

I have a very simple calendar. When clicking any date a jQuery dialog gets opened, the user clicks a button, the dialog closes, the clicked button's value gets appended to the clicked element and after that all clicked elements get saved to an array.
I have created a JSBin.
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
Click me
<div id="dialog"></div>
<link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</body>
</html>
js:
$('.cal_clean_active').click(function(e) {
var that = $(this);
var dates = new Array();
that.toggleClass('clicked');
$('#dialog').dialog({
resizable: false,
height: "auto",
width: "auto",
modal: true,
buttons: {
"Vormittags (bis 12:00 Uhr)": function() {
that.attr('slot','vormittags');
console.log(that.attr('slot'));
$(this).dialog('close');
}
},
beforeClose: function() {
$('.clicked').each(function(i, val) {
dates.push(val.id + '|' + val.slot);
});
console.log(dates);
}
});
});
In Chrome everything works as expected (Console output is 2016-11-01|vormittags) in every other tested Browser (Firefox, Edge, IE) the console output is 2016-11-01|undefined. Any help would be appreciated.

The problem is that slot is not a standard attribute for an element. In most browsers, it is hence not included in the standard properties of an element (like element.value or element.id). Chrome seems to handle this situation differently than the other browsers.
Two bad solutions
A solution would be to change:
dates.push(val.id + '|' + val.slot);
to
dates.push(val.id + '|' + $(val).attr('slot'));`.
Another - plain javascript - solution could be to use the javascript getAttribute() method. This would work because in the jQuery source code custom attributes are set with this line:
elem.setAttribute( name, value + "" ); //from the jQuery source code
Thus making it possible to also read them with element.getAttribute(). Your line would then look like this:
dates.push(val.id + '|' + val.getAttribute("slot"));
The better solution
This might all work, but it still is not considered good code. In your code the attribute slot is used to store data. From the .data() jQuery docs (see this answer):
Store arbitrary data associated with the specified element. Returns the value that was set.
$.attr() on the contrary is used to manipulate attributes, like id, value or type. The clean way of solving this problem would be:
$('.cal_clean_active').click(function(e) {
var that = $(this);
var dates = new Array();
that.toggleClass('clicked');
$('#dialog').dialog({
resizable: false,
height: "auto",
width: "auto",
modal: true,
buttons: {
"Vormittags (bis 12:00 Uhr)": function() {
that.data('slot','vormittags'); //Not the use of data
console.log(that.data('slot'));
$(this).dialog('close');
}
},
beforeClose: function() {
$('.clicked').each(function(i, val) {
dates.push(val.id + '|' + $(val).data("slot")); //Also note it here
});
console.log(dates);
}
});
});

Related

Handsontable RuleJS missing recursive resolution

I use RuleJS plugin for Handsontable (see it on GitHub) which works great for basic formulas but seems to lack recursive resolution.
I've made a code snippet containing two detailed examples, please check it out :
$(document).ready(function () {
var container1 = $('#example1');
var container2 = $('#example2');
container1.handsontable({
data: [[1, '=A2'], ['=B2', '=5 * 2']],
colHeaders: true,
rowHeaders: true,
formulas: true,
minSpareRows: 1
});
container2.handsontable({
data: [[1, '=A2', 3], ['=C1 * B2', '=5 + 1', 3]],
colHeaders: true,
rowHeaders: true,
formulas: true,
minSpareRows: 1
});
});
<!DOCTYPE html>
<html>
<head>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/jquery/jquery-1.10.2.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.css">
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/lodash/lodash.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/underscore.string/underscore.string.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/moment/moment.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numeral/numeral.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numericjs/numeric.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/js-md5/md5.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/jstat/jstat.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/formulajs/formula.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/parser.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/ruleJS.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.formula.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.github.io/handsontable-ruleJS/css/samples.css">
<style type="text/css">
body {background: white; margin: 20px;}
h2 {margin: 20px 0;}
</style>
</head>
<body>
<h2>Bugs in handsontable-ruleJS</h2>
<p>Both cases seem to come from the same problem, but they both worth seeing.</p>
<p>Here B1 displays the value of B2 <b>before</b> its interpretation where it should display "<b>10</b>". Just like it misses some recursive processing. Focusing the cell will show its real value "<b>=A2</b>" which will next be interpreted correctly.</p>
<div id="example1" class="handsontable"></div>
<p>This one is interesting, because when the cell "<b>A2</b>" tries to calculate "<b>C1 * B2</b>" it does "<b>3 * =5 + 1"</b> instead of "<b>3 * 6</b>", which obviously fails.</p>
<div id="example2" class="handsontable"></div>
<p>The only way to correct it is to edit "<b>C1</b>" (even without changing its value).</p>
</body>
</html>
If you prefer JSFiddle, here you go.
Best regards.
Edit: You may not see the first bug when using the embed snippet and going to fullscreen because it seems to trigger a refresh of the table. Use the JSFiddle for better results.
Edit 2 (SOLVED): Ok I think I've patched it, you can find the result here. I'll post a complete answer when Stackoverflow allows me to do it. Any feedback is still welcome, I'm sure there is a better way to do it but at least it seems to work now.
The working code can be found here : http://jsfiddle.net/71o23gp0/8/.
The important part was to replace :
var custom = {
cellValue: instance.getDataAtCell
};
By
var custom = {
cellValue: function(row, col){
var value = instance.getDataAtCell(row, col);
if (value && value[0] === '=') {
var formula = value.substr(1).toUpperCase();
var cellId = instance.plugin.utils.translateCellCoords({
row: row,
col: col
});
var item = instance.plugin.matrix.getItem(cellId);
if (!item) {
item = instance.plugin.matrix.addItem({
id: cellId,
formula: formula
});
} else {
item = instance.plugin.matrix.updateItem({
id: cellId,
formula: formula
});
}
var formulaResult = instance.plugin.parse(formula, {
row: row,
col: col,
id: cellId
});
value = formulaResult.result || '#ERROR';
formulasResults[cellId] = value;
instance.plugin.matrix.updateItem(item, {
formula: formula,
value: formulaResult.result,
error: formulaResult.error
});
}
return value;
}
};
Instead of simply returning the value of the cell, it checks if it's a formula and resolve it if so. Because this method is called by RuleJS when resolving a formula, this make the resolution recursive. The result is then cached for better performance.
There are other minor modifications in the source code, but I've added comments in the fiddle before and after every modification.
Following on from the answer https://stackoverflow.com/a/35528447/489865 in this question, I have patched a little further. The working code can be found at http://jsfiddle.net/ufL1vts5/.
The essential change is to store in formulasResults[] not just the "result" but rather the whole object returned by instance.plugin.parse(), so that cell highlighting for formulas is picked up, as per:
// parse formula
var newValue = instance.plugin.parse(formula, {row: row, col: col, id: cellId});
// cache result
formulasResults[cellId] = newValue;
My modifications include:
Store whole instance.plugin.parse() object in formulasResults[],
so that the formula/formula-error CSS style gets applied. [Note
that this is not perfect: it picks up "calculated" formula style
correctly, but sometimes what should be formula-error style only
get formula style --- but sufficient for my needs.]
Added formula & formula-error CSS styles (from supplied
handsontable.formula.css) into JSFiddle example, so that cell
highlighting can be seen.
Added 2 extra examples: one from
handsontable formula returning #NEED_UPDATE,
to show that works too, and one from the example supplied with
handsontable-ruleJS at https://github.com/handsontable/handsontable-ruleJS/blob/master/index.html.
Removed the newly added beforeRender hook via
instance.removeHook('beforeRender', beforeRender); in this.init = function ().
Changed some code layout in handsontable.formula.js, so that it
minimises the differences from that supplied with
handsontable-ruleJS.

making jQuery Dialog to wait for post back or JavaScript prompt allowing custom html

I want to prompt the user with possible values (which I've got stored in JavaScript array ) to be displayed as radio buttons to choose if some value in text-box is left empty and user clicks on 'Save' telerik's Rad Ribbon Bar button laying in master page.
My problem is, when I click on Save, the server side method does not
wait for the jQuery UI Dialogue to close, I tried a while loop saying
wait here till the dialogue box disappears but that spiked abruptly & hung up my page :-(
For my scenario, we're importing data from other application so, can;t use the on change event
We'e the requirement : While saving prompt the box with available values, get the selected value and continue saving with selected value, so I can not add a button, hide it and trigger .click() event
my client may not welcome "return false;" they just want to continue saving
I've got following working
Client side event handler gets called from content page when save button is called
the above JavaScript function checkes if value is empty
Getting available values from server side and storing in array
creating html and on the fly (code below)
Code Snippet 1 ( to declaring div for jQuery UI dialogue in content page)
<script src="../Scripts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="../Scripts/JQueryUI/js/jquery-ui-1.10.3.min.js" type="text/javascript"></script>
<link href="../Scripts/JQueryUI/css/smoothness/jquery-ui.min.css" rel="stylesheet"
type="text/css" />
<link href="../Scripts/JQueryUI/css/smoothness/jquery.ui.theme.css" rel="stylesheet" type="text/css" />
<div id="dialog-confirm" title="Tracking #">
<span style="float: left; margin: 0 7px 20px 0; z-index: 999999 !important"></span>
<p>
</p>
</div>
Code Snippet 2 ( fires client side function when Click event triggers on Save )
function onSave(sender, args) {
var sButtonText = args.get_button().get_text();
if (sButtonText == "Save") {
var
trackingIDs = $('#<%=_tbPrevtrackerID.ClientID %>').val(),
$trackerIDInputControl = $('#<%= tbtrackerID.ClientID %>'),
currenttrackerIDValue = $trackerIDInputControl.val(),
trackerIDs = trackingIDs.split(',').clean(''), //Extension Method
noOftrackerIDsAvailable = trackerIDs.length,
markup = 'trackerID is empty : <br/><br/><input type="radio" name="trackerIDGroup" value="" >Leave Empty</input><br/>';
for (var i = 0; i < noOftrackerIDsAvailable; i++) {
markup += '<input type="radio" name="trackerIDGroup" value="' + trackerIDs[i] + '">' + trackerIDs[i] + '</input><br/>';
}
if (currenttrackerIDValue == '') {
$('#dialog-confirm').css({ 'display': 'block' });
$("input:radio[name=trackerIDGroup]").click(function () {
$trackerIDInputControl.val($(this).val());
trackerIDChecked = true;
});
//Please note, if I'd use following it does work, but I am going to have multiple values
//$trackerIDInputControl.val(prompt(markup, trackerIDs[0]));
if ($("#dialog-confirm") != null) {
$("#dialog-confirm p").html(markup);
$("#dialog-confirm").dialog({
resizable: false,
height: 300,
width: 300,
closeOnEscape: false,
modal: false,
buttons: {
"Ok": function () {
if ($trackerIDInputControl.val() != '') {
$('#dialog-confirm').css({ 'display': 'none' });
$(this).dialog("close");
}
},
Cancel: function () {
$(this).dialog("close");
$('#dialog-confirm').css({ 'display': 'none' });
}
}
}).parent().appendTo(jQuery("body form"));
}
}
}
I think Ajax Control Tool kit has something more suitable for you, please have a look at this demo.

Using jQuery replaceWith on html elements

I'm writing an MVC application and on one page I need to dynamically give an ID to all the elements because of the way the table is rendered and how data is passed to an from it. When I run this, all the elements are replaced with , however it is removing the content in between the tags. Is there any way to make it only replace the starting tag and not touch the rest, or another jQuery function to do this? My code is below:
<script type="text/javascript" charset="utf-8">
$(document).ready(function () {
var oTable1 = $('#example1').dataTable({
sScrollX: "100%",
sScrollY: "200px",
bFilter: false,
bScrollCollapse: true,
bPaginate: false,
bScrollInfinite: true,
iScollLoadGap: 10,
oLanguage: {
sZeroRecords: "There are no records that match your search criterion",
}
}).makeEditable({ sUpdateURL: "/Home/UpdateData" });
});
</script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function () { var editChange = $('td').replaceWith('<td id = "#Html.ValueFor(x => x.name)" >'); });
</script>
Any help is appreciated.
Instead of using replaceWith may I suggest the use of another function, the function .attr() that is meant to replaced the attributes of an element.
$('td').attr('id','#Html.ValueFor(x => x.name)');
Also, be careful because the ASP values will not be available once in the client side. Your selector $('td') is pretty general, and IDS must be unique.
Try explicitly setting the id on the TD element(s)
$('td').each(function() {
this.id = #Html.ValueFor(x => x.name);
});

Transfer pop up HTML content inside JS file

I have this working pop up HTML code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">
<title>PopUp</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all" href="style.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.popup.min.js"></script>
<script type="text/javascript">
jQuery(function () {
jQuery().popup();
});
</script>
</head>
<body>
Show popup
<div id="popup-box">
This is the pop up content. The quick brown fox jumps over the lazy dog.
</div>
</body>
</html>
The actual pop up content is inside the:
<div id="popup-box">
</div>
Is it possible to transfer the pop up HTML content (..) to my JS file? Actually inside the jQuery function click event? Example:
jQuery( document ).ready( function($) {
$('#triggerforpopup').live('click',(function() {
//launch the pop code to HTML
}));
});
So after the click event, the JS will simply pop it out, but it's originating inside the JS file not an HTML hidden on an existing content.
The reason is that I'm writing a Wordpress plugin and it would be convenient to have all this information in a JS file. I don't want putting additional HTML code in the existing template content which is hidden by default.
Thanks for helping.
UPDATE: I have created a fiddle for this one here: http://jsfiddle.net/codex_meridian/56ZpD/3/
(function (a) {
a.fn.popup = function (b) {
var c, d = [self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop];
a("body").append(c = a('<div id="popup-overlay"></div>')), _init = function () {
_add_overlay(), _add_buttons(), a("#popup-box #popup-content").css("max-height", a(window).height() - 400), a(window).on("resize", function () {
a("#popup-box #popup-content").css("max-height", a(window).height() - 400)
})
}, _add_overlay = function () {
c.css({
opacity: .85,
position: "absolute",
top: 0,
left: 0,
width: "100%",
"z-index": 99999,
display: "none",
height: a(document).height()
})
}, _show_overlay = function () {
c.is(":visible") || c.fadeIn("fast")
}, _hide_overlay = function () {
c.is(":visible") && c.hide()
}, _add_buttons = function () {
a("a[rel=popup-close]").click(function () {
return _hide_box(), !1
}), a("a[rel=popup-open]").click(function () {
return _show_box(), !1
})
}, _show_box = function () {
if (!a("#popup-box").is(":visible")) {
_show_overlay(), a("#popup-box").fadeIn("fast");
var b = a("html");
b.data("scroll-position", d), b.data("previous-overflow", b.css("overflow")), b.css("overflow", "hidden"), window.scrollTo(d[0], d[1])
}
}, _hide_box = function () {
if (a("#popup-box").is(":visible")) {
var b = a("html"),
c = b.data("scroll-position");
b.css("overflow", b.data("previous-overflow")), window.scrollTo(c[0], c[1]), _hide_overlay(), a("#popup-box").hide()
}
}, _init()
}
})(jQuery)
You can write your content directly in your JS as a string and then use the innerHTML property of elements to set their value. You can do this in pure JS as follows.
var popup = document.getElementById("popup-box");
var html = "This is the pop up content. The quick brown fox jumps over the lazy dog.";
popup.innerHTML = html;
And you can do this in jQuery as follows:
$('#triggerforpopup').on('click', function() {
$("#popup-box").html(html); // Where html is a variable containing your text.
});
Note: You can write in HTML tags and the like in your html string and they will be rendered as you would expect on the page. You are not limited to plaintext.
Note: live has been deprecated in jQuery as of jQuery 1.7. It has been replaced with on. See http://api.jquery.com/live/ and http://api.jquery.com/on/.
If you want to include everything in the JavaScript as mentioned in the comments, you can do this:
var popup = document.createElement("div");
popup.id = "popup-box";
popup.innerHTML = "your html here";
document.getElementById("parent element id").appendChild(popup);
What this does is create a new div element, set its id and then append it as the child element of the parent of your choice. You could just do a plain insert of the HTML string into another element, but by creating an element here you have a bit more flexibility regarding its placement.
use
var popupHtml = $('<div>This is the pop up content. The quick brown fox jumps over the lazy dog.</div>');
popupHtml.popup();
I found lots of issues in the popup plugin you have used. Fixed them to make it working. Have a look http://jsbin.com/oyamiy/6/watch

Google Custom Search on submit

I would like to customize my search form. I am using Google Search Service and have it linked to my domain and so on.
I chose the two column layout in the Control Panel, but however, I want to do something onSubmit of the form.
So I tried to put an actionlistener in jQuery into the form, however does not work.
Then I thought google certainly provides something for that. And yes they do. It is called:
setOnSubmitCallback()
http://code.google.com/apis/websearch/docs/reference.html
Unfortunately I dont get it.
So far I have:
google.load('search', '1', {language : 'en', style : google.loader.themes.MINIMALIST});
function initialize()
{
var searchControl = new google.search.CustomSearchControl('017998360718714977594:j6sbtr-d6x8');
searchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
var options = new google.search.DrawOptions();
options.setSearchFormRoot('cse-search-form');
searchControl.draw('cse', options);
}
google.setOnLoadCallback(initialize);
So i have two divs:
#cse-search-form for the form and #cse for the results
#cse is in another div #searchResults, that is hidden and here it comes:
I want to open #searchResults in a dialog from jQuery UI.
$("#searchResults").dialog( { minWidth: 750, minHeight: 750 } );
Which will result into:
.setOnSubmitCallback(function() {
$("#searchResults").dialog( { minWidth: 750, minHeight: 750 } );
} );
So my problem now is, where and on what do I have to put the setOnSubmitCallback?
I cannot put it on google.search.Search or CustomSearchControl as it is stated in the documentation. ANd I cannot call it in the onLoadCallback so it is very strange for me. Cannt figure out how to do that.
I hope somebody has some more experience for the google search and could help me out with a solution.
Thank you very much in advance.
NOTE: the code below is using something Google deprecated. Use this instead: http://code.google.com/apis/customsearch/v1/overview.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Hello World - Google Web Search API Sample</title>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<script src="https://www.google.com/jsapi" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
//<![CDATA[
google.load('search', '1');
google.load("jquery", "1.5.2");
google.load("jqueryui", "1.8.12");
function OnLoad() {
var searchComplete = function(searchControl, searcher){
$('#searchResults').dialog({modal: true, width: 700, height: 400, position: [50, 50]});
for (result in searcher.results) {
var content = searcher.results[result].content;
var title = searcher.results[result].title;
var url = searcher.results[result].url;
$('#searchResults ul')
.append($('<li></li>')
.append($('<a/>').attr('href', url).text(title))
.append($('<p/>').text(content)));
}
};
// called on form submit
newSearch = function(form) {
if (form.input.value) {
// Create a search control
var searchControl = new google.search.SearchControl();
// Add in a set of searchers
searchControl.addSearcher(new google.search.WebSearch());
searchControl.addSearcher(new google.search.VideoSearch());
// tell the searchControl to draw itself (without this, the searchComplete won't get called - I'm not sure why)
searchControl.draw();
searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
searchControl.setSearchCompleteCallback(this, searchComplete);
searchControl.execute(form.input.value);
}
return false;
}
// create a search form without a clear button
// bind form submission to my custom code
var container = document.getElementById("searchFormContainer");
this.searchForm = new google.search.SearchForm(false, container);
this.searchForm.setOnSubmitCallback(this, newSearch);
}
google.setOnLoadCallback(OnLoad);
//]]>
</script>
</head>
<body>
<div id="searchFormContainer">Loading</div>
<div id="searchResults" title="Search Results">
<ul></ul>
</div>
</body>
</html>

Categories

Resources