Categories
discuss

Why does Google’s closure library not use real private members?

I’ve been a JavaScript developer for a while now, and I’ve always thought that the correct way to implement private members in JavaScript is to use the technique outlined by Doug Crockford here: http://javascript.crockford.com/private.html.

I didn’t think this was a particularly controversial piece of JavaScript wisdom, until I started using the Google Closure library. Imagine my surprise… the library makes no effort to use Crockford-style information hiding. All they do is use a special naming convention and note “private” members in the documentation. I’m in the habit of assuming that the guys at Google are usually on the leading edge of software quality, so what gives? Is there some downside to following Mr. Crockford’s advice that’s not obvious?

Answer

There are a lot of examples of pseudo-privacy in main-stream JavaScript libraries. Facebook Connect’s JavaScript library has the same structure.

The main reason developers go that route is for performance. Hiding things in closures can be slower and use more memory. Closure-hiding can also be less flexible, as true privacy can’t be carried between files without some clever hacks. Closure-hiding is more conceptually pure, IMO, but when performance is a concern, using pseudo-privacy is the way to go.

The other reason is that a lot of Google programmers have backgrounds in Python, where there are no private anythings and the underscore prefix is the accepted community standard.

Categories
discuss

How often do you find javascript disabled on browsers?

I have started using ajax/jQuery in our websites / application. There are many plugins that support degrading the javascript to browsers that dont have javascript enabled and techniques to support this. What are peoples thoughts on javascript support, we build applications rather than just websites and are looking to just support javascript enabled browsers as a pre-requisite assuming that most people or companies have javascript enabled.
Do you find most people have javascript? do you monitor the percentage of javascript/non-javascript browsers (I guess this can be done with website stats) and what are the numbers regarding this?

Answer

Whether you should be worried about this really depends on what sort of website you are creating. For instance, if you’re creating a rich javascript app, you have to ask yourself if it’s worth your time & effort to worry about javascript disabled browsers, as these users are probably not too concerned with using rich user interfaces anyway. Also do you have time to put in the extra work for these browsers as there will be little extra traffic and profit gained (if it’s profit making website).

Also note that if javascript is disabled in these user’s browsers, there will be much on the web these people cannot use. So in all likelihood they’re not heavy users.

Categories
discuss

Java many to many association map

I have two classes, ClassA and ClassB, as well as a “many to many” AssociationClass. I want a structure that holds the associations between A and B so that I can find the counterpart for each instance of A or B.

I thought of using a Hashmap, with pair keys:

Hasmap<Pair<ClassA, ClassB>, AssociationClass> associations;

This way, I can add and remove an association between two instances of ClassA and ClassB, and I can query a relation for two given instances.

However, I miss the feature of getting all associations defined for a given instance of ClassA or ClassB.

I could do it by brute force and loop over all keys of the map to search for associations between a given instance, but this is inefficient and not elegant.

Do you know of any data structure / free library that enables this? I don’t want to reinvent the wheel.

NB: This is not a “database” question. These objects are pure POJO used for live computation, I don’t need persistence stuff.

Answer

Thanks for your suggestions.

I finally reinvented the wheel … I have written a generic class for holding associations. I use two maps of maps, synchronized.

The associations holder provides the following methods

void setAssociation(LeftClass left, RightClass right, AssociationClass assoc);
AssociationClass getAssociation(LeftClass left, RightClass right);
Map<RightClass, AssociationClass> getAssocationsLeft(LeftClass left);
Map<LeftClass, AssociationClass> getAssocationsRight(RightClass right); 
void removeAssociation(LeftClass left, RightClass right);

Here is the code:

import java.util.HashMap;

/** This class holds many to many associations between two classes. */
public class AssociationHolder<LeftClass, RightClass, AssociationClass> {

    // -------------------------------------------------------
    // Attributes
    // -------------------------------------------------------

    private HashMap<LeftClass, HashMap<RightClass, AssociationClass>> associationsLeft = 
        new HashMap<LeftClass, HashMap<RightClass,AssociationClass>>();
    private HashMap<RightClass, HashMap<LeftClass, AssociationClass>> associationsRight = 
        new HashMap<RightClass, HashMap<LeftClass,AssociationClass>>();     

    // -------------------------------------------------------
    // Methods
    // -------------------------------------------------------

    /** 
     *  Set an association between two instance.
     *  Any prior association is overwritten.
     */
    public void setAssociation(LeftClass left, RightClass right, AssociationClass association) {

        // Get the map for the left 
        HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left);

        // No association defined yet for this left key ? => Create new map
        if (leftMap == null) {
            leftMap = new HashMap<RightClass, AssociationClass>();
            this.associationsLeft.put(left, leftMap);
        }

