问:
UITextField text jumps when animating width constraint
I'm experiencing a glitch where my UITextField's text jumps to its final position (it doesn't animate) when animating the textfield's width constraint. Take a look at this gif:

When the "Grow" button is tapped, the textfield's width grows. But "hello world" jumps immediately to the center instead of gliding there. When the "Shrink" button is tapped, "hello world" jumps immediately back to the left.

My animation function looks like this:

```<code>func animateGrowShrinkTextFields(grow: Bool) {
    if grow {
        UIView.animate(withDuration: 0.5, animations: {
            self.widthConstraint.constant = 330
            self.view.layoutIfNeeded()
        }, completion: nil)
    } else {
        UIView.animate(withDuration: 0.5, animations: {
            self.widthConstraint.constant = 100
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}
</code>```

I have tried the following list suggestions; none of them worked.

I called self.view.layoutIfNeeded() and self.helloWorldTextField.layoutIfNeeded() before and within the animation block as suggested in this answer: https://stackoverflow.com/a/32996503/2179970

I tried self.view.layoutSubviews and self.helloWorldTextField.layoutSubview as suggested in this answer: https://stackoverflow.com/a/30845306/2179970

Also tried setNeedsLayout() UITextField text jumps iOS 9

I even tried changing the font as suggested here: https://stackoverflow.com/a/35681037/2179970

I tried resignFirstResponder (although though I never tap or edit the textfield in my tests, so it should not involve the firstResponder) as suggested here: https://stackoverflow.com/a/33334567/2179970

I tried subclassing UITextField as seen here: https://stackoverflow.com/a/40279630/2179970

I also tried using a UILabel and got the same jumpy result.

The following question is also very similar to mine but does not have an answer yet: UITextfield text position not animating while width constraint is animated

Here is my project on Github: https://github.com/starkindustries/ConstraintAnimationTest

答:
Solution Demo

I've found a working solution. It feels a little hackish but it works. Here is a gif of the final result. Notice that helloWorldTextField has a blue border to show its location within the second textfield behind it.

Instructions

Make two textfields: helloWorldTextField (the original from the question) and borderTextField (a new textfield). Remove helloWorldTextFields's border and background color. Keep borderTextField's border and background color. Center helloWorldTextField within borderTextField. Then animate the width of borderTextField.

Github link and Code

Here is the project on Github: https://github.com/starkindustries/ConstraintAnimationTest

Here is the code within MyViewController class. Everything else is setup in the storyboard which can be viewed on Github at the link above.

```<code>class MyViewController: UIViewController {

    // Hello World TextField Border var
    @IBOutlet weak var borderTextFieldWidth: NSLayoutConstraint!

    // Button Vars
    @IBOutlet weak var myButton: UIButton!
    var grow: Bool = false

    func animateGrowShrinkTextFields(grow: Bool, duration: TimeInterval) {
        if grow {
            UIView.animate(withDuration: duration, animations: {
                self.borderTextFieldWidth.constant = 330
                self.view.layoutIfNeeded()
            }, completion: { (finished: Bool) in
                print("Grow animation complete!")
            })
        } else {
            UIView.animate(withDuration: duration, animations: {
                self.borderTextFieldWidth.constant = 115
                self.view.layoutIfNeeded()
            }, completion: { (finished: Bool) in
                print("Shrink animation complete!")
            })
        }
    }

    @IBAction func toggle(){
        let duration: TimeInterval = 1.0
        grow = !grow
        let title = grow ? "Shrink" : "Grow"
        myButton.setTitle(title, for: UIControlState.normal)
        animateGrowShrinkTextFields(grow: grow, duration: duration)
    }
}
</code>```

Notes and References

What led me to this solution was @JimmyJames's comment: "You are just animating the UITextField width, but the content inside is not animated."

I researched how to animate font changes and came across this question: Is there a way to animate changing a UILabel's textAlignment?

In that question @CSmith mentioned that "you can animate the FRAME, not the textAlignment" https://stackoverflow.com/a/19251634/2179970

The accepted answer in that question suggests to use a UILabel within another frame. https://stackoverflow.com/a/19251735/2179970

Hope this helps anyone else who comes across this problem. If anyone has another way to solve this, please post a comment or another answer. Thanks!

Body:
I'm experiencing a glitch where my UITextField's text jumps to its final position (it doesn't animate) when animating the textfield's width constraint. Take a look at this gif:

When the "Grow" button is tapped, the textfield's width grows. But "hello world" jumps immediately to the center instead of gliding there. When the "Shrink" button is tapped, "hello world" jumps immediately back to the left.

My animation function looks like this:

func animateGrowShrinkTextFields(grow: Bool) {
    if grow {
        UIView.animate(withDuration: 0.5, animations: {
            self.widthConstraint.constant = 330
            self.view.layoutIfNeeded()
        }, completion: nil)
    } else {
        UIView.animate(withDuration: 0.5, animations: {
            self.widthConstraint.constant = 100
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

I have tried the following list suggestions; none of them worked.

I called self.view.layoutIfNeeded() and self.helloWorldTextField.layoutIfNeeded() before and within the animation block as suggested in this answer: https://stackoverflow.com/a/32996503/2179970

I tried self.view.layoutSubviews and self.helloWorldTextField.layoutSubview as suggested in this answer: https://stackoverflow.com/a/30845306/2179970

Also tried setNeedsLayout() UITextField text jumps iOS 9

I even tried changing the font as suggested here: https://stackoverflow.com/a/35681037/2179970

I tried resignFirstResponder (although though I never tap or edit the textfield in my tests, so it should not involve the firstResponder) as suggested here: https://stackoverflow.com/a/33334567/2179970

I tried subclassing UITextField as seen here: https://stackoverflow.com/a/40279630/2179970

I also tried using a UILabel and got the same jumpy result.

The following question is also very similar to mine but does not have an answer yet: UITextfield text position not animating while width constraint is animated

Here is my project on Github: https://github.com/starkindustries/ConstraintAnimationTest

Body:
Solution Demo

I've found a working solution. It feels a little hackish but it works. Here is a gif of the final result. Notice that helloWorldTextField has a blue border to show its location within the second textfield behind it.

Instructions

Make two textfields: helloWorldTextField (the original from the question) and borderTextField (a new textfield). Remove helloWorldTextFields's border and background color. Keep borderTextField's border and background color. Center helloWorldTextField within borderTextField. Then animate the width of borderTextField.

Github link and Code

Here is the project on Github: https://github.com/starkindustries/ConstraintAnimationTest

Here is the code within MyViewController class. Everything else is setup in the storyboard which can be viewed on Github at the link above.

class MyViewController: UIViewController {

    // Hello World TextField Border var
    @IBOutlet weak var borderTextFieldWidth: NSLayoutConstraint!

    // Button Vars
    @IBOutlet weak var myButton: UIButton!
    var grow: Bool = false

    func animateGrowShrinkTextFields(grow: Bool, duration: TimeInterval) {
        if grow {
            UIView.animate(withDuration: duration, animations: {
                self.borderTextFieldWidth.constant = 330
                self.view.layoutIfNeeded()
            }, completion: { (finished: Bool) in
                print("Grow animation complete!")
            })
        } else {
            UIView.animate(withDuration: duration, animations: {
                self.borderTextFieldWidth.constant = 115
                self.view.layoutIfNeeded()
            }, completion: { (finished: Bool) in
                print("Shrink animation complete!")
            })
        }
    }

    @IBAction func toggle(){
        let duration: TimeInterval = 1.0
        grow = !grow
        let title = grow ? "Shrink" : "Grow"
        myButton.setTitle(title, for: UIControlState.normal)
        animateGrowShrinkTextFields(grow: grow, duration: duration)
    }
}

Notes and References

What led me to this solution was @JimmyJames's comment: "You are just animating the UITextField width, but the content inside is not animated."

I researched how to animate font changes and came across this question: Is there a way to animate changing a UILabel's textAlignment?

In that question @CSmith mentioned that "you can animate the FRAME, not the textAlignment" https://stackoverflow.com/a/19251634/2179970

The accepted answer in that question suggests to use a UILabel within another frame. https://stackoverflow.com/a/19251735/2179970

Hope this helps anyone else who comes across this problem. If anyone has another way to solve this, please post a comment or another answer. Thanks!


来源: stackexchange

问:
Android.Views.InflateException: Binary XML file line #17: Error inflating class android.support.design.internal.NavigationMenuItemView
I am using a material navigation drawer in my android project using Xamarin.
I have been trying to add two Framelayouts into the drawerlayout so that I can switch the content from different fragments see below xml:

```<code> <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">
      <!-- This LinearLayout represents the contents of the screen  -->
      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">
        <!-- The ActionBar displayed at the top -->
        <include
            layout="@layout/toolbar"
android:id="@+id/toolbar" />
        <!-- The main content view where fragments are loaded -->
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            android:id="@+id/scrollview">
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
            <FrameLayout
                android:id="@+id/search_frame"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <FrameLayout
                android:id="@+id/blah"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
          </LinearLayout>
        </ScrollView>
      </LinearLayout>
      <!-- The navigation drawer that comes from the left -->
      <!-- Note that `android:layout_gravity` needs to be set to 'start' -->
      <android.support.design.widget.NavigationView
          android:id="@+id/nav_view"
          android:layout_width="wrap_content"
          android:layout_height="match_parent"
          android:layout_gravity="start"
          app:menu="@menu/drawer_view"
          app:itemTextColor="#FFFFFF"
          app:itemIconTint="#FFFFFF"
          android:background="#464646"/>
    </android.support.v4.widget.DrawerLayout>
</code>```

The main activity :

```<code>protected override void OnCreate(Android_OS.Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.activity_main);

    drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
    // Setting up the toolbar
    var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);
    SupportActionBar.SetTitle(Resource.String.ApplicationName);
    SupportActionBar.SetDisplayHomeAsUpEnabled(true);
    SupportActionBar.SetDisplayShowHomeEnabled(true);

    // Attach item selected handler to navigation view
    var navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
    navigationView.NavigationItemSelected += NavigationView_NavigationItemSelected;

    // Create ActionBarDrawerToggle button and add it to the toolbar
    var drawerToggle = new Android_Support.V7.App.ActionBarDrawerToggle(this, drawerLayout, toolbar, Resource.String.open_drawer, Resource.String.close_drawer);
    drawerLayout.SetDrawerListener(drawerToggle);
    drawerToggle.SyncState();
}
</code>```

I get the following error:  Android.Views.InflateException: Binary XML file line #17: Error inflating class android.support.design.internal.NavigationMenuItemView

I have tried moving the elements in the Drawerlayout but the error is persistent. I have looked at the Android documentation everything seems correct. I have also checked that I have the most recent version of both the Design and AppCompact library

答:
The error is because you might be extending your MainActivity by Activity instead of AppComptActivity

If you are using any of the Design Library components, you should ensure your activity extends AppCompatActivity and uses an appropriate Theme.AppCompat theme. Note that the FloatingActionButton relies on the colorAccent set on your theme - ensure your theme has that defined.

ContentLicense: CC BY-SA 3.0

Body:
I am using a material navigation drawer in my android project using Xamarin.
I have been trying to add two Framelayouts into the drawerlayout so that I can switch the content from different fragments see below xml:

 <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

        <include
            layout="@layout/toolbar"
android:id="@+id/toolbar" />

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            android:id="@+id/scrollview">
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
            <FrameLayout
                android:id="@+id/search_frame"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <FrameLayout
                android:id="@+id/blah"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
          </LinearLayout>
        </ScrollView>
      </LinearLayout>

      <android.support.design.widget.NavigationView
          android:id="@+id/nav_view"
          android:layout_width="wrap_content"
          android:layout_height="match_parent"
          android:layout_gravity="start"
          app:menu="@menu/drawer_view"
          app:itemTextColor="#FFFFFF"
          app:itemIconTint="#FFFFFF"
          android:background="#464646"/>
    </android.support.v4.widget.DrawerLayout>

The main activity :

protected override void OnCreate(Android_OS.Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.activity_main);

    drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
    // Setting up the toolbar
    var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);
    SupportActionBar.SetTitle(Resource.String.ApplicationName);
    SupportActionBar.SetDisplayHomeAsUpEnabled(true);
    SupportActionBar.SetDisplayShowHomeEnabled(true);

    // Attach item selected handler to navigation view
    var navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
    navigationView.NavigationItemSelected += NavigationView_NavigationItemSelected;

    // Create ActionBarDrawerToggle button and add it to the toolbar
    var drawerToggle = new Android_Support.V7.App.ActionBarDrawerToggle(this, drawerLayout, toolbar, Resource.String.open_drawer, Resource.String.close_drawer);
    drawerLayout.SetDrawerListener(drawerToggle);
    drawerToggle.SyncState();
}

I get the following error:  Android.Views.InflateException: Binary XML file line #17: Error inflating class android.support.design.internal.NavigationMenuItemView

I have tried moving the elements in the Drawerlayout but the error is persistent. I have looked at the Android documentation everything seems correct. I have also checked that I have the most recent version of both the Design and AppCompact library


问:
What is the difference between ".class element" and "element.class"?
Is there a difference between .class element and element.class in a CSS selector?

I had always been shown element.class but just the other day came across a CSS file at work that had .class element and wanted to know if this was just a style choice (in which case I would make my changes match), or if there was a specific reason (in which case I would not necessarily want to make my changes match).

答:
I like to think it as follows:

```<code>1) a, b  =   a OR b
2) a  b  =   a AND b (on that order)
3) a.b   =   a.b     (on that order)
</code>```

2, 3) a b is not the same as b a.

2) Elements belonging to a and b simultaneously, i.e. nor a or b elements. Is a range selection.

3) a elements of b class. Is an exact selection.

ContentLicense: CC BY-SA 4.0

Body:
I like to think it as follows:

1) a, b  =   a OR b
2) a  b  =   a AND b (on that order)
3) a.b   =   a.b     (on that order)

