Я безумен

2009-07-29

Небольшая доработка jTip

Filed under: Разработка,JS — thekillerfox @ 11:11 дп
Tags: , ,

Была поставлена задача сделать tooltip на сайте. Причем нужен он был только в одном месте, правда зная подход сегодня не нужно завтра нужно ,решил не заморачиваться, да и в верстке я не особо крут, поэтому решил воспользоваться плагином для jquery — jTip. Выглядит все симпатично, работает без нареканий, а так как на сайте уже использовался jQuery, то вообще все хорошо, вот только подгружает он страницы только извне. А меня бы вполне устроил функционал показать содержимое какого то скрытого блока как tooltip’a. И решил допилить.
Открываем jtip.js и находим там function JT_show(url,linkId,title)
Переходим к последней строчке $(‘#JT_copy’).load(url);
И заменяем ее на такую конструкцию

if (params['element_id']!==undefined)
$('#JT_copy').html($('#'+params['element_id']).html());
else
$('#JT_copy').load(url);

Вуаля, теперь чтобы загрузить не содержимое страницы, а содержимое блока, надо всего лишь передать id блока как параметр element_id в любом урле. Я делал вот так

Warning

Авось кому нибудь это поможет.

2009-07-9

Новости на сайте посредством twitter’a

Filed under: Идеи,Разработка,JS — thekillerfox @ 8:55 дп
Tags: ,

Twitter становится достаточно популярным, но немного не понятно для чего его стоит использовать большинству людей. Сообщать знакомым различные новости это интересно, но возможно можно придумать что то еще.
Предположим у нас есть сайт. На котором что то постоянно происходит (пользователи добавляют новые ссылки, какие то небольшие изменения функционала), как на таком сайте должны выглядеть новости на главной странице или в боковом блоке? Небольшое описание новости, и если нужно ссылка на более подробный текст. Будет неплохо если про эти новости смогут прочитать в twitter аккаунте вашего сайта, или подпишутся на rss ленту. Так зачем же делать все это у себя, пусть twitter возьмет на себя хранение всех новостей на вашем сайте. Соответственно они будут в твиттере, и rss к ним будет предоставлен. Как мне кажется это удобно. Да и добавлять новость на сайт можно будет почти мгновенно, и при этом даже если сайт ляжет, сообщение об этом можно будет быстро послать в твиттер. Минус данного подхода в ограничение в 140 символов, которое налагает твиттер. Но зато новостям придется быть краткими и ясными. А для более подробного разъяснения можно поместить ссылку.
Теперь рассмотрим несколько вариантов каким образом на главную страницу вашего сайта можно будет привнести твиттер.
Тут можно различать два подхода:
1) При формирование главной страницы скрипт получит список сообщений и выведет их.
2) При открытии страницы пользователь ява скрипт подгрузит новости сам, и покажет их пользователю.
Рассмотрим для начала первый вариант, он удобен тем что пользователь получает уже сформированную страницу, со всеми новостями, минус это то что мы должны устанавливать соединение и постоянно получать новости, что замедляет генерацию страниц, да и траффик дополнительные получается. Если мы реализуем серверную часть на php, то чтобы не разбираться самим с парсингом вывода twitter’a (а там очень много различных вариант на выбор, вот как надо реализовывать API) мы идем на phpclasses.
Больше всего мне понравился My Twitter класс, даже не потребовалось допиливание. К тому же устанавливать статус все равно понадобится, например если какой либо пользователь добавил статью. Но что делать если у нас нет backend’a (мифический случай), или же задержка генерации страницы нас не устраивает. Тут мы переходим к способу номер 2.

Этот способ хорош тем что всю работу получения новостей берет на себя браузер пользователя, к тому же если задать интервал обновления то можно сделать так что новые новости пользователь увидет даже если не будет обновлять страницу. Минус в том что если у пользователя выключен js он не увидет новостей. Да и их загрузка через некоторое время после открытия главной страницы тоже может не понравится пользователю, но ведь этот способ можно использовать и для другого, например если у нас есть пользователь с указанным в профиле твиттер аккаунтом, мы можем подгрузить в профиль последние обновления twitter’а этого пользователя.
Так как в последнее время я немного шаманю с jquery то первым делом я полез искать плагин работы с twitter’ом для него. Как никак у twitter’a есть json api и соответственно ничто не мешает реализовать твиттер клиент на js. Так как все придуманно до нас, то решение быстро нашлось, это jquery.twitter,причем новая версия вышла вчера. Как удачно. Скачиваем и смотрим что внутри. Рисунок загрузчика, css’ка, jquery, плагин к нему и страничка с демо.
Для формирования вывода используется Twitter HTML Badge Customizer, для этого в коде подключается внешний js файл.

