Oct 27

PHP Unset ArrayObject in foreach skip the following item – unexpected behaviour

When you unset the item from array in foreach, all works as expected

$array = [1,2,3,4];
foreach($array as $key => $value) {
  if($value === 2) {
    unset($array[$key]);
    continue;
  }
  echo "$value ";
}

Will return following:

1 3 4

When you want to do the same with ArrayObject, you would expect exactly the same behaviour. Unfortunately, it is not the case.

class MainList extends \ArrayObject {}
$arrayListObject = new MainList([1,2,3,4]);
foreach($arrayListObject as $key => $value) {
  if($value === 2) {
    unset($arrayListObject[$key]);
    continue;
  }
  echo "$value ";
}

Will return following:

1 4

See that the number 3 is missing in the response!!!
The reason for this is that the ArrayObject is behaving like object (not as an array) when looping through foreach.

This could be very confusing when you expect that that the foreach will process all the items.

The best option is to process it via

class MainList extends \ArrayObject {}
$arrayListObject = new MainList([1,2,3,4]);
foreach($arrayListObject->getArrayCopy() as $key => $value) {
  if($value === 2) {
    unset($arrayListObject[$key]);
    continue;
  }
  echo "$value ";
}

Will return following (as expected):

1 3 4

Feb 07

Updated script for downloading file from javascript

I had to use the ajax to download a file internally on our NestForms project. I was searching for a solution and found one on Filamentgroup website.

Unforutunatelly, there were some issues that it did not correctly encoded the request. So I had to update the script in order to make it working. See the code below. I hope that it will help you solve your problems.

jQuery.download = function(url, data, method){
  //url and data options required
  if( url && data ){
    //data can be string of parameters or array/object
    data = typeof data == 'string' ? data : jQuery.param(data);
    //split params into form inputs
    var inputs = new Array();
    jQuery.each(data.split('&'), function(){
      var pair = this.split('=');
      inputs[inputs.length] = $('<input name="'+ decodeURIComponent(pair[0]) +'" type="hidden" />')
        .val(decodeURIComponent( pair[1].replace(/\+/g, " ")));
    });
    //send request
    jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+'</form>').append(inputs)
    .appendTo('body').submit().remove();
  };
};

Jun 05

OnBeforeUnload fun

Yesterday, we have encountered issues regarding window.onbeforeunload function. We have implemented checking of json transport issues, but this throws errors, when the page is beeing unloaded and we needed to hide these errors.

So we implemented onBeforeUnload function, however we needed to preserve any previous onBeforeUnload functions. The issue here is that IE does not understand, that return value NULL is supposed to mean ‘Do not show the confirm’.

var origOnBeforeUnload = window.onbeforeunload;
window.onbeforeunload = function(event) {
  if(typeof origOnBeforeUnload === 'function') {
    return origOnBeforeUnload(event);
  }
}

We needed to implement little more robust checking, and when we do not want to show a message, you need to not return anything.

var origOnBeforeUnload = window.onbeforeunload;
window.onbeforeunload = function(event) {
  //do any code you want to
  if(typeof origOnBeforeUnload === 'function') {
    var out = origOnBeforeUnload(event);
    if(typeof out !== 'undefined' && out !== null && out !== false)
      return out;
    }
  }
}

Jan 29

jQuery simple-color-picker

We use simpleColorPicker jQuery plugin.

We had an issue that function .live() is depricated in jQuery 1.9.

We solved it by replacing following line:

Line 56: $(‘body’).live(‘click’, function() {

Correction: $(document).on(‘click’, ‘body’, function() {

Jan 11

PHP – Post name max length

Hi everyone,
I have found problem with PHP Version 5.3.2-1ubuntu4.18. When I tried to submit a form, values appeared in $HTTP_RAW_POST but there was nothing in $_POST. Problem was in legnth of name attribut. In other PHP versions is this length virtually unlimited, but in this version is length of each array key limited on 64 characters. Hope that this information will help someone :)


input type="text" id="text1" name="this_is_very_looooooooooooooooooooooooooooooooooooooooooong_name_which_will_not_submit_the_input" value="text"

Roman

Jun 11

Android – showing Google map in WebView

Hi everyone,

I have resolved my little problem with showing Google map via WebView. When I tried to show map in WebView, I had seen only white box and nothing more, after short delay loading animation appeared and it was all. I was finding solution, but nowhere was described what I am doing wrong. Solution was very simple – I had to set myWebView.getSettings().setJavaScriptEnabled(true); … Simple, isn’t it? :-) I hope that it will be helpful for someone who will has similar stupid problem. :-)

Dec 22

Android – Drawing route on MapView

Hi everyone,

I had quite big problem with drawing route on MapView. Tutorials on the web which I found are quite confusing or with bugs. So I took several of them and did own program, which using some code from several tutorials . Here is source of my map activity:

package tvarwebu.projects.map;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;

public class MapProjectActivity extends MapActivity {

GeoPoint myPoint = null;
GeoPoint nextPoint = null;
MapView map;
private Road mRoad;
int latSpan = -1;
boolean moving = false;
long lastTimestamp = 0;
int pointCount = 0;
int lat = 0;
int lng = 0;
Location currLoc = null;
OverlayItem currPoint;
MyItemizedOverlay currItemizedOverlay;
List<Overlay> mapOverlays;
LocationManager lm;

@Override
protected void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  map = (MapView) findViewById(R.id.mapView);
  map.setBuiltInZoomControls(true);
  map.setStreetView(true);
  map.setSatellite(false);

  // Your position initialize
  lat = 53324388;
  lng = -6263194;

  myPoint = new GeoPoint(lat, lng);

  Drawable drawable = this.getResources().getDrawable(
  R.drawable.flag_green);

  MyItemizedOverlay itemizedoverlay = new MyItemizedOverlay(drawable, this);

  OverlayItem overlayitem = new OverlayItem(myPoint, "Start Position", "Your start position");

  itemizedoverlay.addOverlay(overlayitem);

  // Position of next point
  int lat2 = 53348084;
  int lng2 = -6292434;

  nextPoint = new GeoPoint(lat2, lng2);

  OverlayItem overlayitem2 = new OverlayItem(nextPoint, "Position", "Position of next point");

  itemizedoverlay.addOverlay(overlayitem2);

  mapOverlays = map.getOverlays();
  mapOverlays.add(itemizedoverlay);

  Drawable draw2 = this.getResources().getDrawable(R.drawable.flag_red);

  MyItemizedOverlay over2 = new MyItemizedOverlay(draw2, this);
  over2.addOverlay(overlayitem2);

  mapOverlays.add(over2);

  // zooming to both points
  int maxLatitude = Math.max(lat, lat2);
  int minLatitude = Math.min(lat, lat2);
  int maxLongitude = Math.max(lng, lng2);
  int minLongitude = Math.min(lng, lng2);

  MapController mc = map.getController();
  mc.zoomToSpan(maxLatitude - minLatitude, maxLongitude - minLongitude);
  mc.animateTo(new GeoPoint((maxLatitude + minLatitude) / 2, (maxLongitude + minLongitude) / 2));

  map.invalidate();

  //Drawing path in new Thread
  new Thread() {

  @Override
  public void run() {
    double fromLat = Double.valueOf(myPoint.getLatitudeE6()) / 1000000.0,
    fromLon = Double.valueOf(myPoint.getLongitudeE6()) / 1000000.0;
    double toLat = Double.valueOf(nextPoint.getLatitudeE6()) / 1000000.0,
    toLon = Double.valueOf(nextPoint.getLongitudeE6()) / 1000000.0;

    String url = RoadProvider.getUrl(fromLat, fromLon, toLat, toLon);
    InputStream is = getConnection(url);
    mRoad = RoadProvider.getRoute(is);
    mHandler.sendEmptyMessage(0);
  }
}.start();

}

Handler mHandler = new Handler() {
  public void handleMessage(android.os.Message msg) {
    MapOverlay mapOverlay = new MapOverlay(mRoad, map);
    List<Overlay> listOfOverlays = map.getOverlays();
    // listOfOverlays.clear();
    listOfOverlays.add(mapOverlay);
    map.invalidate();
  };
};

private InputStream getConnection(String url) {
  InputStream is = null;
  try {
    URLConnection conn = new URL(url).openConnection();
    is = conn.getInputStream();
  } catch (MalformedURLException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
  return is;
}

@Override
protected boolean isRouteDisplayed() {
  // TODO Auto-generated method stub
  return false;
}
// Map extends overlay for drawing path
class MapOverlay extends com.google.android.maps.Overlay {
  Road mRoad;
  ArrayList<GeoPoint> mPoints;

  public MapOverlay(Road road, MapView mv) {
    mRoad = road;
    // mRoute is field of route points getting from Google Maps
    if (road.mRoute.length > 0) {
      mPoints = new ArrayList<GeoPoint>();
      for (int i = 0; i < road.mRoute.length; i++) {
        mPoints.add(new GeoPoint(
        (int) (road.mRoute[i][1] * 1000000),
        (int) (road.mRoute[i][0] * 1000000)));
      }
    }
  }

  @Override
  public void draw(Canvas canvas, MapView mv, boolean shadow) {
    drawPath(mv, canvas);
  }

  public void drawPath(MapView mv, Canvas canvas) {
    int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
    Paint paint = new Paint();
    latSpan = mv.getLatitudeSpan();
    paint.setColor(Color.parseColor("#998447cc"));
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(6);
    if (mPoints != null) {
      for (int i = 0; i < mPoints.size(); i++) {
        Point point = new Point();
        mv.getProjection().toPixels(mPoints.get(i), point);
        x2 = point.x;
        y2 = point.y;
        if (i > 0) {
          canvas.drawLine(x1, y1, x2, y2, paint);
        }
        x1 = x2;
        y1 = y2;
      }
    }
  }
}
}

In addition, you will need this files:

1. Road.java

package tvarwebu.projects.map;

public class Road {
public String mName;
public String mDescription;
public int mColor;
public int mWidth;
public double[][] mRoute = new double[][] {};
public Point[] mPoints = new Point[] {};

}

2. Point.java

package tvarwebu.projects.map;

public class Point {
  String mName;
  String mDescription;
  String mIconUrl;
  double mLatitude;
  double mLongitude;
}

3. RoadProvider.java

package tvarwebu.projects.map;

import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class RoadProvider {

public static Road getRoute(InputStream is) {
  KMLHandler handler = new KMLHandler();
  try {
    SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
    parser.parse(is, handler);
  } catch (ParserConfigurationException e) {
    e.printStackTrace();
  } catch (SAXException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
  return handler.mRoad;
}

public static String getUrl(double fromLat, double fromLon, double toLat, double toLon) {// connect to map web service
  StringBuffer urlString = new StringBuffer();
  urlString.append("http://maps.google.com/maps?f=d&hl=en");
  urlString.append("&saddr=");// from
  urlString.append(Double.toString(fromLat));
  urlString.append(",");
  urlString.append(Double.toString(fromLon));
  urlString.append("&daddr=");// to
  urlString.append(Double.toString(toLat));
  urlString.append(",");
  urlString.append(Double.toString(toLon));
  urlString.append("&ie=UTF8&0&om=0&output=kml");

  String ggg = urlString.toString();
  return urlString.toString();
}
}

class KMLHandler extends DefaultHandler {
  Road mRoad;
  boolean isPlacemark;
  boolean isRoute;
  boolean isItemIcon;
  private Stack mCurrentElement = new Stack();
  private String mString;

  public KMLHandler() {
  mRoad = new Road();
}

public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
  mCurrentElement.push(localName);
  if (localName.equalsIgnoreCase("Placemark")) {
    isPlacemark = true;
    mRoad.mPoints = addPoint(mRoad.mPoints);
  } else if (localName.equalsIgnoreCase("ItemIcon")) {
    if (isPlacemark)
      isItemIcon = true;
    }
    mString = new String();
  }

  public void characters(char[] ch, int start, int length) throws SAXException {
    String chars = new String(ch, start, length).trim();
    mString = mString.concat(chars);
  }

  public void endElement(String uri, String localName, String name) throws SAXException {
    if (mString.length() > 0) {
      if (localName.equalsIgnoreCase("name")) {
        if (isPlacemark) {
          isRoute = mString.equalsIgnoreCase("Route");
          if (!isRoute) {
            mRoad.mPoints[mRoad.mPoints.length - 1].mName = mString;
          }
        } else {
          mRoad.mName = mString;
        }
      } else if (localName.equalsIgnoreCase("color") && !isPlacemark) {
        mRoad.mColor = Integer.parseInt(mString, 16);
      } else if (localName.equalsIgnoreCase("width") && !isPlacemark) {
        mRoad.mWidth = Integer.parseInt(mString);
      } else if (localName.equalsIgnoreCase("description")) {
        if (isPlacemark) {
          String description = cleanup(mString);
          if (!isRoute)
            mRoad.mPoints[mRoad.mPoints.length - 1].mDescription = description;
          else
            mRoad.mDescription = description;
        }
      } else if (localName.equalsIgnoreCase("href")) {
        if (isItemIcon) {
          mRoad.mPoints[mRoad.mPoints.length - 1].mIconUrl = mString;
        }
      } else if (localName.equalsIgnoreCase("coordinates")) {
        if (isPlacemark) {
          if (!isRoute) {
            String[] xyParsed = split(mString, ",");
            double lon = Double.parseDouble(xyParsed[0]);
            double lat = Double.parseDouble(xyParsed[1]);
            mRoad.mPoints[mRoad.mPoints.length - 1].mLatitude = lat;
            mRoad.mPoints[mRoad.mPoints.length - 1].mLongitude = lon;
          } else {
            String[] coodrinatesParsed = split(mString, " ");
            int count = 0;
            if(mRoad.mRoute.length < 2)
              mRoad.mRoute = new double[coodrinatesParsed.length][2];
            else {
              double[][] mRouteTmp = mRoad.mRoute;
              mRoad.mRoute = new double[mRouteTmp.length + coodrinatesParsed.length][2];
              //for (int i = 0; i < mRouteTmp.length; i++) {
              //mRoad.mRoute[i] = mRouteTmp[i];
              //mRoad.mRoute[i][i] = mRouteTmp[i][i];
              //}
              System.arraycopy(mRouteTmp, 0, mRoad.mRoute, 0, mRouteTmp.length);

              count = mRouteTmp.length;
            }

            for (int i = count; i < (mRoad.mRoute.length); i++) {
              String[] xyParsed = split(coodrinatesParsed[i - count], ",");
              for (int j = 0; j < 2 && j < xyParsed.length; j++)
                mRoad.mRoute[i][j] = Double.parseDouble(xyParsed[j]);
            }
          }
        }
      }
    }
    mCurrentElement.pop();
    if (localName.equalsIgnoreCase("Placemark")) {
      isPlacemark = false;
      if (isRoute)
      isRoute = false;
    } else if (localName.equalsIgnoreCase("ItemIcon")) {
      if (isItemIcon)
        isItemIcon = false;
    }
  }

  private String cleanup(String value) {
    String remove = "<br/>";
    int index = value.indexOf(remove);
    if (index != -1)
    value = value.substring(0, index);
    remove = " ";
    index = value.indexOf(remove);
    int len = remove.length();
    while (index != -1) {
      value = value.substring(0, index).concat(
      value.substring(index + len, value.length()));
      index = value.indexOf(remove);
    }
    return value;
  }

  public Point[] addPoint(Point[] mPoints) {
    Point[] result = new Point[mPoints.length + 1];
    for (int i = 0; i < mPoints.length; i++)
      result[i] = mPoints[i];
    result[mPoints.length] = new Point();
    return result;
  }

  private static String[] split(String strString, String strDelimiter) {
    String[] strArray;
    int iOccurrences = 0;
    int iIndexOfInnerString = 0;
    int iIndexOfDelimiter = 0;
    int iCounter = 0;
    if (strString == null) {
      throw new IllegalArgumentException("Input string cannot be null.");
    }
    if (strDelimiter.length() <= 0 || strDelimiter == null) {
      throw new IllegalArgumentException("Delimeter cannot be null or empty.");
    }
    if (strString.startsWith(strDelimiter)) {
      strString = strString.substring(strDelimiter.length());
    }
    if (!strString.endsWith(strDelimiter)) {
      strString += strDelimiter;
    }
    while ((iIndexOfDelimiter = strString.indexOf(strDelimiter,
      iIndexOfInnerString)) != -1) {
      iOccurrences += 1;
      iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
    }

    strArray = new String[iOccurrences];
    iIndexOfInnerString = 0;
    iIndexOfDelimiter = 0;
    while ((iIndexOfDelimiter = strString.indexOf(strDelimiter,
      iIndexOfInnerString)) != -1) {
      strArray[iCounter] = strString.substring(iIndexOfInnerString,
      iIndexOfDelimiter);
      iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
      iCounter += 1;
    }

    return strArray;
  }
}

4. MyItemizedOverlay.java :

package tvarwebu.projects.map;

import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
  private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
  private Context mContext;

  public MyItemizedOverlay(Drawable defaultMarker, Context context) {
    super(boundCenterBottom(defaultMarker));
    mContext = context;
  }

  public void addOverlay(OverlayItem overlay) {
    mOverlays.add(overlay);
    populate();
  }

  @Override
  protected OverlayItem createItem(int i) {
    return mOverlays.get(i);
  }

  @Override
  public int size() {
    return mOverlays.size();
  }

  public void removeLast(){
    mOverlays.remove(mOverlays.size()-1);
  }

  @Override
  protected boolean onTap(int index) {
    OverlayItem item = mOverlays.get(index);
    AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
    dialog.setTitle(item.getTitle());
    dialog.setMessage(item.getSnippet());
    dialog.show();
    return true;
  }
}

When you change names of package, you should get this screen after launch:

Hope that this article helps you with this problem :) See the comple source code of Drawing route on MapView.

by Roman Holomek,  TvářWebu