2, 3) a b is not the same as b a.

2) Elements belonging to a and b simultaneously, i.e. nor a or b elements. Is a range selection.

3) a elements of b class. Is an exact selection.


问:
Promise with Pouch not returning from call to inside code
I have a promise that seemed to work before but not now.

I think I have everything in place but after the .get is called, it never gets to the for loop.

It jumps to the end and out of the promise, then back to the return (inside the .get) then to the resolve and then out.

If there were an error, it should have jumped to the catch but didn't, so how does it miss the for loop?

Here is the code:

```<code>    function readAllImagesFromPouch(id, imageDisplay) {

       return new Promise(function (resolve, reject) {

          var startElement = document.getElementById(imageDisplay);
          var image = "";

          // Get all attachments for this id

          DB_TaskImages.get(id, { attachments: true }).then(function (doc) {

         for (var key in doc._attachments) {

            DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {
               var img = document.createElement('img');
               blob = resizeImage(blob, "100", "60");
               var url = URL.createObjectURL(blob);
               img.src = url;
               //alert(img.outerHTML);

               //startElement.appendChild(img);
               $(startElement).append("<div class='row' style='border:1px solid black'><div class='col-xs-10'>" +
                           img.outerHTML +
                           "</div>" +
                           "<div class='col-xs-1' style='padding-top:20px'>" +
                           "<img src='../Images/delete.png' alt='Delete'  class='taskimage'>" +
                           "</div></div>"
                        );
               return;
            }).catch(function () {
               console.log("No attachment for doc._id: " + doc._id + " and key: " + key);
            })
         }
         return;
          }).then(function () {
            resolve();
          }).catch(function (err) {
         console.log("Image not there for id: " + id);
         showMsg("Image not there for id: " + id);
         reject(err);
          })
       });         // end of promise
    }
</code>```

And it is called from this code:

```<code>    readAllImagesFromPouch("006", "divImages").then(function () {
    }).catch(function (err) {
       console.log("In catch for readAllImagesFromPouch with err: " + err);
    })
</code>```

Thanks,

Tom

答:
This may not be the correct way to do this but I wanted to show the code I changed to see if it was the correct way to do this.  This is really part of the other question that @jaromandaX answered.

This is really the same question - how to handle a promise in a promise.

Looking at your code the resizeImage code had a problem because the blob was not really a blob, I think, which was why I had to use blobutil in my other example. This is really a question on how to handle this with a promise - if I needed to go this way.

My old code was:

```<code>function resizeImageOld(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL
   var showImage = document.createElement('img');
   var url = URL.createObjectURL(blob);
   showImage.src = url;

   var newImage;

   showImage.onload = function () {
      URL.revokeObjectURL(showImage.src);
      var canvas = document.createElement("canvas");
      var ctx = canvas.getContext("2d");

      var MAX_WIDTH = maxWidth, maxHeight;
      var MAX_HEIGHT = 60;
      var width = showImage.width;
      var height = showImage.height;

      if (width > height) {
     if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
     }
      } else {
     if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
     }
      }

      canvas.width = width;
      canvas.height = height;

      ctx.drawImage(showImage, 0, 0, width, height);
      newImage = canvas.toDataURL("image/png");
   }
   return newImage;
}
</code>```

Making it a promise was a way to get the blob resized and appended to the DOM before it handled another image.  This way it never did the onload event.

I changed it to:

```<code>function resizeImage(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL

   return new Promise(function (resolve, reject) {

      var showImage = document.createElement('img');
      var url = URL.createObjectURL(blob);
      var newImage;

      showImage.onload = function () {
     URL.revokeObjectURL(showImage.src);
     var canvas = document.createElement("canvas");
     var ctx = canvas.getContext("2d");

     var MAX_WIDTH = maxWidth, maxHeight;
     var MAX_HEIGHT = 60;
     var width = showImage.width;
     var height = showImage.height;

     if (width > height) {
        if (width > MAX_WIDTH) {
           height *= MAX_WIDTH / width;
           width = MAX_WIDTH;
        }
     } else {
        if (height > MAX_HEIGHT) {
           width *= MAX_HEIGHT / height;
           height = MAX_HEIGHT;
        }
     }

     canvas.width = width;
     canvas.height = height;

     ctx.drawImage(showImage, 0, 0, width, height);
     newImage = canvas.toDataURL("image/png");

     resolve(newImage);
      }

      showImage.src = url;
   })
}
</code>```

I then changed your code, which now calls this promise to the following and wanted to see if this was the correct way to handle it or would it just jump out of the promise and continue on and come back later after it went through the other images.  It does seem better but not sure.

Your code:

```<code>function readAllImagesFromPouch(id, imageDisplay) {

   var startElement = document.getElementById(imageDisplay);
   var img = "";
   var imgBlob;
   var base64str;
   var fileName;

   ClearImagePanel();

   // Get all attachments for this id

   return DB_TaskImages.get(id, { attachments: true }).then(function (doc) {

      // a promise to chain to - all following tasks will be performed in series, not parallel - this can be changed

      var promise = Promise.resolve();

      Object.keys(doc._attachments).forEach(function (key) {
     promise = promise.then(function () {
        return DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {

           img = document.createElement('img');

           return resizeImage(blob, "100", "60").then(function(blob) {
          var url = URL.createObjectURL(blob);

          img.src = myUrl;
          $(startElement).append(img.outerHTML);

           })
        }).catch(function (err) {
           alert("No attachment for doc._id: " + doc._id + " and key: " + key);
        })
     });
      });
      return promise;
   }).catch(function (err) {
      console.log("Image not there for id: " + id);
      showMsg("Image not there for id: " + id);
      throw err;
   })
}
</code>```

Is this right or is it the same type of anti-pattern you mentioned before?

I also had two other questions I couldn't seem to find elsewhere.

On the initial promise of a chain (DB_TaskImages.getAttachment, in this case), do we do a "return" because we are returning to the following "then"?  I was not sure, since I had seen examples where there was a return and others where there wasn't a return on the first promise.

In my example, for the "return resizeImage" promise, do I need a .then after it as well as the catch?  I noticed that after you did a "return promise", there was no .then but there was a catch.

Just curious.

Thanks.