$.getScript("http://twitter.com/javascripts/blogger.js");

там определенны две функции twitterCallback2 которая собственно и формирует HTML код, и relative_time для формирования относительного времени (это запись в виде 5 days ago), я подумал что относительно время это хорошо, но надо пожалуй как то это дело руссифицировать. Встала проблема, так как в русском языке существительные принято склонять. И тут вспомнилась одна статья на хабре: Склонение существительных с числительными , косметические изменения и у нас есть такая же функция, но только переписанная на JavaScript.

function plural(n, form1, form2, form5)
{
	n = Math.abs(n) % 100;
                n1 = n % 10;
                if (n > 10 && n < 20) return form5;
                else if (n1 > 1 && n1 < 5) return form2;
                else if (n1 == 1) return form1;

        return form5;
}

Теперь правим функцию relative_time и вуаля у нас теперь все как надо.

function relative_time(time_value) {
  var values = time_value.split(" ");
  time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
  var parsed_date = Date.parse(time_value);
  var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
  var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
  delta = delta + (relative_to.getTimezoneOffset() * 60);

  if (delta < 60) {
    return 'меньше минуты назад';
  } else if(delta < 120) {
    return 'около минуты назад';
  } else if(delta < (60*60)) {
    return (parseInt(delta / 60)).toString() + '  ' + plural((parseInt(delta / 60)).toString(),'минута','минуты','минут')+ ' назад';
  } else if(delta < (120*60)) {
    return 'около часа назад';
  } else if(delta < (24*60*60)) {
    return 'около ' + (parseInt(delta / 3600)).toString() + '  ' + plural((parseInt(delta / 3600)).toString(),'час','часа','часов')+ ' назад';
  } else if(delta < (48*60*60)) {
    return '1 день назад';
  } else {
    return (parseInt(delta / 86400)).toString() + ' ' + plural((parseInt(delta / 86400)).toString(),'день','дня','дней') +'  назад';
  }
}

Теперь у нас на повестке дня ссылка на rss. Что же идем на FeedIcons и скачиваем подходящие нам иконки. И делаем небольшую поправку в самом плагине.

if (o.showProfileLink) {
	var profileLinkHTML = "<p class=\"profileLink\"><a href=\"http://twitter.com/"+o.userName+"\">http://twitter.com/"+o.userName+"</a>&nbsp;<a href='http://twitter.com/statuses/user_timeline/"+o.userName+".rss'><img src='feed-icon.png'/></a></p>";
	c.append(profileLinkHTML);
}

Кстати чтобы не подгружать каждый раз blogger.js, да ведь мы и не можем ему менять, я просто закомментировал строку с его загрузкой, а исправленные функции, записал в конец jquery.twitter.js плагина.
Ниже можно скачать то что у меня получилось.
Скачать поправленный для себя jquery.twitter

Пользователям может не понравится такой способ предоставления новостей, но мне кажется есть ресурсы где это может пригодиться, к тому же так можно оживить даже статичный сайт. Мы же живем в эпоху mash-up’a, так почему бы и нет.
UPD: еще можно использовать Juitter , тоже очень интересный плагин, автоматическое обновление в случае появления новых твиттов, реплаи, показ аватаров, поиск. Но мне почему то jquery.twitter нравится больше, он менее нагружен как мне кажется.

2009-02-2

.Net CF программное управление bluetooth

Filed under: .NET,Разработка,Windows Mobile — thekillerfox @ 1:56 пп
Tags: , , , ,

Для начала нам нужно подключить пространство имен System.Runtime.InteropServices

using System.Runtime.InteropServices;

Теперь создаем свой класс :

public class Network
{
     public enum BluetoothMode
     {
          Off=0,
          Connectable=1,
          Discoverable=2
     }
     [DllImport("BthUtil.dll")]
     private static extern int BthGetMode(out BluetoothMode dwMode);
     [DllImport("BthUtil.dll")]
     public static extern int BthSetMode(BluetoothMode dwMode);
     public static String GetBthMode()
     {
          BluetoothMode mode;
          int ret = BthGetMode(out mode);
          return mode.ToString();
     }
}

Теперь мы можем попробовать переключить статусы. Например вот так :

if (Network.GetBthMode() == "Off")  //Проверяем текущее состояние
    Network.BthSetMode(Network.BluetoothMode.Connectable); //Переводим в состояние Connectable
else Network.BthSetMode(Network.BluetoothMode.Off); // или же выключаем

Как программно позвонить в WM5, WM6

