Latest Entries »

Saturday, January 14, 2012

jQuery check if element has border

Sometimes you need to check if an html element has border for some reason. Normally we can use build in function css() for this purpose. But this approach is quite troublesome to find answer due to some facts: $(element).css('property') function returns window.getComputedStyle(element) . For border we have 4 css-computed rules:

.someClass{
    border: 1px solid black;
    /* is in fact computed in browser as */
    border-top-style: solid;
    border-right-style: solid;
    border-bottom-style: solid;
    border-left-style: solid;
}

To check if element has border we need to write something like this. Code is simple but in fact really ugly.

if ($(element).css('border-top-style') != 'none' && 
        $(element).css('border-right-style') != 'none' &&
        $(element).css('border-bottom-style') != 'none' &&
        $(element).css('border-left-style') != 'none'){
    //Has border
    }

Moreover code above may give you wrong result. Imagine situation when web-developer wrote:

.anotherFancyClass{
    /* only bottom border */
    border-bottom: 1px solid black;
    /* is in fact computed as */
    border-top-style: none;
    border-right-style: none;
    border-bottom-style: solid;
    border-left-style: none;
}

Now javascript if condition fail. You can change condition from AND to OR but it is still UGLY code.

Better solution


To check if element has border we will use another functions:

And here's a code and explaination:


$.fn.hasBorder = function() {
    /* outer contains: dimensions + padding + border */
    /* inner contains: dimensions + padding */
  if ((this.outerWidth() - this.innerWidth() > 0) ||  (this.outerHeight() - this.innerHeight() > 0)){
        return true;
    }
    else{
        return false;
    }
  };
  
  /* Usage */
  if ($('#selector').hasBorder()){
      //With border. Such more sophisticated ain't true?
  }

That's all.

Thursday, January 12, 2012

Android service with dynamic schedule time

Introduction

In this article I will show you how to write example android service which will be restarted after change user preferences. After changes are applied service will show toast with last execution time.


XML Files

First we will write some piece of code that will display preferences and will show them to user. Let's start from define xml with preferences:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Update frequency" >
        <ListPreference
            android:defaultValue="15 minut"
            android:entries="@array/listFrequency"
            android:entryValues="@array/listValues"
            android:key="Frequency"
            android:title="Change update frequency" />
    </PreferenceCategory>

</PreferenceScreen>

Here goes entries and entryValues from @array:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="listFrequency">
        <item>1 minuta</item>
        <item>2 minuty</item>
        <item>10 minut</item>
        <item>15 minut</item>
        <item>30 minut</item>
        <item>Wylaczone</item>
    </string-array>
    <string-array name="listValues">
        <item>60000</item>
        <item>120000</item>
        <item>600000</item>
        <item>900000</item>
        <item>1800000</item>
        <item>0000</item>
    </string-array>
</resources>

This xml will look like:

And don't forget to modify AndroidManifest.xml
<application>
     .....
        <service
            android:enabled="true"
            android:name=".service.BackgroundService" >
        </service>
    </application>
 <uses-permission android:name="android.permission.VIBRATE" />

Now let's code.

It's time to create Activity which will extend PreferenceActivity class. In this class we add OnSharedPreferenceChangeListener which will be called after change user preferences.
package com.stock_app.home;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.stock_app.R;
import com.stock_app.service.BackgroundService;

public class PreferencesActivity extends PreferenceActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
  SharedPreferences prefs = PreferenceManager
    .getDefaultSharedPreferences(this);
  prefs.registerOnSharedPreferenceChangeListener(prefchanged);
 }

 OnSharedPreferenceChangeListener prefchanged = new OnSharedPreferenceChangeListener() {

  @Override
  // Method for listening changes of SharedPreferences. 
  public void onSharedPreferenceChanged(
    SharedPreferences sharedPreferences, String key) {
   Intent serviceIntent = new Intent(getBaseContext(),
     BackgroundService.class);
   // Only if key was Frequency we will restart service. 
   if (key.equals("Frequency")) {
    String value = sharedPreferences.getString("Frequency", "0000");
    // If user turned of Service 
    if (value.equals("0000")) {
     stop(serviceIntent);
     String message = "Service is shut down.";
     Toast myToast = Toast.makeText(getApplicationContext(),
       message, Toast.LENGTH_SHORT);
     myToast.show();

    } else {
     // Oherwise restart
     stop(serviceIntent);
     start(serviceIntent);
    }

   }
  }
 };
 // Helper methods for start/stop service 
 private void start(Intent serviceIntent) {
  try {
   startService(serviceIntent);
  } catch (Exception e) {
   // If exception thrown means service is running 
   stopService(serviceIntent);
  }
 }

 private void stop(Intent serviceIntent) {
  try {
   stopService(serviceIntent);
  } catch (Exception e) {
   // If exception thrown means service not is running 
   startService(serviceIntent);
  }
 }
}

