jquery ui dialog loses values on second call (IE8) - jquery-ui

I have a page which has 16 buttons. When clicked a dialog opens and a user can select various select elements (an item, an operator, and a value).
This works great in FF but not so good in IE8.
User clicks button 1, enters data, closes the dialog (FF, IE8 Good)
User clicks button 2, enters data, closes the dialog (FF, IE8 Good)
User clicks button 2 again, enters data, closes the dialog (FF Good), (IE8 fails)
The problem only happens if a user clicks the same button in succession (note two instances are not opened both at the same time: user clicks button 2, processes it, closes it then clicks button 2 a few moments later).
The problem is to do with the script losing the form values.
When the button is clicked the following vars are set:
var item = $("#name-item"),operator = $("#name-operator")
item will be something like "-tNAME", operator something like "eq="
on the second run $("#name-item") and $("#name-operator") are blank so this sounds like a declaration / initialization problem but where?
dialog code:
$("#dialog-form-name").dialog({autoOpen:false,height:450,width:350,modal:false,position:[675,200],buttons: {
'Add Name Filter': function() {
var item = $("#name-item"),operator = $("#name-operator"),value = $("#name-value"),disp=$('#name-item option:selected').text(),join = $("#name-join"),tn = $("#name-item").val().substr(0,2);
var allFields = $([]).add(item).add(operator).add(value).add(join),tips = $(".validateTips"),bValid = true;
allFields.removeClass('ui-state-error');
bValid = bValid && checkLength(value,"value",1,255);
bValid = bValid && checkRegexp(value,/^([\ \.\,\'\(\)0-9a-z_])+$/i,"Value may consist of a-z, 0-9, underscores, commas, spaces");
if(bValid) { updateTableRow('name',item,operator,value,join,disp,tn);$(this).dialog('close'); }
},
Cancel: function() { if(form_status == 'edit') { form_status = 'new';$('#' + rowid).removeClass('ui-state-highlight'); }$(this).dialog('close');$('#form-name')[0].reset();$('#form-name').removeClass('ui-state-error');}},
close: function() { if(form_status == 'edit') { form_status = 'new';$('#' + rowid).removeClass('ui-state-highlight'); }$('#form-name')[0].reset();$('#form-name').removeClass('ui-state-error');$(".validateTips").html();}
});
$("#dialog-form-course").dialog({autoOpen:false,height:450,width:350,modal:false,position:[675,200],buttons: {
'Add Course Filter': function() {
var item = $("#course-item"),value = $("#course-value"),join = $("#course-join"),disp=$('#course-item option:selected').text(),tn = $("#course-item").val().substr(0,2);
if(tn == '-n') { var operator = $("#course-operator-n"); } else { var operator = $("#course-operator-t"); }
var allFields = $([]).add(item).add(operator).add(value).add(join),tips = $(".validateTips"),bValid = true;
allFields.removeClass('ui-state-error');
bValid = bValid && checkLength(value,"value",1,255);
bValid = bValid && checkRegexp(value,/^([\ \.\,\'\(\)0-9a-z_])+$/i,"Value may consist of a-z, 0-9, underscores, commas, spaces");
if(operator.val() == 'beBetween') { if(checkRegexp(value,/[0-9]\ and\ [0-9]/i,"Value must have ' and ' between a range of numbers. Please see example below.") == false) { bValid = false;$("#example-course").html('<br /><em>Example:</em> ' + disp + ' Between 1 <strong>and</strong> 3'); } }
if(bValid) { updateTableRow('course',item,operator,value,join,disp,tn);$(this).dialog('close'); }
},
Cancel: function() { if(form_status == 'edit') { form_status = 'new';$('#' + rowid).removeClass('ui-state-highlight'); }$(this).dialog('close');$('#form-course')[0].reset();$('#form-course').removeClass('ui-state-error');}},
close: function() { if(form_status == 'edit') { form_status = 'new';$('#' + rowid).removeClass('ui-state-highlight'); }$('#form-course')[0].reset();$('#form-course').removeClass('ui-state-error');$(".validateTips").html('Choose an item to filter such as Course, Grade or Direction<br />An operator such as = or a Between range<br />Value such as an individual course, list of courses or value such as Left.');}
});
buttons code:
$('#add-name').button({icons: {primary:'ui-icon-plus'}}).click(function(){form_status == 'new';$('#dialog-form-name').dialog('open');return false;});
$('#add-course').button({icons: {primary:'ui-icon-plus'}}).click(function(){$("#course-operator-t").show();$("#course-operator-n").hide();$("#course-value").autocomplete("option","disabled",false);$('#dialog-form-course').dialog('open');return false;});
You can see the problem here.
In IE click on NAME and then enter anything in the value box and save it. Now click on NAME and do the same again. As soon as you enter anything IE fails because it can not read $("#name-operator")

Finally worked this out.
in the close: function I had
$('#form-name')[0].reset();
This is to reset the form back to defaults after data was entered. In IE it totally wipes sets the form to null values, whilst in firefox it just resets it.
Had to change it to:
$('#form-name :text').val('');
for the text fields and reset the select id for the select options.

Related

Trigger cocoon add_association from javascript

I am using cocoon and I want to automatically add a child record when a date(can be multiple dates) in a date picker is selected.
I can trap the date selections in coffeescript like this, but I don't know how to get a child record added through cocoon i.e. by emulating what happens when the link_to_add_association is fired.
$(".form_multidate").datepicker().on 'changeDate', (e) -> alert(e.dates)
the cocoon setup is a standard nested form, no tricks, working fine on the page.
EDIT: Code mentioned in comment re binding calendar:
$(document).ready(function() {
$('#other_request_details')
.bind('cocoon:after-insert', function() {
return $('.datepicker-single').datepicker({
dateFormat: "DD, dd M yy"
});
});
});
Calling a JS function in order to add a new record with Cocoon is not possible. The only thing you can do is trigger the click event of the add association button.
If you see Cocoon's library code you will see that all new record functionality is bound to the click button
$(document).on('click', '.add_fields', function(e) {
e.preventDefault();
var $this = $(this),
assoc = $this.data('association'),
assocs = $this.data('associations'),
content = $this.data('association-insertion-template'),
insertionMethod = $this.data('association-insertion-method') || $this.data('association-insertion-position') || 'before',
insertionNode = $this.data('association-insertion-node'),
insertionTraversal = $this.data('association-insertion-traversal'),
count = parseInt($this.data('count'), 10),
regexp_braced = new RegExp('\\[new_' + assoc + '\\](.*?\\s)', 'g'),
regexp_underscord = new RegExp('_new_' + assoc + '_(\\w*)', 'g'),
new_id = create_new_id(),
new_content = content.replace(regexp_braced, newcontent_braced(new_id)),
new_contents = [];
if (new_content == content) {
regexp_braced = new RegExp('\\[new_' + assocs + '\\](.*?\\s)', 'g');
regexp_underscord = new RegExp('_new_' + assocs + '_(\\w*)', 'g');
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
}
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents = [new_content];
count = (isNaN(count) ? 1 : Math.max(count, 1));
count -= 1;
while (count) {
new_id = create_new_id();
new_content = content.replace(regexp_braced, newcontent_braced(new_id));
new_content = new_content.replace(regexp_underscord, newcontent_underscord(new_id));
new_contents.push(new_content);
count -= 1;
}
var insertionNodeElem = getInsertionNodeElem(insertionNode, insertionTraversal, $this)
if( !insertionNodeElem || (insertionNodeElem.length == 0) ){
console.warn("Couldn't find the element to insert the template. Make sure your `data-association-insertion-*` on `link_to_add_association` is correct.")
}
$.each(new_contents, function(i, node) {
var contentNode = $(node);
insertionNodeElem.trigger('cocoon:before-insert', [contentNode]);
// allow any of the jquery dom manipulation methods (after, before, append, prepend, etc)
// to be called on the node. allows the insertion node to be the parent of the inserted
// code and doesn't force it to be a sibling like after/before does. default: 'before'
var addedContent = insertionNodeElem[insertionMethod](contentNode);
insertionNodeElem.trigger('cocoon:after-insert', [contentNode]);
});
});

jQuery Mobile: how to detect when one moving image hovering over the button

In my mobile app, I need to move a green image around the web page.
When the green image hover over the submit button, the button will show "Submit?", and when the user droped the green image on the submit button, the button will turn to orange.
Here's the pictures:
The problem is when the green image hover over the button, the button cannot change, only when I touch the button it can change. I have tried hover() and mouseover() method, all didn't work. It is jQuery Mobile, in my PC version, everything worked very well, but mobile app is different.
So, what can I do so that when the green image hovering over the button, it can show "Submit?"? Or is there any way to detect the object is Yes or No button when the green image hoving over one of them?
here's the code: The drag and drop methods are from another JS file, but should not influence this question.
id = "html";
$(id).ready(function (e) {
$('.yes').bind('mouseover', function( event, ui ){
$('.yes').attr("src","images/submit_confirm.png");
$('input[name=stimulusResponse]').val("yes");
$('.no').attr("src","images/no.png");
});
$('.no').mouseover(function( event, ui ){
$('.no').attr("src","images/submit_confirm.png");
$('input[name=stimulusResponse]').val("no");
$('.yes').attr("src","images/yes.png");
});
$('.bottomGoButton').drag(function( ev, dd ){
$( this ).css({
top: dd.offsetY,
left: dd.offsetX
});
$(this).bind('vmousemove', function(event) {
$('input[name=test]').val(event.pageX + ", " + event.pageY + $('input[name=test]').val());
});
});
$('.no').drop(function(){
$('input[name=stimulusResponse]').val("no");
$('.no').attr("src","images/submitted_no.png");
});
$('.yes').drop(function(){
$('input[name=stimulusResponse]').val("yes");
$('.yes').attr("src","images/submitted_yes.png");
});
});
I have solved this problem myself by using the position of the button and the mouse to do each operation, this have added more flexibility.
Here's part of the code:
1. this is the way to get the top, left, right, bottom arguments:
var yesPosition = $('.yes').position(), noPosition = $('.no').position(),
yesWidth = $('.yes').width(), yesHeight = $('.yes').height(),
noWidth = $('.no').width(), noHeight = $('.no').height();
//get the relative position of yes/no button
var yesTop = yesPosition.top, yesLeft = yesPosition.left,
yesBottom = yesTop + yesHeight, yesRight = yesLeft + yesWidth,
noTop = noPosition.top, noLeft = noPosition.left,
noBottom = noTop + noHeight, noRight = noLeft + noWidth;
/2. this is a replace of hover() method, only when the mouse is moving and in the range of one of the button, we can do the operations we want, pretty cool right :)/
if(isMouseUp == false && event.pageX >= yesLeft && event.pageX <= yesRight && event.pageY >= yesTop && event.pageY <= yesBottom) {
$('input[name=test]').val("X: " + event.pageX + ", " + event.pageY);
$('.yes').attr("src","images/submit_confirm.png");
$('input[name=stimulusResponse]').val("yes hover");
$('.no').attr("src","images/no.png");
}
else if (isMouseUp == false && event.pageX >= noLeft && event.pageX <= noRight && event.pageY >= noTop && event.pageY <= noBottom) {
$('input[name=test]').val("X: " + event.pageX + ", " + event.pageY);
$('.no').attr("src","images/submit_confirm.png");
$('input[name=stimulusResponse]').val("no hover");
$('.yes').attr("src","images/yes.png");
}
else {
$('input[name=stimulusResponse]').val("");
$('.yes').attr("src","images/yes.png");
$('.no').attr("src","images/no.png");
}

how to copy link name to title

i wanna ask how to change title in
name
so i want to make link name copy to title automatic
so if i make this code
title link
to
title link
how to do that in php or javascript
i know some in php
but need to make all words in link at database or make for every link variable $
can some one help me in that?
I'd suggest:
function textToTitle(elem, attr) {
if (!elem || !attr) {
// if function's called without an element/node,
// or without a string (an attribute such as 'title',
// 'data-customAttribute', etc...) then returns false and quits
return false;
}
else {
// if elem is a node use that node, otherwise assume it's a
// a string containing the id of an element, search for that element
// and use that
elem = elem.nodeType == 1 ? elem : document.getElementById(elem);
// gets the text of the element (innerText for IE)
var text = elem.textContent || elem.innerText;
// sets the attribute
elem.setAttribute(attr, text);
}
}
var link = document.getElementsByTagName('a');
for (var i = 0, len = link.length; i < len; i++) {
textToTitle(link[i], 'title');
}
JS Fiddle demo.
And since it seems traditional to offer a concise jQuery option:
$('a').attr('title', function() { return $(this).text(); });
JS Fiddle demo.
If you don't want to use a library:
var allLinks = document.getElementsByTagName('a');
for(var i = 0; i < allLinks.length; i++){
allLinks[i].title = allLinks[i].innerHTML;
}
Since you wanted to do all this to one element on the page, consider using something like this:
var allLinks = document.getElementById('myelement').getElementsByTagName('a'); // gets all the link elements out of #myelement
for ( int i = 0; i < allLinks.length; i++ ){
allLinks[i].title = allLinks[i].innerHTML;
}
Actually, this is roughly the same as before but we are changing the input elements.
Or, assuming you use jQuery, you could do something like this:
$('a').each(function(){ // runs through each link element on the page
$(this).attr('title', $(this).html()); // and changes the title to the text within itself ($(this).html())
});
In JQuery you can change an attribute by knowing the current tag and using the .attr() feature. Something like $('a').attr('title', 'new_title'); http://api.jquery.com/attr/

How to set the popUp Panel show at the position of mouse cursor in richFaces

Is there any Attributes to be able to put popup panel show in the position of the mouse cursor in richFaces 4.?
I now think of one solution is to impact on the show event in rich: component (). Show() function, set the location for the popup by javascript.
You can directly handle the showing of a richfaces modal panel through javascript as shown Here
this js function below will give you the x/y coordinate position of the mouse pointer, the return value of which you can pass as arguments to the Richfaces.showModalPanel function
function getPosition(e) {
e = e || window.event;
var cursor = {x:0, y:0};
if (e.pageX || e.pageY) {
cursor.x = e.pageX;
cursor.y = e.pageY;
}
else {
var de = document.documentElement;
var b = document.body;
cursor.x = e.clientX +
(de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
cursor.y = e.clientY +
(de.scrollTop || b.scrollTop) - (de.clientTop || 0);
}
return cursor;
}
so you can have RichFaces.showModalPanel('panel',{top:getPosition(ev).y,left:getPosition(ev).x})
Sorry about the hideous javascript.

ASP.Net MVC Database Driven Menu Strange HTML output

I have a database driven menu Helper that gets called from within my master page:
<div class="topBar">
<%= Html.MenuTree(39, false, "first", "last") %>
<div class="clear"></div>
</div>
Below is the code that outputs my HTML unordered list. The problem is that sometimes the output of the menu is completely wrong and all over the place ie. sub menu items appear as equal as top menu items.
I cannot find any pattern to why it does it so thought I'd post the code to see if anyone can spot the problem. My only other thought is that somehow its half cached half called and mixes the output.
This is what it should look like Correct http://img718.imageshack.us/img718/9317/screenshot20100328at120.png
Sometimes it comes out like this:alt text http://img413.imageshack.us/img413/9317/screenshot20100328at120.png
Here's the code (the boolean IsAdmin is false in this scenario):
public static string MenuTree(this HtmlHelper helper, int MenuCategoryID, bool Admin, string firstCssClass, string lastCssClass)
{
//TODO: Check for Subsonic fix for UNION bug
IOrderedQueryable<Menu> menuItems;
if (Admin)
{
menuItems = (from menu2 in Menu.All()
join pages in WebPage.All() on menu2.PageID equals pages.ID
join pagesRoles in PageRole.All() on pages.ID equals pagesRoles.PageID
join roles in aspnet_Role.All() on pagesRoles.RoleId equals roles.RoleId
where Roles.GetRolesForUser().Contains(roles.RoleName) && menu2.CategoryID == MenuCategoryID && menu2.Visible
select menu2).Distinct().OrderBy(f => f.OrderID);
}
else
{
menuItems = (from menu2 in Menu.All()
join pages in WebPage.All() on menu2.PageID equals pages.ID
where menu2.CategoryID == MenuCategoryID && menu2.Visible
select menu2).Distinct().OrderBy(f => f.OrderID);
}
var nonlinkedmenuItems = (from menu in Menu.All().Where(x => x.PageID == null && x.CategoryID == MenuCategoryID && x.Visible).OrderBy(f => f.OrderID) select menu);
var allCategories = menuItems.ToList().Concat<Menu>(nonlinkedmenuItems.ToList()).OrderBy(p => p.OrderID).ToList();
allCategories.ForEach(x => x.Children = allCategories.Where(y => y.ParentID == x.ID).OrderBy(f => f.OrderID));
Menu home = null;
if (Admin)
{
home = (from menu in Menu.All()
join pages in WebPage.All() on menu.PageID equals pages.ID
where pages.MenuName == "Home" && pages.IsAdmin
select menu).SingleOrDefault();
}
IEnumerable<Menu> topLevelItems;
if (Admin)
topLevelItems = allCategories.Where(f => f.ParentID == 0 && (f.Children.Count() > 0 || f.ID == home.ID));
else
topLevelItems = allCategories.Where(f => f.ParentID == 0);
var topLevelItemList = topLevelItems.ToList();
sbMenu.Length = 0;
sbMenu.AppendLine("<ul>");
LoopChildren(helper, Admin, topLevelItemList, 0, firstCssClass, lastCssClass);
sbMenu.AppendLine("</ul>");
string menuString = sbMenu.ToString();
//if ((menuString.IndexOf("<li>")) > 0)
// menuString = menuString.Insert((menuString.IndexOf("<li>") + 3), " class='first'");
//if (menuString.LastIndexOf("<li>\r\n") > 0)
// menuString = menuString.Insert((menuString.LastIndexOf("<li>\r\n") + 3), " class='last'");
return sbMenu.ToString();
}
private static void LoopChildren(this HtmlHelper helper, bool Admin, List<Menu> CurrentNode, int TabIndents, string firstCssClass, string lastCssClass)
{
for (int i = 0; i < CurrentNode.Count; i++)
{
sbMenu.Append(Tabs(TabIndents + 1));
string linkUrl = "";
string urlTitle = "";
if (CurrentNode[i].PageID != null)
{
WebPage item = WebPage.SingleOrDefault(x => x.ID == CurrentNode[i].PageID);
linkUrl = item.URL;
urlTitle = item.MenuName;
}
else
{
linkUrl = CurrentNode[i].URL;
urlTitle = CurrentNode[i].Title;
}
//Specify a RouteLink so that when in Error 404 page for example the links don't become /error/homepage
//If in admin we can manually write the <a> tag as it has the controller and action in it
bool selected = false;
if (helper.ViewContext.RouteData.Values["pageName"] != null && helper.ViewContext.RouteData.Values["pageName"].ToString() == linkUrl)
selected = true;
string anchorTag = Admin ? "<a href='" + linkUrl + "'>" + urlTitle + "</a>" : helper.RouteLink(urlTitle, new { controller = "WebPage", action = "Details", pageName = linkUrl });
if (TabIndents == 0 && i == 0 && firstCssClass != null)
sbMenu.AppendLine("<li class='" + firstCssClass + "'>" + anchorTag);
else if (TabIndents == 0 && i == (CurrentNode.Count - 1) && lastCssClass != null)
sbMenu.AppendLine("<li class='" + lastCssClass + "'>" + anchorTag);
else if (selected)
sbMenu.AppendLine("<li class='selected'>" + anchorTag);
else
sbMenu.AppendLine("<li>" + anchorTag);
if (CurrentNode[i].Children != null && CurrentNode[i].Children.Count() > 0)
{
sbMenu.Append(Tabs(TabIndents + 2));
sbMenu.AppendLine("<ul>");
LoopChildren(helper, Admin, CurrentNode[i].Children.ToList(), TabIndents + 2, "", "");
sbMenu.Append(Tabs(TabIndents + 2));
sbMenu.AppendLine("</ul>");
}
sbMenu.Append(Tabs(TabIndents + 1));
sbMenu.AppendLine("</li>");
}
}
private static string Tabs(int n)
{
return new String('\t', n);
}
I agree with the comments that string concatenation for this is painful. TagBuilder is a lot less painful for you.
I didn't check your code for problems, but I imagine that what I would do is basically to take the text output from your helper in a good case and a bad case and run them through a diff tool. Leave some markers before and after the point where you call Html.MenuTree() for debugging purposes - this way you will know exactly where the output starts and stops.
The diff tool will tell you what the differences in the two outputs are. Then you can go looking for the cause of these differences.
Another way I would seriously consider approaching this is through unit testing. Start with a simple unit test giving the MenuTree() method a very simple structure to work with. Verify that the output is sane. Then test more complex scenarios. If you during testing, debugging or in production discover a certain combination of input that causes the problem, write a unit test that tests for the correct output. Then fix it. When the test passes, you'll know that you are finished. Also, if you run your tests whenever you change something, you will know that this particular bug will never creep back in.
New bug? New unit test. And so on. Unit tests never solve the problem for you, but they give you the confidence to know that what used to work still works, even when you refactor and come up with cool new stuff.

Resources