Body:
I have a promise that seemed to work before but not now.

I think I have everything in place but after the .get is called, it never gets to the for loop.

It jumps to the end and out of the promise, then back to the return (inside the .get) then to the resolve and then out.

If there were an error, it should have jumped to the catch but didn't, so how does it miss the for loop?

Here is the code:

    function readAllImagesFromPouch(id, imageDisplay) {

       return new Promise(function (resolve, reject) {

          var startElement = document.getElementById(imageDisplay);
          var image = "";

          // Get all attachments for this id

          DB_TaskImages.get(id, { attachments: true }).then(function (doc) {

         for (var key in doc._attachments) {

            DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {
               var img = document.createElement('img');
               blob = resizeImage(blob, "100", "60");
               var url = URL.createObjectURL(blob);
               img.src = url;
               //alert(img.outerHTML);

               //startElement.appendChild(img);
               $(startElement).append("

" +
                           img.outerHTML +
                           "
" +
                           "
" +
                           "" +
                           "

"
                        );
               return;
            }).catch(function () {
               console.log("No attachment for doc._id: " + doc._id + " and key: " + key);
            })
         }
         return;
          }).then(function () {
            resolve();
          }).catch(function (err) {
         console.log("Image not there for id: " + id);
         showMsg("Image not there for id: " + id);
         reject(err);
          })
       });         // end of promise
    }

And it is called from this code:

    readAllImagesFromPouch("006", "divImages").then(function () {
    }).catch(function (err) {
       console.log("In catch for readAllImagesFromPouch with err: " + err);
    })

Thanks,

Tom

Body:
This may not be the correct way to do this but I wanted to show the code I changed to see if it was the correct way to do this.  This is really part of the other question that @jaromandaX answered.

This is really the same question - how to handle a promise in a promise.

Looking at your code the resizeImage code had a problem because the blob was not really a blob, I think, which was why I had to use blobutil in my other example. This is really a question on how to handle this with a promise - if I needed to go this way.

My old code was:

function resizeImageOld(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL
   var showImage = document.createElement('img');
   var url = URL.createObjectURL(blob);
   showImage.src = url;

   var newImage;

   showImage.onload = function () {
      URL.revokeObjectURL(showImage.src);
      var canvas = document.createElement("canvas");
      var ctx = canvas.getContext("2d");

      var MAX_WIDTH = maxWidth, maxHeight;
      var MAX_HEIGHT = 60;
      var width = showImage.width;
      var height = showImage.height;

      if (width > height) {
     if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
     }
      } else {
     if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
     }
      }

      canvas.width = width;
      canvas.height = height;

      ctx.drawImage(showImage, 0, 0, width, height);
      newImage = canvas.toDataURL("image/png");
   }
   return newImage;
}

Making it a promise was a way to get the blob resized and appended to the DOM before it handled another image.  This way it never did the onload event.

I changed it to:

function resizeImage(blob, maxWidth, maxHeight) {
   // Set img src to ObjectURL

   return new Promise(function (resolve, reject) {

      var showImage = document.createElement('img');
      var url = URL.createObjectURL(blob);
      var newImage;

      showImage.onload = function () {
     URL.revokeObjectURL(showImage.src);
     var canvas = document.createElement("canvas");
     var ctx = canvas.getContext("2d");

     var MAX_WIDTH = maxWidth, maxHeight;
     var MAX_HEIGHT = 60;
     var width = showImage.width;
     var height = showImage.height;

     if (width > height) {
        if (width > MAX_WIDTH) {
           height *= MAX_WIDTH / width;
           width = MAX_WIDTH;
        }
     } else {
        if (height > MAX_HEIGHT) {
           width *= MAX_HEIGHT / height;
           height = MAX_HEIGHT;
        }
     }

     canvas.width = width;
     canvas.height = height;

     ctx.drawImage(showImage, 0, 0, width, height);
     newImage = canvas.toDataURL("image/png");

     resolve(newImage);
      }

      showImage.src = url;
   })
}

I then changed your code, which now calls this promise to the following and wanted to see if this was the correct way to handle it or would it just jump out of the promise and continue on and come back later after it went through the other images.  It does seem better but not sure.

Your code:

function readAllImagesFromPouch(id, imageDisplay) {

   var startElement = document.getElementById(imageDisplay);
   var img = "";
   var imgBlob;
   var base64str;
   var fileName;

   ClearImagePanel();

   // Get all attachments for this id

   return DB_TaskImages.get(id, { attachments: true }).then(function (doc) {

      // a promise to chain to - all following tasks will be performed in series, not parallel - this can be changed

      var promise = Promise.resolve();

      Object.keys(doc._attachments).forEach(function (key) {
     promise = promise.then(function () {
        return DB_TaskImages.getAttachment(doc._id, key).then(function (blob) {

           img = document.createElement('img');

           return resizeImage(blob, "100", "60").then(function(blob) {
          var url = URL.createObjectURL(blob);

          img.src = myUrl;
          $(startElement).append(img.outerHTML);

           })
        }).catch(function (err) {
           alert("No attachment for doc._id: " + doc._id + " and key: " + key);
        })
     });
      });
      return promise;
   }).catch(function (err) {
      console.log("Image not there for id: " + id);
      showMsg("Image not there for id: " + id);
      throw err;
   })
}

Is this right or is it the same type of anti-pattern you mentioned before?

I also had two other questions I couldn't seem to find elsewhere.

On the initial promise of a chain (DB_TaskImages.getAttachment, in this case), do we do a "return" because we are returning to the following "then"?  I was not sure, since I had seen examples where there was a return and others where there wasn't a return on the first promise.

In my example, for the "return resizeImage" promise, do I need a .then after it as well as the catch?  I noticed that after you did a "return promise", there was no .then but there was a catch.

Just curious.

Thanks.


问:
how to edit source code in JAR file and combine it again?
I have extract the JAR file with winrar, and i able to saw all the class file which inside the JAR file.

I wish to edit some of the source code for the entire JAR file, and combine it again become a new JAR file which can work properly.
I have successful to edit the source code in class file, how can i combine it again??

is it i need to create a new project? copy all the source code in class file to a java file?
i have no idea and i am still new to this.
thanks if got any comment or better solution.

答:
Google is your Freind : "Java create a jar"

http://download.oracle.com/javase/tutorial/deployment/jar/build.html

ContentLicense: CC BY-SA 2.5


问:
SQL - LINQ2SQL - Accessing sys.table
I have Googled this without any success.

Here is the SQL query and I wish to turn it into LINQ2SQL.

```<code>SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID WHERE t.Name = 'Address'
</code>```

At first I tried accessing just the sys.table like this:

```<code>from n in _db.sys.table where n.table select n

_db = new DBDataContext(ConfigurationManager.ConnectionStrings["DATABASE"].ConnectionString);
</code>```

I am however receiving the following error - Cannot resolve symbol 'sys'

Can you even do this in LINQ2SQL?

Thanks in advance.

Clare :-)

答: A stored proc can work well too - you just drag it in and it creates a new type with all the right in and out parameters.</p>

Title: SQL - LINQ2SQL - Accessing sys.table

Body:
I have Googled this without any success.

Here is the SQL query and I wish to turn it into LINQ2SQL.

SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID WHERE t.Name = 'Address'

At first I tried accessing just the sys.table like this:

from n in _db.sys.table where n.table select n

_db = new DBDataContext(ConfigurationManager.ConnectionStrings["DATABASE"].ConnectionString);

I am however receiving the following error - Cannot resolve symbol 'sys'

Can you even do this in LINQ2SQL?

Thanks in advance.

Clare :-)


问:
element.val() returning previous value
Here is my problem

I am trying to create a button that calls a directive function which then activates the google place 'place_changed' event that is assigned to the directive. If the getPlace() function doesn't return a result e.g. var result = scope.gPlace.getPlace(); then I want force a place prediction by doing the following.

```<code>if( result === undefined ) {
   result = { name: element.val() }
}
</code>```

however the problem is that this code will work when the page is first loaded but subsequent attempts will assign the var result to the previous text that was entered. e.g. Type "Adelaide" and click on the button equals successful process however now type melbourne and click on the button will still equal "Adelaide"

'use strict';
angular.module( "ngAutocomplete", [])
  .directive('ngAutocomplete', function() {
    return {
      require: 'ngModel',
      scope: {
        ngModel: '=',
        options: '=?',
        details: '=?',
        setFn: '&'
      },

      link: function(scope, element, attrs, controller) {

        //options for autocomplete
        var opts
        var watchEnter = false
        //convert options provided to opts
        var initOpts = function() {

          opts = {}
          if (scope.options) {

            if (scope.options.watchEnter !== true) {
              watchEnter = false
            } else {
              watchEnter = true
            }

            if (scope.options.types) {
              opts.types = []
              opts.types.push(scope.options.types)
              scope.gPlace.setTypes(opts.types)
            } else {
              scope.gPlace.setTypes([])
            }

            if (scope.options.bounds) {
              opts.bounds = scope.options.bounds
              scope.gPlace.setBounds(opts.bounds)
            } else {
              scope.gPlace.setBounds(null)
            }

            if (scope.options.country) {
              opts.componentRestrictions = {
                country: scope.options.country
              }
              scope.gPlace.setComponentRestrictions(opts.componentRestrictions)
            } else {
              scope.gPlace.setComponentRestrictions(null)
            }
          }
        }

        if (scope.gPlace == undefined) {
          scope.gPlace = new google.maps.places.Autocomplete(element[0], {});
        }

        google.maps.event.addListener(scope.gPlace, 'place_changed', function() {

          var result = scope.gPlace.getPlace();

          //hack to make sure we have an object to pass to ensure we can get results from the called function activateGetPlace
          if( result === undefined ) {
            result = { name: element.val() }
          }

          console.log("the result", result);

          if (result !== undefined) {

            if (result.address_components !== undefined) {

              scope.$apply(function() {
                scope.details = result;
                controller.$setViewValue(element.val());
              });
            }
            else {
              if (watchEnter) {
                getPlace(result)
              }
            }
          }
        })

        //function to get retrieve the autocompletes first result using the AutocompleteService
        var getPlace = function(result) {
          var autocompleteService = new google.maps.places.AutocompleteService();
          if (result.name.length > 0){
            autocompleteService.getPlacePredictions(
              {
                input: result.name,
                offset: result.name.length,
                types: opts.types,
              componentRestrictions: opts.componentRestrictions
              },
              function listentoresult(list, status) {
                if(list == null || list.length == 0) {

                  scope.$apply(function() {
                    scope.details = null;
                  });

                } else {
                  var placesService = new google.maps.places.PlacesService(element[0]);
                  placesService.getDetails(
                    {'reference': list[0].reference},
                    function detailsresult(detailsResult, placesServiceStatus) {

                      if (placesServiceStatus == google.maps.GeocoderStatus.OK) {
                        scope.$apply(function() {

                          controller.$setViewValue(detailsResult.formatted_address);
                          element.val(detailsResult.formatted_address);

                          scope.details = detailsResult;

                          //on focusout the value reverts, need to set it again.
                          var watchFocusOut = element.on('focusout', function(event) {
                            element.val(detailsResult.formatted_address);
                            element.unbind('focusout')
                          })

                        });
                      }
                    }
                  );
                }
              });
          }
        }

        controller.$render = function () {
          var location = controller.$viewValue;
          element.val(location);
        };

        //watch options provided to directive
        scope.watchOptions = function () {
          return scope.options
        };

        scope.$watch(scope.watchOptions, function () {
          initOpts()
        }, true);

        scope.activateGetPlace = function() {
          google.maps.event.trigger(scope.gPlace, 'place_changed');
        }

        scope.setFn({theDirFn: scope.activateGetPlace});

      }
    };
  });

  var mechanicsearch = angular.module('mechanicsearch', ['ngRoute','ngResource','ngAutocomplete']),
    radiusOptions = [];

