Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

2018-12-30

[SOLVED] Using Bootstrap-Select and Vue together

I ran into some trouble when trying to use Vue bindings and Bootstrap-Select together that kept the visual controls from updating when options were changed via a Vue model update. 

I wrote up an article on my JavaScriptJedi.com website with both broken and working examples and an explanation about what happens.

The quick answers for making sure bootstrap-select works with Vue:

  • Prevent bootstrap-select from automatically hooking itself up to your controls by avoiding using the "selectpicker" class on the <select> element.  Use a different class like "select-picker" instead that you can manually hook up the selectpicker after your Vue model is finished mounting.
    • (Use Vue's $nextTick function inside your "mounted" handler function to ensure all components/child-components are mounted as well before setting up bootstrap-select)
  • Only use the "title" HTML attribute on your <select> when you don't have a default selected value on your <select>
  • ALWAYS call bootstrap-select's "refresh" after changing the <select>'s options via an update to the Vue model.
Please see my write-up on JavaScript Jedi and leave feedback here if you can help me enhance the article or find it helpful.  I hope this saves someone some time and frustration! 

2018-06-27

ASP.NET MVC: Controlling order when using Scripts.Render

The Problem

I like concise, so when I realized I could change the following:

@Scripts.Render("~/bundles/bundle1")
@Scripts.Render("~/bundles/bundle2")
@Scripts.Render("~/bundles/bundle3")
@Scripts.Render("~/bundles/bundle4")


... to ...

@Scripts.Render("~/bundles/bundle1", "~/bundles/bundle2", "~/bundles/bundle3", "~/bundles/bundle4")

... naturally I got excited.  And it worked really well, that is, until I needed bundle3 to come before bundle1.

For a more realistic example, I have my own bundle that is dependent on KnockoutJS and requires Knockout to be loaded before my bundle is.  It would look like this:

@Scripts.Render("~/bundles/something", "~/bundles/knockout", "~/bundles/adminView")

I assumed that the bundles would be rendered in the same order I specified in that call, but it doesn't seem to play nice that way. My "~/bundles/adminView" was rendered before Knockout which broke my script.

To fix it, I removed my bundle from the rest of the list and moved it out into a separate Scripts.Render call. Now it looks like:

@Scripts.Render("~/bundles/something", "~/bundles/knockout")
@Scripts.Render("~/bundles/adminView")


Doing this forced my "adminView" bundle to be rendered after the other two because it was a separate call.

Moral of the Story

You can only "bundle" multiple bundle paths in one Scripts.Render call when none of them depend on each other, because you can't count on what order they will be rendered in. I don't know how Microsoft decides the order to render them in, but it's not necessarily the order you provide.

If order matters, use separate calls and order them the way you need to.

2013-01-08

JavaScript String.Replace: Replacement Pattern for Full Match Reminder

This is my quick reminder to self to use
$&
instead of
$0
in JavaScript for Regular Expression replacement patterns when wishing to use the entire matched text.

Some browsers allow $0, but $& is officially documented (table 22, page 147) and supposed to work in all of them.

Example:
document.write("Hello World".replace(/^Hello/, "$& to the whole");

Output:
Hello to the whole World

2011-08-30

Silverlight throws InvalidOperationException with Common_MethodFailed error when calling HtmlElement.SetAttribute for the "type" attribute

I was working on a Silverlight application the other day and needed to create and submit an HTML form to another ASPX page inside the website hosting the app.

To accomplish this, I was using the HtmlDocument.CreateElement, HtmlElement.SetAttribute and HtmlElement.AppendChild methods to set the whole thing up.

After deploying the application having success with Internet Explorer 9 (IE9), Chrome, etc. we tested on two virtual machines that had IE7 and IE8 and were met with errors and no form submission.

It turns out it was because I was trying to set the "type" attribute of the <input /> elements I was creating with the Silverlight methods after I'd called the AppendChild method.

IE7 and IE8 don't like a developer setting the "type" attribute after the element has been appended to the document and it will throw a JavaScript error which bubbles up to the Silverlight application and the user is shown an obscure InvalidOperationException error whose key is "Common_MethodFailed".

It made no sense to me, but I dug deeper until I could find the offending line.  I then tried an experiment with a XHTML/JavaScript page in the offending browsers to see if it was a Silverlight problem or a problem with the JavaScript engines of said browsers.

I ran into the same problem without Silverlight in the equation.  I wrote up a detailed article explaining it and have the experiment to try in different browsers yourself on my JavaScript Jedi website.

The problem can be solved by making sure you call AppendChild AFTER you set up all the properties/attributes on the HtmlElement, not before.

I hope this helps you avoid several hours of frustration.  :)
Happy Coding!

2010-08-26

Making sure JavaScript gets called after an AJAX Partial Postback in ASP.NET

ScriptManager.RegisterStartupScript(Page page, Type type, string key, string script, bool addScriptTags)

Notice the first parameter of this method, as it has an overload that takes a Control as its first parameter.  When you use the Control overload, it only registers the startup script once on the initial rendering of the page.

If you use the Page overload listed above, it will register it for every asynchronous postback to ensure your JavaScript is executed everytime.

Remember to use ScriptManager and not ClientScriptManager...

From the Remarks on the MSDN article for the overload listed above:
"You use this method to register a startup script block that is included every time that an asynchronous postback occurs. To register a script block for a control that is inside an UpdatePanel control so that the script block is registered only when the UpdatePanel control is updated, use the RegisterStartupScript(Control, Type, String, String, Boolean) overload of this method.

If you want to register a startup script that does not pertain to partial-page updates, and if you want to register the script only one time during initial page rendering, use the RegisterStartupScript method of the ClientScriptManager class. You can get a reference to the ClientScriptManager object from the ClientScript property of the page."

Also very important:
Make sure you have the following using statement in your codebehind...
using System.Web.UI;

If you don't, you will get the error:
Cannot access internal property 'ScriptManager' here

2010-05-16

Introducing document.queryString for JavaScript

I got sick of not having a quick/easy reference object in JavaScript for getting a query string parameter's value.  JavaScript has always offered the window.location.search property to get the entire query string, but who wants to parse that every time?

So I set out to see how long it would take me to make a quick parser that would load it into a nice object that I could jam on the document.

Roughly 30 minutes later, I had one.  It also handles param names that contain periods (person.firstname) which is nice for those that do that with their ASP.NET MVC projects.

I don't have any docs yet, but see the quick write up at my JavaScript Jedi website if you'd like to see it in action and perhaps try it for yourself.

Enjoy!

2008-08-14

JavaScript Won't Run on Internet Explorer as a Local File When Copied From Another Computer

My friend Walt was trying to write a little HTML page with JavaScript to automate a task at work for himself and some colleagues.

He developed it on his own computer; saved it and ran it in Internet Explorer (the only browser allowed to be on their computers at work.) On his computer, the page appeared in "My Computer" (counted in the "Internet" zone if you double-click to bring up the security settings.) Internet Explorer prompted him to allow the ActiveX content.

He then put the file on a network share and allowed his colleagues to download it to their own local machines.

When they downloaded and opened the file in Internet Explorer on their local computers, it appeared as "Restricted Sites" zone. This confused both of us, so I asked him to send me the file.

He transferred it to me via Windows Live Messenger and I saved it to my desktop. I got the same result when I opened it in Internet Explorer.

For an experiment, I edited the file... copied all of its contents into a new file I created from scratch on my machine. When I loaded the new file in Internet Explorer, it appeared as "My Computer" in the "Internet" zone as it had when Walt originally created it.

Thus we can deduce that IE must look at the file's properties and determine if a file was created on the machine asking to run it and if not, locks it down as a "Restricted Sites" file. It treats the ones created on the machine in question as "Internet."

While annoying, this is a nice security feature... and now you know how to get around it...
1. Make sure you analyze the code before you copy to a new file - if you don't and you introduce malicious code on your own machine... shame on you and Microsoft did all they could to protect you. Shame on you... :)
2. Copy the code into a new file that you save to your own machine.
3. Open in Internet Explorer

Of course, I don't know that Firefox has the same restriction, because it doesn't allow direct calls via JavaScript to ActiveX objects so it may run just fine without the extra steps... If so, and you have Firefox on your computer; well, you know what to do.

2008-05-06

Bug Discovered in Internet Explorer 7 JavaScript Regular Expression Engine

I enhanced my understanding about Regular Expressions' "look-ahead" concept that I hadn't fully comprehended before. The fact that (at least in the .NET framework and most JavaScript engines; I assume it also works in PERL and other popular RegEx engines...) you can use look-aheads to not only find a match but not include in the full-text match; but can look-ahead and not have the position of the start of the match matter either.

For some reason I always thought that the match would be made and the beginning of the next match would start at the position the other left off at. I wet my pants with glee when I found that wasn't the case...

That is, until I tried an expression in JavaScript in Internet Explorer 7.

To see an example of what I'm talking about, run my "Regular Expression Tests for Your Browser" on JavaScriptJedi.com in multiple browsers on your computer. You'll be running the "Pre Match Look Aheads (2008-05-05)" tests which are the only ones there at the time of this writing. I may add more in the future.

The scenario is this:
I had a set of password restriction requirements to enforce on a form when a user wanted to change their password. The requirements were that the password must be at least 8 characters long; contains at least one number and at least one "symbol". Due to a database constraint, I also added a max-length requirement of 50 characters, and I interpreted "symbol" to mean any non-alpha-numeric character.

That said, the regular expression ended up like this:
/^(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{8,50}$/

What's really cool about this is; when run in a properly working regular expression engine, it doesn't matter if the number or "symbol" come first, it will detect them both and then from the beginning of the string match any characters between the lengths 8 and 50. Genius. Whoever came up with Regular Expressions needs a Nobel prize or some equivalent; because, well, they just make a developer's world a better place to live. :)

So after getting uber-excited about my new found knowledge and greater love for Regular Expressions, my bubble was quickly burst when I found out it didn't work correctly in IE7 and I had to come up with a workaround.

So go see my page and try it for yourself; and I'd love to get your feedback on this one. I'll be submitting a bug report to Microsoft (if I can figure out how...) and if I hear anything back from them (which I'm sure I won't...) I'll post my findings here.

I'd especially like to hear from Mac users that can test on the major Mac browsers for me and tell me which work and which don't.