Now it's time for Service:

package com.stock_app.service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.IBinder;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

public class BackgroundService extends Service {

 private static final String TAG = BackgroundService.class.getSimpleName();
 private static int NOTIFICATION_ID = 1;
 private int icon = (Integer) 0x7f02000d;
 private Toast myToast;

 private Timer updatingTimer;
 public NotificationManager notificationmanager;
 public static boolean isGoing = false;
 SharedPreferences preferences = null;
 private TimerTask notify;

 @Override
 public void onCreate() {
  super.onCreate();

  if (!isGoing) {
   notify = new TimerTask() {
    @Override
    public void run() {
     checkValues();
    }
   };
   notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   updatingTimer = new Timer();
  }

 }

 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 @Override
 public void onDestroy() {
  updatingTimer.cancel();
  notify.cancel();
  super.onDestroy();
  isGoing = false;
 }

 public void onStart(Intent intent, int startId) {
  super.onStart(intent, startId);
  String message = "";
  isGoing = true;
  preferences = PreferenceManager.getDefaultSharedPreferences(this);
  try {

   String str_frequency = preferences
     .getString("Frequency", "1800000");
   long frequency = Long.parseLong(str_frequency);

   if (str_frequency.equals("60000")) {
    message = "Changed to one minute";

   } else if (str_frequency.equals("120000")) {
    message = "Changed to 2 minutes";
   } else if (str_frequency.equals("600000")) {
    message = "Changed to 10 minutes";

   } else if (str_frequency.equals("900000")) {
    message = "Changed to 15 minutes";

   } else if (str_frequency.equals("1800000")) {
    message = "Changed to 30 minutes";
   }

   // If running show toast:
   if (message != "" && message != "0000") {
    myToast = Toast.makeText(getApplicationContext(), message,
      Toast.LENGTH_SHORT);
    myToast.show();
   }

   updatingTimer.scheduleAtFixedRate(notify, 1 * 1000, frequency);
  } catch (Exception ex) {
   Log.i(TAG, ex.toString());
  }
 }

 public void displayNotificationMessage(String message) {
  Notification notif = new Notification(icon, message,
    System.currentTimeMillis());

  // enabling vibrate
  boolean checkVibration = preferences
    .getBoolean("checkVibration", false);
  if (checkVibration)
   vibrtationEnabled(notif);

  // enabling sound
  boolean checkSound = preferences.getBoolean("checkSound", false);
  if (checkSound)
   soundEnabled(notif);

  PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
    new Intent(this, BackgroundServiceActivity.class), 0);

  notif.setLatestEventInfo(this, "Notification!", message, contentIntent);
  notif.defaults |= Notification.DEFAULT_LIGHTS;
  notificationmanager.notify(NOTIFICATION_ID, notif);
  NOTIFICATION_ID++;
 }

 public void vibrtationEnabled(Notification notification) {
  long[] vibrate = { 0, 100, 200, 300 };
  Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
  vibrator.vibrate(vibrate, -1);

 }

 public static void soundEnabled(Notification notification) {
  notification.sound = Uri
    .parse("android.resource://com.stock.app/raw/notifsound");
  notification.defaults |= Notification.DEFAULT_SOUND;

 }

 public void checkValues() {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
  Calendar c = Calendar.getInstance();
  c.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH,
    Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND);
  Date time = c.getTime();
  displayNotificationMessage(sdf.format(time));
 }
}


Conclusion

This is a sample code that will make your life easier :) If you want full application source code @me.