mechanicsearch.run(function($rootScope) {
  $rootScope.$on('handleActiveJobsPanel', function(event, args) {
      $rootScope.$broadcast('activateJobsPanel', args);
  });
  $rootScope.$on('handleActiveFinalise', function(event, args) {
      $rootScope.$broadcast('activateFinalisePanel', args);
  });
  $rootScope.$on('handleActiveSearch', function(event, args) {
      $rootScope.$broadcast('activateSearchPanel', args);
  });
});

mechanicsearch.filter('htmlToPlaintext', function() {
  return function(text) {
    return  text ? String(text).replace(/<[^>]+>/gm, '') : '';
  };
});

// mechFactory service
mechanicsearch.factory('mechFactory', function($resource,$window) {
    var mechanics = [];
    var jobs = [];

    var addMechanic = function(mechanic){
      mechanics.push(mechanic);
    };

    var getAllMechanics = function(){
      return mechanics;
    };

    var removeAllMechanics = function() {
      mechanics = [];
    }

    var addJob = function(job) {
      jobs.push(job);
    }

    var getAllJobs = function() {
      return jobs;
    }

    var removeAllJobs = function() {
      jobs = [];
    }

    return {
      getMechanics: function(location,radius) {
        return $resource('/ajax/api.cfm?api=mechanic&function=getMechanicByLocation&lat=:lat&lng=:lng&radius=:radius' ).get({lat:location.lat,lng:location.lng,radius:radius});
      },
      getJobs: function() {
        return $resource('/ajax/api.cfm?api=job&function=getJobsAssignedtoWorkshop' ).get();
      },
      sendMechanicsJobNotifications: function(mechanics, jobs) {
        return $resource('/ajax/api.cfm?api=job&function=sendMechanicsJobNotifications&mechanics=:mechanics&jobs=:jobs' ).get({mechanics:mechanics.toString(),jobs:jobs.toString()});
      },
      addMechanic: addMechanic,
      removeAllMechanics: removeAllMechanics,
      getAllMechanics: getAllMechanics,
      addJob: addJob,
      removeAllJobs: removeAllJobs,
      getAllJobs: getAllJobs
    }
});

mechanicsearch.controller('SearchCtrl', ['$timeout', '$scope', '$window', '$location', '$routeParams', 'filterFilter', 'mechFactory', '$resource', '$element',

    function ($timeout, $scope, $window, $location, $routeParams, filterFilter, mechFactory, $resource, $element) {

        $scope.place = {};
        $scope.place.address = null;
        $scope.place.lat = null;
        $scope.place.lng = null;
        $scope.radius = 25;
        $scope.mechanics = [];
        $scope.selection = [];
        $scope.alert = null;
        $scope.showSearchPanel = true;

        //Helper method to get selected mechanics
        $scope.selectedMechanics = function selectedMechanics() {
          filterFilter($scope.mechanics, { selected: true })
        };

        //allow mechanic checkbox to select/deselect on click
        $scope.toggleMechanicSelect = function(mechanic) {
          mechanic.selected = !mechanic.selected;
        }

        $scope.goToJobListing = function() {
          $scope.showSearchPanel = false;
          mechFactory.removeAllMechanics();
          for( var i in $scope.selection ) {
            mechFactory.addMechanic($scope.selection[i]);
          }
          $scope.$emit('handleActiveJobsPanel');
        }

        // watch mechanics for changes
        $scope.$watch('mechanics|filter:{selected:true}', function (nv) {
         $scope.selection = nv.map(function (mechanic) {
           return mechanic.objectid;
         });
        }, true);

        //watch the returning google autocomplete details object
        $scope.$watch('details', function() {
          if( $scope.details !== undefined && $scope.details !== null ) {
            $scope.place.address = $scope.details.formatted_address;
            $scope.place.lat = $scope.details.geometry.location.lat();
            $scope.place.lng = $scope.details.geometry.location.lng();
          }
        });

        // watch the $scope.place data for changes
        $scope.$watchCollection('place', function() {
          if( $scope.place.lat !== null || $scope.place.lng !== null ) {
            $scope.getMechanics();
          }
        });

        $scope.$watch('radius', function() {
          if( Number.isInteger(parseInt($scope.radius))  ){
            $scope.getMechanics();
          }
        });

        $scope.setDirectiveFn = function(directiveFn) {
          $scope.directiveFn = directiveFn;
        };

        $scope.getMechanics = function() {
          mechFactory.getMechanics($scope.place, $scope.radius).$promise.then(
            function successfulResult (mechanicsData) {

              if (!mechanicsData || !mechanicsData.data.length){
                $scope.alert = 'Sorry, no mechanic found in "' + $scope.place.address + '" with radius of ' + $scope.radius + '.';
                $scope.mechanics = [];
                $scope.selection = [];
              } else {
                $scope.alert = mechanicsData.data.length + ' mechanic(s) found in "' + $scope.place.address + '" with radius of ' + $scope.radius + ' km.';
                $scope.mechanics = mechanicsData.data;
                $scope.selection = [];
              }

            }, function failedResult (err) {
              $scope.alert = err.message;
            });
        };

        //display panel once we have recieved the event
        $scope.$on('activateSearchPanel', function(event, args) {
          $scope.mechanics = [];
          $scope.selection = [];
          $scope.alert = null;
          $scope.showSearchPanel = true;
          $scope.place = {};
          $scope.radius = 25;
        });
    }
]);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-route.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-resource.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCmN0htBqG3DGo04KKKzC9srgIrhP0Dq5o&libraries=places"></script>