Filed under: .NET,Разработка,Windows Mobile — thekillerfox @ 1:40 пп
Tags: , , , , ,

В Windows Mobile 6 был значительно расширен .Net Compact Framework и то для чего раньше требовалось много шаманство теперь делается в две строчки.
Например чтобы позвонить надо всего лишь подключить пространство имен конструкцией :

using Microsoft.WindowsMobile.Telephony;

А в коде создать экземпляр класса Microsoft.WindowsMobile.Telephony.Phone:

Phone phone = new Phone();phone.Talk("ваш номер тут");

Это очень удобно, но если вы пишете программы под Windows Mobile желательно не ориентироваться только на последнюю версию этой ОС, и обратить внимание еще на предыдущию версию, так как многие девайсы не имеют прошивок на WM6 или же прошивки неоффициальные и не каждый согласиться лишить себя гарантии прошивая непойми что.
Для этого можно подкючить OpenNet CF где уже реализована поддержка необходимых классов. Старая версия фреймворка доступна на бесплатной основе. Покопавшись в ней я выдернул класс отвечающий за звонки.
Для его работы надо подключить Пространство имен System.Runtime.InteropServices.

using System.Runtime.InteropServices;
public class PhoneTools {
   
    /// <summary>
    /// Make a voice call to the specified number.
    /// </summary>
    /// <param name=”destination”>A valid phone number to be dialled.</param>
    /// <returns>True if successful else False</returns>
    public static bool MakeCall(string destination)
    {
        return MakeCall(destination, false, null);
    }
   
    /// <summary>
    /// Make a voice call to the specified number optionally prompting the user before dialling.
    /// </summary>
    /// <param name=”destination”>A valid phone number to be dialled.</param>
    /// <param name=”prompt”>If True user will be prompted before call is made, else call will be made without user intervention.</param>   
    /// <returns>True if successful else False</returns>
    public static bool MakeCall(string destination, bool prompt)
    {
        return MakeCall(destination, prompt, null);
    }

    /// <summary>
    /// Make a voice call to the specified number optionally prompting the user before dialling.
    /// </summary>
    /// <param name=”destination”>A valid phone number to be dialled.</param>
    /// <param name=”prompt”>If True user will be prompted before call is made, else call will be made without user intervention.</param>
    /// <param name=”calledParty”>A display name for the party being called.</param>
    /// <returns>True if successful else False</returns>
   
    public static bool MakeCall(string destination, bool prompt, string calledParty)
    {
        //setup structure for native call
        MakeCallInfo mci = new MakeCallInfo();
        mci.cbSize = 24;
        mci.pszDestAddress = Apps.StringToHGlobalUni(destination);
        if(calledParty!=null)
        {
            mci.pszCalledParty = Apps.StringToHGlobalUni(calledParty);
        }
        if(prompt)
        {
            mci.dwFlags = CallFlags.PromptBeforeCalling;
        }
        else
        {
            mci.dwFlags = CallFlags.Default;
        }

        //call native function
        int result = PhoneMakeCall(ref mci);

        //free strings
        if(mci.pszDestAddress!=IntPtr.Zero)
        {
            Apps.FreeHGlobal(mci.pszDestAddress);
        }

        if(mci.pszCalledParty!=IntPtr.Zero)
        {
            Apps.FreeHGlobal(mci.pszCalledParty);
        }

        //check return value
        if(result==0) { return true; } else { return false; }
    }
    [DllImport("phone.dll", SetLastError = true)]
    private static extern int PhoneMakeCall(ref MakeCallInfo ppmci);
     //used internally by PhoneMakeCallInfo
    private struct MakeCallInfo
    {
        public int cbSize;
        public CallFlags dwFlags;
        public IntPtr pszDestAddress;
        IntPtr pszAppName;
        public IntPtr pszCalledParty;
        IntPtr pszComment;
    }

    /// <summary>
    /// Flags which determine the behaviour of the <see cref=”M:OpenNETCF.Phone.Phone.MakeCall”/> function.
    /// </summary>
    private enum CallFlags : int {
        /// <summary>
        /// Do not prompt, dial the supplied number.
        /// </summary>
        Default = 0&x00000001,
        /// <summary>
        /// Prompt the user whether to dial the supplied number.
        /// </summary>
         PromptBeforeCalling = 0&x00000002,
    }

}

Размещаем этот класс в собственной библиотеке, подключаем и используем просто:

PhoneTools phone = new PhoneTools();
PhoneTools.MakeCall("ваш номер");

Возможно этот трюк прокатит и в WM 2003, но я не проверял.

Блог на WordPress.com.