        // Get the map for the right 
        HashMap<LeftClass, AssociationClass> rightMap = this.associationsRight.get(right);

        // No association defined yet for this right key ? => Create new map
        if (rightMap == null) {
            rightMap = new HashMap<LeftClass, AssociationClass>();
            this.associationsRight.put(right, rightMap);
        }

        // Set the assoication on both maps
        leftMap.put(right, association);
        rightMap.put(left, association);        

    } 

    /** @return null if no association found. */
    public AssociationClass getAssociation(LeftClass left, RightClass right) {

        // Use left maps (could have used the right one as well)
        HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left);
        if (leftMap == null) return null;
        return leftMap.get(right);
    }

    /** Get all associations defined for a given Left instance.  */
    public HashMap<RightClass, AssociationClass> getAssociationsLeft(LeftClass left) {

        HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left);

        // No map defined ? return empty one instead of null
        if (leftMap == null) {
            return new HashMap<RightClass, AssociationClass>();
        } else {
            return leftMap;
        }   
    }

    /** Get all associations defined for a given Right instance.  */
    public HashMap<LeftClass, AssociationClass> getAssociationsRight(RightClass right) {

        HashMap<LeftClass, AssociationClass> rightMap = this.associationsRight.get(right);

        // No map defined ? return empty one instead of null
        if (rightMap == null) {
            return new HashMap<LeftClass, AssociationClass>();
        } else {
            return rightMap;
        }   
    }

    /** 
     *  Remove an association between two instances.
     */
    public void removeAssociation(LeftClass left, RightClass right) {
        HashMap<RightClass, AssociationClass> leftMap = this.getAssociationsLeft(left);
        HashMap<LeftClass, AssociationClass> rightMap = this.getAssociationsRight(right);
        leftMap.remove(right);      
        rightMap.remove(left);  
    }
}

I hope this can help someone in the future.

Categories
discuss

How to correct character encoding in IE8 native json?

I am using json with unicode text, and am having a problem with the IE8 native json implementation.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<script>
    var stringified = JSON.stringify("สวัสดี olé");
    alert(stringified);
</script>

Using json2.js or FireFox native json, the alert() string is the same as in the original one. IE8 on the other hand returns Unicode values rather than the original text u0e2au0e27u0e31u0e2au0e14u0e35 olu00e9 . Is there an easy way to make IE behave like the others, or convert this string to how it should be ? And would you regard this as a bug in IE, I thought native json implementations were supposed to be drop-in identical replacements for json2.js ?

Edit: An repro on jsfiddle using the above code – http://jsfiddle.net/vV4uz/

Answer

To answer my own question – Apparently this is not natively possible in IE8, but it does work correctly in the IE9 Beta.

A fix is possible though:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<script>
    var stringified = JSON.stringify("สวัสดี olé");
    stringified  = unescape(stringified.replace(/\u/g, '%u'));
    alert(stringified);
</script>

Which will correctly alert() back the original string on all of IE, FF and Chrome.

Categories
discuss

How to add multiple widgets in the same app?

I’ve just finished my Android widget. Now I need to have different sizes of this widget for the user to choose from.

For example, I need a medium, small and large size widget, so when the user installs the app and hold the home screen then choose widget, in the widget menu I want him to see three widgets with the same app name but with the size. Something like this:

helloSmall helloMedium helloLarge

I have the medium one ready, but how can I add the small and the large in the same app? Knowing that all three sizes contain the same exact data and actions, just the size and the background are different.

Answer

You need a receiver definition for each type in your manifest file like:

    <receiver android:name=".MyWidget" android:label="@string/medium_widget_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/medium_widget_provider" />
    </receiver>

    <receiver android:name=".MyWidget" android:label="@string/large_widget_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/large_widget_provider" />
    </receiver>

This would allow you to have the same AppWidgetProvider class be used for multiple widgets, with different widget names and different sizes defined in the <appwidget-provider> XML.

Now if you need more differences in your widgets than what is in the <appwidget-provider> XML I would create a base widget class that implements all the common behavoir between the different types:

public abstract class MyBaseWidget extends AppWidgetProvider

And then each of your concrete implementations could extend MyBaseWidget. Then in your manifest file you would have a receiver definition for each of your concrete implementations like:

    <receiver android:name=".MyMediumWidget" android:label="@string/medium_widget_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/medium_widget_provider" />
    </receiver>

    <receiver android:name=".MyLargeWidget" android:label="@string/large_widget_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/large_widget_provider" />
    </receiver>
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..