<div id="mechanicsearch" data-ng-app="mechanicsearch">

        <div data-ng-controller="SearchCtrl" ng-show="showSearchPanel">
          <aside class="workshopsearch" >

              <form method="post" class="form-inline" role="form">
                <div class="row">
                      <div class="col-sm-6 form-group input-group-lg">
                          <input type="text" id="geoSearch" ng-model="autocomplete" class="form-control" ng-autocomplete options="{ types: 'geocode', country: 'au', watchEnter: true }" details="details" set-fn="setDirectiveFn(theDirFn)" />
                      </div>
                      <div class="col-sm-6 input-group input-group-lg">
                        <input type="text" class="form-control" name="radius" id="radius" placeholder="Radius" data-ng-model="radius">
                        <span class="input-group-btn"><button class="btn btn-go" ng-click="directiveFn()">Go</button</span>
                      </div>
                  </div>
              </form>
          </aside>
         </div>
        </div></code>```

}

答: Why are you using element.val() when you have an ngModel bound to the input? Why not use scope.ngModel instead?

Title: element.val() returning previous value

Body:
Here is my problem

I am trying to create a button that calls a directive function which then activates the google place 'place_changed' event that is assigned to the directive. If the getPlace() function doesn't return a result e.g. var result = scope.gPlace.getPlace(); then I want force a place prediction by doing the following.

if( result === undefined ) {
   result = { name: element.val() }
}

however the problem is that this code will work when the page is first loaded but subsequent attempts will assign the var result to the previous text that was entered. e.g. Type "Adelaide" and click on the button equals successful process however now type melbourne and click on the button will still equal "Adelaide"

'use strict';
angular.module( "ngAutocomplete", [])
  .directive('ngAutocomplete', function() {
    return {
      require: 'ngModel',
      scope: {
        ngModel: '=',
        options: '=?',
        details: '=?',
        setFn: '&'
      },

      link: function(scope, element, attrs, controller) {

        //options for autocomplete
        var opts
        var watchEnter = false
        //convert options provided to opts
        var initOpts = function() {

          opts = {}
          if (scope.options) {

            if (scope.options.watchEnter !== true) {
              watchEnter = false
            } else {
              watchEnter = true
            }

            if (scope.options.types) {
              opts.types = []
              opts.types.push(scope.options.types)
              scope.gPlace.setTypes(opts.types)
            } else {
              scope.gPlace.setTypes([])
            }

            if (scope.options.bounds) {
              opts.bounds = scope.options.bounds
              scope.gPlace.setBounds(opts.bounds)
            } else {
              scope.gPlace.setBounds(null)
            }

            if (scope.options.country) {
              opts.componentRestrictions = {
                country: scope.options.country
              }
              scope.gPlace.setComponentRestrictions(opts.componentRestrictions)
            } else {
              scope.gPlace.setComponentRestrictions(null)
            }
          }
        }

        if (scope.gPlace == undefined) {
          scope.gPlace = new google.maps.places.Autocomplete(element[0], {});
        }

        google.maps.event.addListener(scope.gPlace, 'place_changed', function() {

          var result = scope.gPlace.getPlace();

          //hack to make sure we have an object to pass to ensure we can get results from the called function activateGetPlace
          if( result === undefined ) {
            result = { name: element.val() }
          }

          console.log("the result", result);

          if (result !== undefined) {

            if (result.address_components !== undefined) {

              scope.$apply(function() {
                scope.details = result;
                controller.$setViewValue(element.val());
              });
            }
            else {
              if (watchEnter) {
                getPlace(result)
              }
            }
          }
        })

        //function to get retrieve the autocompletes first result using the AutocompleteService
        var getPlace = function(result) {
          var autocompleteService = new google.maps.places.AutocompleteService();
          if (result.name.length > 0){
            autocompleteService.getPlacePredictions(
              {
                input: result.name,
                offset: result.name.length,
                types: opts.types,
              componentRestrictions: opts.componentRestrictions
              },
              function listentoresult(list, status) {
                if(list == null || list.length == 0) {

                  scope.$apply(function() {
                    scope.details = null;
                  });

                } else {
                  var placesService = new google.maps.places.PlacesService(element[0]);
                  placesService.getDetails(
                    {'reference': list[0].reference},
                    function detailsresult(detailsResult, placesServiceStatus) {

                      if (placesServiceStatus == google.maps.GeocoderStatus.OK) {
                        scope.$apply(function() {

                          controller.$setViewValue(detailsResult.formatted_address);
                          element.val(detailsResult.formatted_address);

                          scope.details = detailsResult;

                          //on focusout the value reverts, need to set it again.
                          var watchFocusOut = element.on('focusout', function(event) {
                            element.val(detailsResult.formatted_address);
                            element.unbind('focusout')
                          })

                        });
                      }
                    }
                  );
                }
              });
          }
        }

        controller.$render = function () {
          var location = controller.$viewValue;
          element.val(location);
        };

        //watch options provided to directive
        scope.watchOptions = function () {
          return scope.options
        };

        scope.$watch(scope.watchOptions, function () {
          initOpts()
        }, true);

        scope.activateGetPlace = function() {
          google.maps.event.trigger(scope.gPlace, 'place_changed');
        }

        scope.setFn({theDirFn: scope.activateGetPlace});

      }
    };
  });

  var mechanicsearch = angular.module('mechanicsearch', ['ngRoute','ngResource','ngAutocomplete']),
    radiusOptions = [];

mechanicsearch.run(function($rootScope) {
  $rootScope.$on('handleActiveJobsPanel', function(event, args) {
      $rootScope.$broadcast('activateJobsPanel', args);
  });
  $rootScope.$on('handleActiveFinalise', function(event, args) {
      $rootScope.$broadcast('activateFinalisePanel', args);
  });
  $rootScope.$on('handleActiveSearch', function(event, args) {
      $rootScope.$broadcast('activateSearchPanel', args);
  });
});

mechanicsearch.filter('htmlToPlaintext', function() {
  return function(text) {
    return  text ? String(text).replace(/<[^>]+>/gm, '') : '';
  };
});

// mechFactory service
mechanicsearch.factory('mechFactory', function($resource,$window) {
    var mechanics = [];
    var jobs = [];

    var addMechanic = function(mechanic){
      mechanics.push(mechanic);
    };

    var getAllMechanics = function(){
      return mechanics;
    };

    var removeAllMechanics = function() {
      mechanics = [];
    }

    var addJob = function(job) {
      jobs.push(job);
    }

    var getAllJobs = function() {
      return jobs;
    }

    var removeAllJobs = function() {
      jobs = [];
    }

    return {
      getMechanics: function(location,radius) {
        return $resource('/ajax/api.cfm?api=mechanic&function=getMechanicByLocation&lat=:lat&lng=:lng&radius=:radius' ).get({lat:location.lat,lng:location.lng,radius:radius});
      },
      getJobs: function() {
        return $resource('/ajax/api.cfm?api=job&function=getJobsAssignedtoWorkshop' ).get();
      },
      sendMechanicsJobNotifications: function(mechanics, jobs) {
        return $resource('/ajax/api.cfm?api=job&function=sendMechanicsJobNotifications&mechanics=:mechanics&jobs=:jobs' ).get({mechanics:mechanics.toString(),jobs:jobs.toString()});
      },
      addMechanic: addMechanic,
      removeAllMechanics: removeAllMechanics,
      getAllMechanics: getAllMechanics,
      addJob: addJob,
      removeAllJobs: removeAllJobs,
      getAllJobs: getAllJobs
    }
});

mechanicsearch.controller('SearchCtrl', ['$timeout', '$scope', '$window', '$location', '$routeParams', 'filterFilter', 'mechFactory', '$resource', '$element',

    function ($timeout, $scope, $window, $location, $routeParams, filterFilter, mechFactory, $resource, $element) {

        $scope.place = {};
        $scope.place.address = null;
        $scope.place.lat = null;
        $scope.place.lng = null;
        $scope.radius = 25;
        $scope.mechanics = [];
        $scope.selection = [];
        $scope.alert = null;
        $scope.showSearchPanel = true;

        //Helper method to get selected mechanics
        $scope.selectedMechanics = function selectedMechanics() {
          filterFilter($scope.mechanics, { selected: true })
        };

        //allow mechanic checkbox to select/deselect on click
        $scope.toggleMechanicSelect = function(mechanic) {
          mechanic.selected = !mechanic.selected;
        }

        $scope.goToJobListing = function() {
          $scope.showSearchPanel = false;
          mechFactory.removeAllMechanics();
          for( var i in $scope.selection ) {
            mechFactory.addMechanic($scope.selection[i]);
          }
          $scope.$emit('handleActiveJobsPanel');
        }

        // watch mechanics for changes
        $scope.$watch('mechanics|filter:{selected:true}', function (nv) {
         $scope.selection = nv.map(function (mechanic) {
           return mechanic.objectid;
         });
        }, true);

        //watch the returning google autocomplete details object
        $scope.$watch('details', function() {
          if( $scope.details !== undefined && $scope.details !== null ) {
            $scope.place.address = $scope.details.formatted_address;
            $scope.place.lat = $scope.details.geometry.location.lat();
            $scope.place.lng = $scope.details.geometry.location.lng();
          }
        });

        // watch the $scope.place data for changes
        $scope.$watchCollection('place', function() {
          if( $scope.place.lat !== null || $scope.place.lng !== null ) {
            $scope.getMechanics();
          }
        });

        $scope.$watch('radius', function() {
          if( Number.isInteger(parseInt($scope.radius))  ){
            $scope.getMechanics();
          }
        });

        $scope.setDirectiveFn = function(directiveFn) {
          $scope.directiveFn = directiveFn;
        };

        $scope.getMechanics = function() {
          mechFactory.getMechanics($scope.place, $scope.radius).$promise.then(
            function successfulResult (mechanicsData) {

              if (!mechanicsData || !mechanicsData.data.length){
                $scope.alert = 'Sorry, no mechanic found in "' + $scope.place.address + '" with radius of ' + $scope.radius + '.';
                $scope.mechanics = [];
                $scope.selection = [];
              } else {
                $scope.alert = mechanicsData.data.length + ' mechanic(s) found in "' + $scope.place.address + '" with radius of ' + $scope.radius + ' km.';
                $scope.mechanics = mechanicsData.data;
                $scope.selection = [];
              }

            }, function failedResult (err) {
              $scope.alert = err.message;
            });
        };

        //display panel once we have recieved the event
        $scope.$on('activateSearchPanel', function(event, args) {
          $scope.mechanics = [];
          $scope.selection = [];
          $scope.alert = null;
          $scope.showSearchPanel = true;
          $scope.place = {};
          $scope.radius = 25;
        });
    }
]);

              <form method="post" class="form-inline" role="form">

                          <input type="text" id="geoSearch" ng-model="autocomplete" class="form-control" ng-autocomplete options="{ types: 'geocode', country: 'au', watchEnter: true }" details="details" set-fn="setDirectiveFn(theDirFn)" />

                        <input type="text" class="form-control" name="radius" id="radius" placeholder="Radius" data-ng-model="radius">
                        <button class="btn btn-go" ng-click="directiveFn()">Go</button

              </form>

}


问:
How to unmount an Azure File Share
I've got a Windows Server VM on Azure. I also have a File Share. According to the MS documentation, one can mount the drive using the following command:

```<code>net use <drive-letter>: \\<storage-account-name>.file.core.windows.net\<share-name>
</code>```

This does indeed work.

Unfortunately, the documentation makes no mention of how to unmount the storage...

Does anyone know how to do this?

答:
how to unmount the storage

You can login your VM via RDP, then select network locations and select the file share disk. select disconnect.

Title: How to unmount an Azure File Share

Body:
I've got a Windows Server VM on Azure. I also have a File Share. According to the MS documentation, one can mount the drive using the following command:

net use <drive-letter>: \\<storage-account-name>.file.core.windows.net\<share-name>

This does indeed work.

Unfortunately, the documentation makes no mention of how to unmount the storage...

Does anyone know how to do this?


问:
How can I simplify this code?
I want to input a single argument (spend) to this function, and then have it return a string stating which of the 9 possibilities (plan500_90, plan500_80, etc.) is the lowest number.

It's currently working but seems much longer than it has to be.

```<code>def woof(spend):
    plan500_90 = 35.05 * 12
    plan500_80 = 32.63 * 12
    plan500_70 = 29.85 * 12
    plan250_90 = 42.66 * 12
    plan250_80 = 39.41 * 12
    plan250_70 = 35.80 * 12
    plan100_90 = 53.38 * 12
    plan100_80 = 49.10 * 12
    plan100_70 = 44.41 * 12

    if spend > 500:
        a = plan500_90 + spend - 0.90 * (spend - 500)
        b = plan500_80 + spend - 0.80 * (spend - 500)
        c = plan500_70 + spend - 0.70 * (spend - 500)
    else:
        a = plan500_90 + spend
        b = plan500_80 + spend
        c = plan500_70 + spend
    if spend > 250:
        d = plan250_90 + spend - 0.90 * (spend - 250)
        e = plan250_80 + spend - 0.80 * (spend - 250)
        f = plan250_70 + spend - 0.70 * (spend - 250)
    else:
        d = plan250_90 + spend
        e = plan250_80 + spend
        f = plan250_70 + spend
    if spend > 100:
        g = plan100_90 + spend - 0.90 * (spend - 100)
        h = plan100_80 + spend - 0.80 * (spend - 100)
        i = plan100_70 + spend - 0.70 * (spend - 100)
    else:
        g = plan100_90 + spend
        h = plan100_80 + spend
        i = plan100_70 + spend

    list1 = [a, b, c, d, e, f, g, h, i,]

    if min(list1) == a:
        print "Plan500_90 is the cheapest plan at $%d per year." % a
    elif min(list1) == b:
        print "Plan500_80 is the cheapest plan at $%d per year." % b
    elif min(list1) == c:
        print "Plan500_70 is the cheapest plan at $%d per year." % c
    elif min(list1) == d:
        print "Plan250_90 is the cheapest plan at $%d per year." % d
    elif min(list1) == e:
        print "Plan250_80 is the cheapest plan at $%d per year." % e
    elif min(list1) == f:
        print "Plan250_70 is the cheapest plan at $%d per year." % f
    elif min(list1) == g:
        print "Plan100_90 is the cheapest plan at $%d per year." % g
    elif min(list1) == h:
        print "Plan100_80 is the cheapest plan at $%d per year." % h
    elif min(list1) == i:
        print "Plan100_70 is the cheapest plan at $%d per year." % i
</code>```

答:
something like this will be a lot shorter. i haven't tested it, but should be ok.</p>

```<code>class Plan:
    def __init__(self, monthly_spend, min_spend, discount):
        self.yearly_spend = monthly_spend * 12
        self.min_spend = min_spend
        self.discount = discount

    def cost(self, spend):
        return float(self.yearly_spend + spend - self.discount * max(spend - self.min_spend, 0))

    def __str__(self):
        return 'Plan{}_{}'.format(self.min_spend, self.discount)

plans = [Plan(35.05, 500, .9), Plan(32.63, 500, .8)]  # TODO: fill in rest

def get_cheapest_plan(spend):
    cheapest_plan = min(plans, key=lambda x: x.cost(spend))
    print('{} is the cheapest plan at ${:.02} per year'.format(str(cheapest_plan), cheapest_plan.cost(spend))
</code>```

Title: How can I simplify this code?

Body:
I want to input a single argument (spend) to this function, and then have it return a string stating which of the 9 possibilities (plan500_90, plan500_80, etc.) is the lowest number.

It's currently working but seems much longer than it has to be.

def woof(spend):
    plan500_90 = 35.05 * 12
    plan500_80 = 32.63 * 12
    plan500_70 = 29.85 * 12
    plan250_90 = 42.66 * 12
    plan250_80 = 39.41 * 12
    plan250_70 = 35.80 * 12
    plan100_90 = 53.38 * 12
    plan100_80 = 49.10 * 12
    plan100_70 = 44.41 * 12

    if spend > 500:
        a = plan500_90 + spend - 0.90 * (spend - 500)
        b = plan500_80 + spend - 0.80 * (spend - 500)
        c = plan500_70 + spend - 0.70 * (spend - 500)
    else:
        a = plan500_90 + spend
        b = plan500_80 + spend
        c = plan500_70 + spend
    if spend > 250:
        d = plan250_90 + spend - 0.90 * (spend - 250)
        e = plan250_80 + spend - 0.80 * (spend - 250)
        f = plan250_70 + spend - 0.70 * (spend - 250)
    else:
        d = plan250_90 + spend
        e = plan250_80 + spend
        f = plan250_70 + spend
    if spend > 100:
        g = plan100_90 + spend - 0.90 * (spend - 100)
        h = plan100_80 + spend - 0.80 * (spend - 100)
        i = plan100_70 + spend - 0.70 * (spend - 100)
    else:
        g = plan100_90 + spend
        h = plan100_80 + spend
        i = plan100_70 + spend

    list1 = [a, b, c, d, e, f, g, h, i,]

    if min(list1) == a:
        print "Plan500_90 is the cheapest plan at $%d per year." % a
    elif min(list1) == b:
        print "Plan500_80 is the cheapest plan at $%d per year." % b
    elif min(list1) == c:
        print "Plan500_70 is the cheapest plan at $%d per year." % c
    elif min(list1) == d:
        print "Plan250_90 is the cheapest plan at $%d per year." % d
    elif min(list1) == e:
        print "Plan250_80 is the cheapest plan at $%d per year." % e
    elif min(list1) == f:
        print "Plan250_70 is the cheapest plan at $%d per year." % f
    elif min(list1) == g:
        print "Plan100_90 is the cheapest plan at $%d per year." % g
    elif min(list1) == h:
        print "Plan100_80 is the cheapest plan at $%d per year." % h
    elif min(list1) == i:
        print "Plan100_70 is the cheapest plan at $%d per year." % i

Body:
something like this will be a lot shorter. i haven't tested it, but should be ok.

class Plan:
    def __init__(self, monthly_spend, min_spend, discount):
        self.yearly_spend = monthly_spend * 12
        self.min_spend = min_spend
        self.discount = discount

    def cost(self, spend):
        return float(self.yearly_spend + spend - self.discount * max(spend - self.min_spend, 0))

    def __str__(self):
        return 'Plan{}_{}'.format(self.min_spend, self.discount)

plans = [Plan(35.05, 500, .9), Plan(32.63, 500, .8)]  # TODO: fill in rest

def get_cheapest_plan(spend):
    cheapest_plan = min(plans, key=lambda x: x.cost(spend))
    print('{} is the cheapest plan at ${:.02} per year'.format(str(cheapest_plan), cheapest_plan.cost(spend))


问:
Finding the Central city using coordinates that are user input
this is my prompt below:

```<code>/*
(Central city) Given a set of cities, the central city is the city that has the
shortest distance to all other cities. Write a program that prompts the user to enter the number of
cities and the locations of the cities (the coordinates are two decimal numbers), and finds the
central city and its total distance to all other cities.
*/
</code>```

for some reason when I try to run it, eclipse gives me this error:

```<code>Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2  at Testing.main(Testing.java:26)
</code>```

I did some tinkering and it seems that the problem arises when I try to make a two dimensional array with a column of 2. Is there a specific reason why this doesn't work? Or am I doing something wrong? Thanks in advance!

```<code>    import java.util.Scanner;
    public static void main(String[] args) {
    //Declarations
    int num_city;
    double[][] locations;
    Scanner keyboard = new Scanner(System.in);

    //input
    System.out.print("Please enter in the number of cities you want: ");
    num_city = keyboard.nextInt();
    locations = new double [num_city][2];

    System.out.print("Please enter the coordinates of the cities: ");
    for (int i = 0; i < locations.length; i++)
    {
        for (int x = 0; x < locations.length; x++)
        {
            locations[i][x] = keyboard.nextDouble();
        }
    }

    //Output
    getCentral(locations);

    }

    //method to find the index of the central city and total distance to other cities
    public static void getCentral(double[][] array)
    {
        //declarations
        double totalDistance = 0;
        int position = 0;
        double cityDistance;

        //processing
        for(int i =0; i < array.length; i++)
        {
            cityDistance = 0;
            for (int j = 0; j < array.length; j++)
            {
                cityDistance = Math.sqrt( Math.pow( (array[j][0] - array[i][0]), 2) + Math.pow( (array[j][1] - array[i][1]), 2) );
            }
            if ((i==0 || totalDistance > cityDistance))
            {
                totalDistance = cityDistance;
                position = i;
            }
        }
        System.out.print("The central city is at (" + array[position][0] + ", " + array[position][1] + ")");
        System.out.println("The total distance to the other cities are :" + totalDistance );
    }

}
</code>```

答:
Replace locations.length in the inner for loop with locations[0].length.

The reason why you are getting Array Out of bound exception is the fact that locations.length equates to num_city. So in your inner loop you are allowing x to go all the way up to num_city instead of just till 2.

For an array arr[row][col], arr.length = row but arr[i].length = col

Body:
this is my prompt below:

/*
(Central city) Given a set of cities, the central city is the city that has the
shortest distance to all other cities. Write a program that prompts the user to enter the number of
cities and the locations of the cities (the coordinates are two decimal numbers), and finds the
central city and its total distance to all other cities.
*/

for some reason when I try to run it, eclipse gives me this error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2  at Testing.main(Testing.java:26)

I did some tinkering and it seems that the problem arises when I try to make a two dimensional array with a column of 2. Is there a specific reason why this doesn't work? Or am I doing something wrong? Thanks in advance!

    import java.util.Scanner;
    public static void main(String[] args) {
    //Declarations
    int num_city;
    double[][] locations;
    Scanner keyboard = new Scanner(System.in);

    //input
    System.out.print("Please enter in the number of cities you want: ");
    num_city = keyboard.nextInt();
    locations = new double [num_city][2];

    System.out.print("Please enter the coordinates of the cities: ");
    for (int i = 0; i < locations.length; i++)
    {
        for (int x = 0; x < locations.length; x++)
        {
            locations[i][x] = keyboard.nextDouble();
        }
    }

    //Output
    getCentral(locations);

    }

    //method to find the index of the central city and total distance to other cities
    public static void getCentral(double[][] array)
    {
        //declarations
        double totalDistance = 0;
        int position = 0;
        double cityDistance;

        //processing
        for(int i =0; i < array.length; i++)
        {
            cityDistance = 0;
            for (int j = 0; j < array.length; j++)
            {
                cityDistance = Math.sqrt( Math.pow( (array[j][0] - array[i][0]), 2) + Math.pow( (array[j][1] - array[i][1]), 2) );
            }
            if ((i==0 || totalDistance > cityDistance))
            {
                totalDistance = cityDistance;
                position = i;
            }
        }
        System.out.print("The central city is at (" + array[position][0] + ", " + array[position][1] + ")");
        System.out.println("The total distance to the other cities are :" + totalDistance );
    }

}


问:
The reference to the class in ES6 is lost
I have the following structure Javacript es5-es6 and the controller class loses the reference in the class Get, I was already investigating but I can not find how to avoid losing the reference.</p>

```<code>class Controller {
    constructor() {
        this.name = 'Test';
    }
    test() {
        console.log(1, this.name);
    }
}

referenceController = new Controller();
// working reference: console.log(1, 'Test');
referenceController.test();

class Get {
    method() {
        return {
            controller: referenceController.test
        }
    }
}

// Lost self reference: console.log(1, undefined)
new Get().method().controller()
</code>```

答:
Your method function returns an object with key controller whose value is not a reference to the instance of the Controller class but a function that references this.

The this context of a method will be assigned to the object that it is attached to when it is invoked.

So new Get().method().controller()

Calls the method test where this is the value that new Get().method() resolves to which is:

```<code>{
  controller: referenceController.test
}
</code>```

Hence it logs out undefined

Amend your Get class as follows:

class Controller {
    constructor() {
        this.name = 'Test';
    }
    test() {
        console.log(1, this.name);
    }
}

referenceController = new Controller();
// working reference: console.log(1, 'Test');
referenceController.test();

class Get {
    method() {
        return {
            controller: referenceController
        }
    }
}

// this logs out correctly
new Get().method().controller.test();```

The above works because new Get().method().controller resolves to the Controller class instance referenceController that does have a property defined name with a value.

Body:
I have the following structure Javacript es5-es6 and the controller class loses the reference in the class Get, I was already investigating but I can not find how to avoid losing the reference.

class Controller {
    constructor() {
        this.name = 'Test';
    }
    test() {
        console.log(1, this.name);
    }
}

referenceController = new Controller();
// working reference: console.log(1, 'Test');
referenceController.test();

class Get {
    method() {
        return {
            controller: referenceController.test
        }
    }
}

// Lost self reference: console.log(1, undefined)
new Get().method().controller()

Body:
Your method function returns an object with key controller whose value is not a reference to the instance of the Controller class but a function that references this.

The this context of a method will be assigned to the object that it is attached to when it is invoked.

So new Get().method().controller()

Calls the method test where this is the value that new Get().method() resolves to which is:

{
  controller: referenceController.test
}

Hence it logs out undefined

Amend your Get class as follows:

class Controller {
    constructor() {
        this.name = 'Test';
    }
    test() {
        console.log(1, this.name);
    }
}

referenceController = new Controller();
// working reference: console.log(1, 'Test');
referenceController.test();

class Get {
    method() {
        return {
            controller: referenceController
        }
    }
}

// this logs out correctly
new Get().method().controller.test();

The above works because new Get().method().controller resolves to the Controller class instance referenceController that does have a property defined name with a value.


问:
What would be the best way to make a sort of drop-down-more-info div?
I have 4 divs with a more-info button on the bottom of each, like so:

http://codepen.io/anon/pen/VpVbPq

And when a user presses ' more info ' I would like for it to extend to the bottom and show extra info, obviously.

The problem is under the more-info div, text is seen, but what if I want to hide whats under it, even if its opacity is 0.6 ?

I thought it would've been the best if I draw what I need, so here:

Codepen code below:

html

```<code><body>
  <div class="wrapper">
  <div class="info">
      <p>
          dummy text
      </p>
        <div class="more-info">more info</div>
      </div>
      <div class="info"><div class="more-info">more info</div></div>
      <div class="info"><div class="more-info">more info</div></div>
      <div class="info"><div class="more-info">more info</div></div>
    </div>
</body>
</code>```

css

```<code>.wrapper  {
  width: 1045px;
  margin: 0 auto;
}
.info  {
  width: 500px; height: 200px;
  background-color: #1A5AB6;
  display: inline-block;
  margin: 10px;
  position: relative;
  font-size: 20px;
  overflow: hidden;
}
.more-info {
  width: 100%; height: 40px;
  background-color: #0C1B44;
  bottom: 0; left: 0;
  display: inline-block;
  position: absolute;
  font-size: 20px;
  color: white;
  line-height: 35px;
  text-align: center;
  opacity: 0.6;
}
.more-info:hover  {background-color: #010716;}
</code>```

答:
In order to have the text expand, you can use a little jQuery to set the height to automatically adapt to however much text there is, and hide the 'more info' button entirely:

```<code>$(".more-info").on("click", function() {
  $(this).css("opacity", "0");
  $(this).parent().css("height", "auto");
});
</code>```

With regards to not having the text visible behind the 'more info' button, you would need to set the opacity to 1:

```<code>.more-info {
  opacity: 1;
}
</code>```

This naturally distorts the colour a little, but you can always change the background colour and hover colour to cover this.

I've created an updated pen showcasing this here.

Hope this helps! :)

Body:
I have 4 divs with a more-info button on the bottom of each, like so:

http://codepen.io/anon/pen/VpVbPq

And when a user presses ' more info ' I would like for it to extend to the bottom and show extra info, obviously.

The problem is under the more-info div, text is seen, but what if I want to hide whats under it, even if its opacity is 0.6 ?

I thought it would've been the best if I draw what I need, so here:

Codepen code below:

html

          dummy text

more info

more info

more info

more info

css

.wrapper  {
  width: 1045px;
  margin: 0 auto;
}
.info  {
  width: 500px; height: 200px;
  background-color: #1A5AB6;
  display: inline-block;
  margin: 10px;
  position: relative;
  font-size: 20px;
  overflow: hidden;
}
.more-info {
  width: 100%; height: 40px;
  background-color: #0C1B44;
  bottom: 0; left: 0;
  display: inline-block;
  position: absolute;
  font-size: 20px;
  color: white;
  line-height: 35px;
  text-align: center;
  opacity: 0.6;
}
.more-info:hover  {background-color: #010716;}

Body:
In order to have the text expand, you can use a little jQuery to set the height to automatically adapt to however much text there is, and hide the 'more info' button entirely:

$(".more-info").on("click", function() {
  $(this).css("opacity", "0");
  $(this).parent().css("height", "auto");
});

With regards to not having the text visible behind the 'more info' button, you would need to set the opacity to 1:

.more-info {
  opacity: 1;
}

This naturally distorts the colour a little, but you can always change the background colour and hover colour to cover this.

I've created an updated pen showcasing this here.

Hope this helps! :)


答:
In for (int x = 0; x < locations.length; x++) the value of locations.length is whatever was entered for num_city ... that is, locations.length is the size of the first dimension of the 2d array.

When x becomes 2 (or more) it is too large for the second dimension of the array, which you have fixed at [2]

Arrays are zero-based so an array of length==2 has places for a[0] and a[1] so when x >= 2 it is out of bounds.

A multi-dimensional array is actually an array of arrays, so to get the length of the second dimension you need to reference one of the arrays in the first dimension, such as locations[0].length or, if in a loop, locations[i].length would work.

This is also important in your inner loop for (int j = 0; j < array.length; j++)

Here again, array.length is the size of the first dimension; in this loop you would want for (int j = 0; j < array[i].length; j++)

Title: Finding the Central city using coordinates that are user input


问:
SQL TRY_CONVERT DateTime vs DateTime2
I have a situation where I need to convert datetime string values in a column to a more standardised format, the converting process is quiet manual I am not just casting and storing.

So the script grabs the value, fumbles it around and stores it back in the same cell in a ODBC format. The thing is that I need to be able to check whether the value stored in the cell has already been converted or still needs to be processed as the script needs to be re-runnable.

So the example situation that I have is I come across the following two values:

```<code>08/03/2017 3:51 PM
28/03/2017 7:30 AM
</code>```

Now I know for a fact that it is day first.

If I use

```<code>TRY_CONVERT(DATETIME, [Value], 121)
</code>```

I will get the resulting value:

```<code>2017-08-03 15:51:00.000
NULL
</code>```

Now I would like to get is NULL for both, so it is correct for the second value but not the first and worse it swapped the day and month components for the first one.

However if I use

```<code>TRY_CONVERT(DATETIME2, [Value], 121)
</code>```

I do get NULL for both note, so my question is what is the difference in converting with DATETIME and DATETIME2? Why does DATETIME2 return NULL for the first?

I know that it is returning NULL for the second value because the first componentt is greater than 12.

Side note:

At the end of my script I end up with the ODBC form for the values (probably should be ISO?)

```<code>2016-06-07 03:23:17.000
2016-06-07 03:23:17.000
</code>```

When I run

```<code>TRY_CONVERT(DATETIME2, [Value], 121)
</code>```

I happily get not NULL values so I don't have to covert it :)

Title: SQL TRY_CONVERT DateTime vs DateTime2

Body:
I have a situation where I need to convert datetime string values in a column to a more standardised format, the converting process is quiet manual I am not just casting and storing.

So the script grabs the value, fumbles it around and stores it back in the same cell in a ODBC format. The thing is that I need to be able to check whether the value stored in the cell has already been converted or still needs to be processed as the script needs to be re-runnable.

So the example situation that I have is I come across the following two values:

08/03/2017 3:51 PM
28/03/2017 7:30 AM

Now I know for a fact that it is day first.

If I use

TRY_CONVERT(DATETIME, [Value], 121)

I will get the resulting value:

2017-08-03 15:51:00.000
NULL

Now I would like to get is NULL for both, so it is correct for the second value but not the first and worse it swapped the day and month components for the first one.

However if I use

TRY_CONVERT(DATETIME2, [Value], 121)

I do get NULL for both note, so my question is what is the difference in converting with DATETIME and DATETIME2? Why does DATETIME2 return NULL for the first?

I know that it is returning NULL for the second value because the first componentt is greater than 12.

Side note:

At the end of my script I end up with the ODBC form for the values (probably should be ISO?)

2016-06-07 03:23:17.000
2016-06-07 03:23:17.000

When I run

TRY_CONVERT(DATETIME2, [Value], 121)

I happily get not NULL values so I don't have to covert it :)

Body:
If you need to convert day first into ODBC canonical (with milliseconds), you can use set dateformat dmy and try_convert(datatype,val) without the style component.

Apply the 121 style after the conversion to datetime/datetime2 when converting back to char() for string storage.

create table t (dt varchar(32));
insert into t values ('08/03/2017 3:51 PM'),('28/03/2017 7:30 AM');

set dateformat dmy;
select
    dt
  , tryparse      = convert(char(23),try_parse(dt as datetime2(3)),121)
  , tryparseBrit  = convert(char(23),try_parse(dt as datetime2(3) using 'en-GB'),121)
  , tryconvert    = convert(char(23),try_convert(datetime2(3),dt),121)
  , tryconvert121 = convert(char(23),try_convert(datetime2(3),dt,121),121)
  , trycast       = convert(char(23),try_cast(dt as datetime2(3)),121)
from t

rextester demo: http://rextester.com/GFC92046

returns:

+--------------------+-------------------------+-------------------------+-------------------------+---------------+-------------------------+
|         dt         |        tryparse         |      tryparseBrit       |       tryconvert        | tryconvert121 |         trycast         |
+--------------------+-------------------------+-------------------------+-------------------------+---------------+-------------------------+
| 08/03/2017 3:51 PM | 2017-08-03 15:51:00.000 | 2017-03-08 15:51:00.000 | 2017-03-08 15:51:00.000 | NULL          | 2017-03-08 15:51:00.000 |
| 28/03/2017 7:30 AM | NULL                    | 2017-03-28 07:30:00.000 | 2017-03-28 07:30:00.000 | NULL          | 2017-03-28 07:30:00.000 |
+--------------------+-------------------------+-------------------------+-------------------------+---------------+-------------------------+

To select values that haven't been converted yet, you can use:

... where dt not like '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%'


问:
nodejs server not receiving any parameters from POST request
server.js:

```<code>    var express = require('express');
    var app = express();
    loggedIn = {};

    app.use('/',express.static('www')); // static files

    app.listen(8080, function () {
      console.log('Port 8080!');
    });

    app.get('/user', function(req, res) {
        if (typeof req.param('user') != 'undefined') {
            user = req.param('user');
            res.status(200).send('Works');
        }
    });

    app.post('/user', function(req, res) {
            user = req.param('user');
            if (typeof users[user] != 'undefined') {
                return res.status(405).send('Access Forbidden');
            } else {
                   loggedIn[user] = "";
                   res.status(201).send('New User');
            }
        }
    });
</code>```

client.js requests:

```<code>    $.ajax({
        method: "GET",
        url: "/user",
        data: {"user" : user},
        dataType: "application/json",
        success: function(data) {
            // success
        },
        error: function() {
            // error case
        }
    });

    $.ajax({
        method: "POST",
        url: "/user",
        data: {"user" : user},
        dataType: "application/json",
        success: function(data) {
            // success
        },
        error: function() {
            // error case
        }
    });
</code>```

Even though the GET request works exactly as expected and passes the parameter here, for some reason, the post request doesn't. In firebug, I notice the POST request receives no parameters whatsoever (POST user) while GET request does (GET user?user=XYZ). I am really at a loss right now.

答:
You have to tell your express app to parse the request body

```<code>app.use(express.bodyParser());
</code>```

for express 4+

```<code>var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/json
app.use(bodyParser.json())
</code>```

For reference goto https://expressjs.com/en/4x/api.html#req and look at the section titled req.body

Body:
server.js:

    var express = require('express');
    var app = express();
    loggedIn = {};

    app.use('/',express.static('www')); // static files

    app.listen(8080, function () {
      console.log('Port 8080!');
    });

    app.get('/user', function(req, res) {
        if (typeof req.param('user') != 'undefined') {
            user = req.param('user');
            res.status(200).send('Works');
        }
    });

    app.post('/user', function(req, res) {
            user = req.param('user');
            if (typeof users[user] != 'undefined') {
                return res.status(405).send('Access Forbidden');
            } else {
                   loggedIn[user] = "";
                   res.status(201).send('New User');
            }
        }
    });

client.js requests:

    $.ajax({
        method: "GET",
        url: "/user",
        data: {"user" : user},
        dataType: "application/json",
        success: function(data) {
            // success
        },
        error: function() {
            // error case
        }
    });

    $.ajax({
        method: "POST",
        url: "/user",
        data: {"user" : user},
        dataType: "application/json",
        success: function(data) {
            // success
        },
        error: function() {
            // error case
        }
    });

Even though the GET request works exactly as expected and passes the parameter here, for some reason, the post request doesn't. In firebug, I notice the POST request receives no parameters whatsoever (POST user) while GET request does (GET user?user=XYZ). I am really at a loss right now.

Body:
You have to tell your express app to parse the request body

app.use(express.bodyParser());

for express 4+

var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/json
app.use(bodyParser.json())

For reference goto https://expressjs.com/en/4x/api.html#req and look at the section titled req.body


问:
More terse way to filter Pandas dataframe?
The following code works.

```<code>df1 =  df.loc[lambda df: df.myfield == 'abc' , ['myfield' ,  'field2', 'field3','field4']]
print df1.iloc[:60]
</code>```

However I would just like to print out the selected columns of the first 60 entries of df matching my 'abc' condition in a single statement without this extra step of assigning to df1 then doing the 2nd iloc statement. I tried adding a 2nd condition in my lambda but could not get it to work.

答:
At the very least, you should be able to simplify this to:

```<code>print df.loc[df.myfield == 'abc', ['myfield', 'field2', 'field3', 'field4']].iloc[:60]
</code>```

generally, I would do something like:

```<code>row_selection = df.myfield == 'abc'
col_selection = ['myfield', 'field2', 'field3', 'field4']
print df.loc[row_selection, col_selection].iloc[:60]
</code>```

Body:
The following code works.

df1 =  df.loc[lambda df: df.myfield == 'abc' , ['myfield' ,  'field2', 'field3','field4']]
print df1.iloc[:60]

However I would just like to print out the selected columns of the first 60 entries of df matching my 'abc' condition in a single statement without this extra step of assigning to df1 then doing the 2nd iloc statement. I tried adding a 2nd condition in my lambda but could not get it to work.

Body:
At the very least, you should be able to simplify this to:

print df.loc[df.myfield == 'abc', ['myfield', 'field2', 'field3', 'field4']].iloc[:60]

generally, I would do something like:

row_selection = df.myfield == 'abc'
col_selection = ['myfield', 'field2', 'field3', 'field4']
print df.loc[row_selection, col_selection].iloc[:60]


问:
R data.table distance from ith element to every remaining element by group
Suppose I have the following data:

```<code>d = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45) )
</code>```

I want to see if each ith element in x by group id has an element between 30 and 40 greater than it. So for the first element in x by group id (1), I am looking to see if any value in x after 1 is between the values 31 and 41. The answer is yes, so I'd like to create a column valid_gap that is TRUE for the first element. In the end, I'm looking to get:

```<code>d_final = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45), valid_gap = c(T, T, F, F, F, F ) )
</code>```

I've thought about this question with a colleague for a little while, and we're really trying to avoid using a loop here but can't figure it out. Is this possible without a loop?

My best attempt is something like:

```<code>d[, valid_gap := any(between( rdist(x[ .N - .I ])[,1], left = 30, right = 40 )), by = id]
</code>```

but I'm thinking about the problem as trying to index through x as if in a loop, which I suspect is the wrong idea.

EDIT - "Bad" solution:

```<code>x = c(1, 10, 17, 35, 37, 45)
valid_gap = c()

for( i in 1:length(x) ) {
  if( i == length(x) ){
    valid_gap = c(valid_gap, F)
  } else {
    valid_gap = c(valid_gap, any(between( rdist( x[ x >= x[i] ] )[,1], left = 30, right = 40 )) )
  }
}
valid_gap
</code>```

Thank you in advance!

答:
```<code>library('data.table')
myfun <- function( y, z )
{
  any( z > y+30 & z < y+40 )  # check for values between the range
}
myfun <- Vectorize( FUN = myfun, vectorize.args = 'y')  # vectorize myfun() function for 'y' argument

d = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45) )
d[, valid_gap := myfun(y = x, z = x ), by = .(id)]
d
#    id  x valid_gap
# 1:  1  1      TRUE
# 2:  1 10      TRUE
# 3:  1 17     FALSE
# 4:  1 35     FALSE
# 5:  1 37     FALSE
# 6:  1 45     FALSE
</code>```

Body:
Suppose I have the following data:

d = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45) )

I want to see if each ith element in x by group id has an element between 30 and 40 greater than it. So for the first element in x by group id (1), I am looking to see if any value in x after 1 is between the values 31 and 41. The answer is yes, so I'd like to create a column valid_gap that is TRUE for the first element. In the end, I'm looking to get:

d_final = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45), valid_gap = c(T, T, F, F, F, F ) )

I've thought about this question with a colleague for a little while, and we're really trying to avoid using a loop here but can't figure it out. Is this possible without a loop?

My best attempt is something like:

d[, valid_gap := any(between( rdist(x[ .N - .I ])[,1], left = 30, right = 40 )), by = id]

but I'm thinking about the problem as trying to index through x as if in a loop, which I suspect is the wrong idea.

EDIT - "Bad" solution:

x = c(1, 10, 17, 35, 37, 45)
valid_gap = c()

for( i in 1:length(x) ) {
  if( i == length(x) ){
    valid_gap = c(valid_gap, F)
  } else {
    valid_gap = c(valid_gap, any(between( rdist( x[ x >= x[i] ] )[,1], left = 30, right = 40 )) )
  }
}
valid_gap

Thank you in advance!


问:
Monitortool for Realtime database of Firebase
Is there any tool to monitor the data transfer to my real time database in firebase? To see how many user connect at live time and how much data is transferred?</p>

答:
There's a usage tab in your Firebase Database console that has most of that information.

We also just released a tool that allows you to profile your database usage. See that tool's blog post and reference documentation.