Tweetmatic

var TM = {};

(function() {
  TM = {
    accountUserUsernameRegex: /^[a-zA-Z0-9_]{1,15}$/gi,
    debug: false,
    loggedIn: false,
    pageUrl: "",
    updateTimelines: true,
    setupState: "none",
    timerRateLimits: 30,
    timerTimespans: 20,
    timerUpdates: 30,
    tweetPending_Id: 1,
    tweetPendingImage: "/Content/images/pool_pending.png",
    tweetApproved_Id: 2,
    tweetApprovedImage: "/Content/images/pool_approved.png",
    tweetType: "New",
    tweetReplyId: "",
    tweetReplyFromAccount: "",
    tweetReplyFromAccountId: 0,
    tweetTokens: [],
    tweetMaxLength: 140,
    tweetCharsRemaining: 0,
    tweetDefaultAction: "TweetNow",
    tweetLinkRegex: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])/gi,
    tweetLinkReplace: "<a href=\"$1\" data-mediatype=\"\" data-mediaurl=\"\" data-mediaid=\"\" title=\"Jump to $1\" target=\"_blank\" class=\"bluecolor\">$1</a>",
    tweetUserRegex: /(@([_a-z0-9\-]+))/gi,
    tweetUserReplace: "<a href=\"http://twitter.com/$2\" title=\"Browse $2\" target=\"_blank\" class=\"bluecolor\">$1</a>",
    tweetHashtagRegex: /(#([_a-z0-9\-]+))/gi,
    tweetHashtagReplace: "<a href=\"http://search.twitter.com/search?q=%23$2\" title=\"Search $1\" target=\"_blank\" class=\"bluecolor\">$1</a>",
    urlShortenerRegex: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])\s/gi,
    urlShortenerRegexNoEndingSpace: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])/gi,
    init: function() {
      $.views.allowCode = true;
      $.views.registerTags({
        formatTwitterDate: function(content) {
          return TM.timeSpanString($.render(content, this.data));
        }
      });

      var $Notification = $("#Notification");

      if ($Notification.find("span").length > 0) $("#Notification").css("display", "block");

      $(".hideTips").click(function() {
        TM.saveSetting("#chkShowTipsInHeader", "checkbox", "ShowHeaderTips", "No");
        $Notification.fadeOut("fast", function() {
          $(this).empty();
        });
      });
      $("#MainNav li a[href=\"" + TM.pageUrl + "\"]").addClass("pageAnchor");
      $("#AdminNav li a[href=\"" + TM.pageUrl + "\"]").addClass("pageAnchor");
      if (!TM.loggedIn) {
        $("#loginpanel input.returnForLogin").keyup(function(e) {
          if (e.keyCode == $.ui.keyCode.ENTER) {
            $("#signinlink").click();
          }
        });
      }

      TM.updateSetup();

      // for Chrome, hide the yellow color for visited fields
      $('input.noautocomplete').attr('autocomplete', 'off');
    },
    updateSetup: function() {
      var $accountSetupModal = $("#FirstTimePanel");
      if ($accountSetupModal.length > 0) {
        if (TM.setupState == "notwitteridentities" && TM.queryString("a") == "") {
          $accountSetupModal.find("p.firstTimeMessage").text("Click OK to add a twitter identity to your Tweetmatic account.");
          $accountSetupModal.find("a.btnFirstTimeCancel").unbind("click").click(TM.quitSetup);
          $accountSetupModal.find("a.btnFirstTimeOK").unbind("click").click(function() {
            window.location = "/Settings?a=openaddti";
          });
          $accountSetupModal.modal();
        } else if (TM.setupState == "noauthorizedtwitteridentities" && TM.queryString("a") == "") {
          $accountSetupModal.find("p.firstTimeMessage").text("Click OK to authorize your twitter identity so that Tweetmatic is allowed to post on your behalf.");
          $accountSetupModal.find("a.btnFirstTimeCancel").unbind("click").click(TM.quitSetup);
          $accountSetupModal.find("a.btnFirstTimeOK").unbind("click").click(function() {
            window.location = "/Settings?a=openoauth";
          });
          $accountSetupModal.modal();
        }
      }
    },
    quitSetup: function() {
      $.modal.close();
      TM.setupState = "complete";
      $.ajax({
        url: "/Account/QuitSetup",
        data: {},
        dataType: "json",
        type: 'POST',
        success: function(data) {},
        complete: function() {},
        error: function(XMLHttpRequest, textStatus, errorThrown) {}
      });
    },
    queryString: function(key) {
      key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
      var regexS = "[\\?&]" + key + "=([^&#]*)";
      var regex = new RegExp(regexS);
      var results = regex.exec(window.location.href);
      if (results == null) return "";
      else return decodeURIComponent(results[1].replace(/\+/g, " "));
    },
    showMessage: function(el, message, type) {
      type = type.toLowerCase();
      if (message == null || message == "") message = "&nbsp;";
      var className = (type == "error" ? "statusError" : (type == "success" ? "statusSuccess" : (type == "loading" ? "statusLoading" : (type == "info" ? "statusInfo" : ""))));
      $(el).removeClass("statusError statusLoading statusSuccess statusInfo").empty().html(message);
      if (className != "") $(el).addClass(className);
    },
    twitterOAuthPopup: function(returnUrl) {
      window.open("/Twitter/GetRequestToken?ReturnUrl=" + escape(returnUrl) + "", "tm_oauth_popup", "width=750,height=700,toolbar=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,modal=yes");
    },
    twitterOAuthPopupCallback: function() {
      var url = TM.queryString("ReturnUrl");
      if (url != null && url != "") {
        if (url == "/Account" && !window.opener.closed) {
          window.opener.reloadTwitterIdentities();
        } else {
          window.opener.location.href = url;
        }
      } else {
        window.opener.location.reload();
      }
      window.close();
    },
    setSetting: function(formSelector, elementType, settingName, settingValue) {
      $(formSelector).attr("data-setting", settingValue);
      if (elementType == "checkbox") {
        if (settingValue.toString().toLowerCase() == "yes") $(formSelector).attr("checked", "checked");
        else $(formSelector).removeAttr("checked");
      } else if (elementType == "select" || elementType == "textbox" || elementType == "textarea") $(formSelector).val(settingValue);
      // alert("setting " + formSelector + " to " + settingValue + " (" + settingName + ")");
    },
    getSetting: function(formSelector, elementType, settingName) {
      $.ajax({
        url: "/Account/GetAccountUserSetting",
        data: {
          SettingName: settingName
        },
        dataType: "json",
        type: 'POST',
        success: function(data) {
          if (formSelector != "") TM.setSetting(formSelector, elementType, settingName, data.SettingValue);
        },
        complete: function() {},
        error: function(XMLHttpRequest, textStatus, errorThrown) {}
      });
    },
    saveSetting: function(formSelector, elementType, settingName, settingValue) {
      if (settingName == null || settingValue == null || settingName == "") return;
      $.ajax({
        url: "/Account/SaveAccountUserSetting",
        data: {
          SettingName: settingName,
          SettingValue: settingValue
        },
        dataType: "json",
        type: 'POST',
        success: function(data) {
          if (formSelector != null && formSelector != "") {
            $(formSelector).attr("data-setting", settingValue);
            if (formSelector == "#chkShowTipsInHeader" && $(formSelector).length > 0) TM.setSetting(formSelector, elementType, settingName, settingValue);
          }
        },
        complete: function() {},
        error: function(XMLHttpRequest, textStatus, errorThrown) {}
      });
    },
    updateTweetCounter: function(tweetId, counterId) {
      var txt = $(tweetId).val();
      TM.tweetCharsRemaining = TM.tweetMaxLength - txt.length;
      $(counterId).text(TM.tweetCharsRemaining);
    },
    ScheduledDate: function(strDate) {
      var date = TM.GetDateFromJsonDate(strDate);
      return TM.ShortDateTime(date);
    },
    shortenLinksHistory: [],
    resetShortenLinksHistory: function() {
      TM.shortenLinksHistory = [];
    },
    shortenLinksHistoryList: function() {
      var list = [];
      for (var i = 0; i <= TM.shortenLinksHistory.length - 1; i++) {
        list.push(TM.shortenLinksHistory[i].LongUrl + " => " + TM.shortenLinksHistory[i].ShortUrl + "\n");
      }
      return list.join(", ");
    },
    shortenLinksLocalCache: function(arr, selectorForTextArea, selectorForTweetCounter, requireEndingSpace) {
      var found = false;
      var txt = String($(selectorForTextArea).val());
      var oldTxt = txt;
      var i = 0;
      var initialCount = arr.length;
      var medialCount = 0;
      var finalCount = 0;
      while (i <= arr.length - 1) {
        if (arr[i].indexOf("bit.ly") > -1 || arr[i].length <= 20) {
          arr.splice(i, 1);
          i--;
        }
        i++;
      }
      medialCount = arr.length;
      for (var i = 0; i <= TM.shortenLinksHistory.length - 1; i++) {
        while (txt.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")) > -1)
        txt = txt.replace(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : ""), TM.shortenLinksHistory[i].ShortUrl + (requireEndingSpace ? " " : ""));
        while (arr.length > 0 && arr.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")) > -1)
        arr.splice(arr.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")), 1);
        while (txt.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")) > -1)
        txt = txt.replace(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : ""), TM.shortenLinksHistory[i].ShortUrl + (requireEndingSpace ? " " : ""));
        while (arr.length > 0 && arr.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")) > -1)
        arr.splice(arr.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")), 1);
      }
      finalCount = arr.length;
      if (txt != oldTxt) {
        $(selectorForTextArea).val(txt);
        TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
      }
      return arr;
    },
    shortenLinksDetector: function(selectorForTextArea, selectorForTweetCounter, checkForLinks, requireEndingSpace) {
      if (!checkForLinks) return;
      var txt = String($(selectorForTextArea).val());
      var m = txt.match(requireEndingSpace ? TM.urlShortenerRegex : TM.urlShortenerRegexNoEndingSpace);
      if (m != null && m.length > 0) {
        m = TM.shortenLinksLocalCache(m, selectorForTextArea, selectorForTweetCounter);
        if (m.length > 0) TM.shortenLinks(m, selectorForTextArea, selectorForTweetCounter, requireEndingSpace);
      }
    },
    shortenLinks: function(arr, selectorForTextArea, selectorForTweetCounter, requireEndingSpace) {
      var urls = $.trim(arr.join(" "));
      if (urls == "") return;
      $.ajax({
        url: "/Tweet/ShortenLinksBitLy",
        data: {
          url: urls
        },
        dataType: "json",
        type: 'POST',
        success: function(data) {
          if (data != null && data.length > 0) {
            var ta = $(selectorForTextArea);
            var txt = String(ta.val());
            for (var i = 0; i <= data.length - 1; i++) {
              if (data[i].ShortUrl.indexOf("Error: Status code") == -1) {
                txt = txt.replace(data[i].LongUrl + (requireEndingSpace ? " " : ""), data[i].ShortUrl + (requireEndingSpace ? " " : "")).replace(data[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : ""), data[i].ShortUrl + (requireEndingSpace ? " " : ""));
                TM.shortenLinksHistory.push(data[i]);
              }
            }
            $(selectorForTextArea).val(txt);
            TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
          }
        },
        complete: function() {},
        error: function(XMLHttpRequest, textStatus, errorThrown) {
          TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
        }
      });
    },
    stripeTweetList: function(selector) {
      if ($(selector + " li:not(.norecords)").length > 0) $(selector + " li.norecords").hide();
      else $(selector + " li.norecords").show();

      $(selector + " li:visible").removeClass("odd").removeClass("even");
      $(selector + " li:visible:odd").addClass("odd");
      $(selector + " li:visible:even").addClass("even");
      $(selector + " li span.tweet_application a").attr("target", "_blank");
    },
    stripeTable: function(selector) {
      if ($(selector + " tbody tr:not(.norecords)").length > 0) $(selector + " tbody tr.norecords").hide();
      else $(selector + " tbody tr.norecords").show();

      $(selector + " tbody tr:visible").removeClass("odd").removeClass("even");
      $(selector + " tbody tr:visible:odd").addClass("odd");
      $(selector + " tbody tr:visible:even").addClass("even");
    },
    fixupTweetText: function(dataItem) {
      var txt = String(dataItem.text);
      txt = txt.replace(TM.tweetLinkRegex, TM.tweetLinkReplace);
      txt = txt.replace(TM.tweetUserRegex, TM.tweetUserReplace);
      txt = txt.replace(TM.tweetHashtagRegex, TM.tweetHashtagReplace);
      if (dataItem.entities != null && dataItem.entities.urls != null && dataItem.entities.urls.length > 0) {
        for (var i = 0; i <= dataItem.entities.urls.length - 1; i++) {
          var item = dataItem.entities.urls[i];
          if (item != null && item.display_url != null) {
            var mediaType = "none";
            var mediaUrl = "none";
            var mediaID = "";
            var suffix = "";
            if (item.display_url.indexOf("yfrog") > -1) {
              suffix = item.display_url.substring(item.display_url.length - 1, item.display_url.length);
              // j; JPEG p; PNG b; BMP t; TIFF g; GIF s; SWF d; PDF f; FLV z; MP4 x; Gallery
              if (suffix == "j" || suffix == "p" || suffix == "b" || suffix == "t" || suffix == "g") {
                mediaType = "photo";
                mediaUrl = item.expanded_url + ":iphone";
              } else if (suffix == "x" || suffix == "z") {
                mediaType = "video";
                mediaUrl = item.expanded_url;
              }
            } else if (item.display_url.indexOf("twitpic.com") > -1) {
              mediaType = "photo";
              mediaID = item.expanded_url.substring(item.expanded_url.lastIndexOf("/") + 1, item.expanded_url.length);
              mediaUrl = "http://twitpic.com/show/thumb/" + mediaID;
            } else if (item.display_url.indexOf("twitvid") > -1 || item.display_url.indexOf("youtube.com") > -1) {
              mediaType = "video";
              mediaUrl = item.expanded_url;
              try {
                mediaID = item.expanded_url.substring(item.expanded_url.lastIndexOf("/") + 1, item.expanded_url.length);
              } catch (e) {};
            }
            txt = txt.replace("<a href=\"" + item.url + "\" data-mediatype=\"\" data-mediaurl=\"\" data-mediaid=\"\" title=\"Jump to " + item.url + "\" target=\"_blank\" class=\"bluecolor\">" + item.url + "</a>", "<a href=\"" + item.expanded_url + "\" data-mediatype=\"" + mediaType + "\" data-mediaurl=\"" + mediaUrl + "\" data-mediaid=\"" + mediaID + "\" title=\"Jump to " + item.display_url + "\" target=\"_blank\" class=\"bluecolor\">" + item.display_url + "</a>");
          }
        }
      }
      return txt;
    },
    timeSpanString: function(dateString) {
      // twitter timestamp format: Fri Apr 09 12:53:54 +0000 2010

      var second = 1000,
        minute = second * 60,
        hour = minute * 60,
        day = hour * 24,
        week = day * 7;
      var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

      var now = new Date();
      var then = new Date();
      var offset = new Date().getTimezoneOffset();

      var errored = false;

      if ($.browser.msie) {
        // then = Date.parse(dateString.replace(/( \+)/, ' UTC$1'));
        try {
          var v = dateString.split(/\s+/);
          then = new Date(Date.parse(v[1] + " " + v[2] + ", " + v[5] + " " + v[3] + " UTC"));
        } catch (e) {
          then = new Date(dateString);
        }
      } else {
        then = new Date(dateString);
      }

      var UTCnow = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
      var UTCthen = new Date(then.getUTCFullYear(), then.getUTCMonth(), then.getUTCDate(), then.getUTCHours(), then.getUTCMinutes(), then.getUTCSeconds());

      // document.write("now=" + now.toString() + "; then=" + then.toString() + "...<br />");

      var diff = UTCnow.getTime() - UTCthen.getTime();


      if (isNaN(diff) || diff < 0) {
        return ""; // return blank string if unknown
      } else if (diff < second * 2) {
        // within 2 seconds
        return "right now";
      } else if (diff < minute) {
        return Math.floor(diff / second) + " seconds ago";
      } else if (diff < minute * 2) {
        return "about 1 minute ago";
      } else if (diff < hour) {
        return Math.floor(diff / minute) + " minutes ago";
      } else if (diff < hour * 2) {
        return "about 1 hour ago";
      } else if (diff < day) {
        return Math.floor(diff / hour) + " hours ago";
      } else if (diff > day && diff < day * 2) {
        return "yesterday";
      } else if (diff < day * 10) {
        return Math.floor(diff / day) + " days ago";
      } else if (now.getFullYear() == then.getFullYear()) {
        return months[then.getMonth()] + " " + then.getDate();
      } else {
        return months[then.getMonth()] + " " + then.getDate() + " " + then.getFullYear();
      }
    },
    loadLoginCookie: function() {
      var remember = $.cookie('remember');
      if (remember == 'true') {
        var username = $.cookie('username');
        var password = $.cookie('password');
        if (username != null) $('#LoginName').val(username);
        if (password != null) $('#LoginPassword').val(password);
      }
    },
    saveLoginCookie: function(username, password, remember) {
      if (remember) {
        $.cookie('username', username, {
          expires: 30
        });
        $.cookie('password', password, {
          expires: 30
        });
        $.cookie('remember', true, {
          expires: 30
        });
      } else {
        // reset cookies
        $.cookie('username', null);
        $.cookie('password', null);
        $.cookie('remember', null);
      }
    },
    endsWith: function(inputString, target) {
      inputString = String(inputString);
      var lastIndex = inputString.lastIndexOf(target);
      return (lastIndex != -1) && (lastIndex + target.length == inputString.length);
    },
    /*  Date common functions */
    CreateDisplayDateFromJsonDate: function(jsonDate) {
      var today = new Date();
      var date2 = TM.GetDateFromJsonDate(jsonDate);
      if (TM.IsSameDay(today, date2)) {
        return TM.ShortTime(date2);
      } else {
        return TM.ShortDate(date2);
      }
    },
    ShortJsonDateTime: function(strDate) {
      var date = TM.GetDateFromJsonDate(strDate);
      return TM.ShortDate(date) + " " + TM.ShortTime(date);
    },
    ShortJsonDate: function(strDate) {
      var date = TM.GetDateFromJsonDate(strDate);
      return TM.ShortDate(date);
    },
    ShortDateTime: function(date) {
      return TM.ShortDate(date) + " " + TM.ShortTime(date);
    },
    ShortDate: function(date) {
      if (isNaN(date.getMonth())) return "";
      else return (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear();
    },
    ShortTime: function(date) {
      var h = date.getHours();
      if (isNaN(h)) return "";
      var m = date.getMinutes();
      var ampm = h < 12 ? "AM" : "PM";
      if (h == 0) h = 12;
      if (h > 12) h -= 12;
      return h + ":" + (m < 10 ? "0" : "") + m + " " + ampm;
    },
    IsSameDay: function(date1, date2) // ignores time
    {
      console.log(TM.RemoveTimeFromDate(date1), TM.RemoveTimeFromDate(date2), (TM.RemoveTimeFromDate(date1).getTime() == TM.RemoveTimeFromDate(date2).getTime()));
      return (TM.RemoveTimeFromDate(date1).getTime() == TM.RemoveTimeFromDate(date2).getTime());
    },
    RemoveTimeFromDate: function(dateToConvert) {
      var selectedMonth = dateToConvert.getMonth();
      var selectedYear = dateToConvert.getFullYear();
      var selectedDay = dateToConvert.getDate();
      return new Date(selectedYear, selectedMonth, selectedDay);
    },
    dateWithin: function(beginDate, endDate, checkDate) {
      var b, e, c;
      b = Date.parse(beginDate);
      e = Date.parse(endDate);
      c = Date.parse(checkDate);
      if ((c <= e && c >= b)) {
        return true;
      }
      return false;
    },
    GetDateFromJsonDate: function(jsonDate) {
      var date = new Date(parseInt(jsonDate.slice(6)));
      return date;
    },
    IsDateEqual: function(date1, date2) // no time compare, only day, month and year
    {
      a = new Date(date1.getYear(), date1.getMonth(), date1.getDate());
      b = new Date(date2.getYear(), date2.getMonth(), date2.getDate());
      return a.getTime() === b.getTime() // prints true
    },
    IsDateAPastDate: function(dateToCompare) {
      return (dateToCompare.getTime() < new Date().getTime());
    },
    DaysCalc: function(inputDate, DaysToAdd) {
      var TheDate = new Date(inputDate.getTime()); // must do this to clone date object, otherwise a ref is used
      TheDate = TM.addDays(TheDate, -DaysToAdd);
      return TheDate;
    },
    GetLastFridayOfWeek: function(CurrentDate) {
      var daysToAddToGetToFriday = (5 - CurrentDate.getDay());
      var lastFridayOfCurrentWeek = new Date(CurrentDate.getTime()); // must do this to clone date object, otherwise a ref is used
      lastFridayOfCurrentWeek = TM.addDays(lastFridayOfCurrentWeek, daysToAddToGetToFriday);
      return lastFridayOfCurrentWeek;
    },
    daysInMonth: function(month, year) {
      var dd = new Date(year, month, 0);
      return dd.getDate();
    },
    addDays: function(dateObj, days) {
      return dateObj.setDate(dateObj.getDate() + days);
    }
  };

  if ($("#LoginName").length > 0 && $("#LoginName").is(":visible")) {
    $("#LoginName").watermark("login");
    $("#LoginPassword").watermark("password");

    $("#loginpanel form").submit(function(e) {
      if ($("#LoginName").val() != "" && $("#Password").val() != "") {
        TM.saveLoginCookie($("#LoginName").val(), $("#LoginPassword").val(), $("#RememberMe").is(":checked"));
        return true;
      } else {
        return false;
      }
    });

    $("#signinlink").click(function() {
      $("#loginpanel form").submit();
    });

    $("#signinlink").keypress(function(event) {
      if (event.which == 13) {
        event.preventDefault();
        $("#loginpanel form").submit();
      }
    });

    TM.loadLoginCookie();
  }

  $.fn.setCursorPosition = function(pos) {
    this.each(function(index, elem) {
      if (elem.setSelectionRange) {
        elem.setSelectionRange(pos, pos);
      } else if (elem.createTextRange) {
        var range = elem.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
      }
    });
    return this;
  };

  $(document).ready(TM.init);

})();
var TM = {};

(function ()
{
    TM = {
        accountUserUsernameRegex: /^[a-zA-Z0-9_]{1,15}$/gi,
        debug: false,
        loggedIn: false,
        pageUrl: "",
        updateTimelines: true,
        setupState: "none",
        timerRateLimits: 30,
        timerTimespans: 20,
        timerUpdates: 30,
        tweetPending_Id: 1,
        tweetPendingImage: "/Content/images/pool_pending.png",
        tweetApproved_Id: 2,
        tweetApprovedImage: "/Content/images/pool_approved.png",
        tweetType: "New",
        tweetReplyId: "",
        tweetReplyFromAccount: "",
        tweetReplyFromAccountId: 0,
        tweetTokens: [],
        tweetMaxLength: 140,
        tweetCharsRemaining: 0,
        tweetDefaultAction: "TweetNow",
        tweetLinkRegex: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])/gi,
        tweetLinkReplace: "<a href=\"$1\" data-mediatype=\"\" data-mediaurl=\"\" data-mediaid=\"\" title=\"Jump to $1\" target=\"_blank\" class=\"bluecolor\">$1</a>",
        tweetUserRegex: /(@([_a-z0-9\-]+))/gi,
        tweetUserReplace: "<a href=\"http://twitter.com/$2\" title=\"Browse $2\" target=\"_blank\" class=\"bluecolor\">$1</a>",
        tweetHashtagRegex: /(#([_a-z0-9\-]+))/gi,
        tweetHashtagReplace: "<a href=\"http://search.twitter.com/search?q=%23$2\" title=\"Search $1\" target=\"_blank\" class=\"bluecolor\">$1</a>",
        urlShortenerRegex: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])\s/gi,
        urlShortenerRegexNoEndingSpace: /((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9_-]+\.[a-z0-9_\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])/gi,
        init: function ()
        {
            $.views.allowCode = true;
            $.views.registerTags({
                formatTwitterDate: function (content) { return TM.timeSpanString($.render(content, this.data)); }
            });

            var $Notification = $("#Notification");

            if ($Notification.find("span").length > 0)
                $("#Notification").css("display", "block");

            $(".hideTips").click(function ()
            {
                TM.saveSetting("#chkShowTipsInHeader", "checkbox", "ShowHeaderTips", "No");
                $Notification.fadeOut("fast", function () { $(this).empty(); });
            });
            $("#MainNav li a[href=\"" + TM.pageUrl + "\"]").addClass("pageAnchor");
            $("#AdminNav li a[href=\"" + TM.pageUrl + "\"]").addClass("pageAnchor");
            if (!TM.loggedIn)
            {
                $("#loginpanel input.returnForLogin").keyup(function (e) { if (e.keyCode == $.ui.keyCode.ENTER) { $("#signinlink").click(); } });
            }

            TM.updateSetup();

            // for Chrome, hide the yellow color for visited fields
            $('input.noautocomplete').attr('autocomplete', 'off');
        },
        updateSetup: function ()
        {
            var $accountSetupModal = $("#FirstTimePanel");
            if ($accountSetupModal.length > 0)
            {
                if (TM.setupState == "notwitteridentities" && TM.queryString("a") == "")
                {
                    $accountSetupModal.find("p.firstTimeMessage").text("Click OK to add a twitter identity to your Tweetmatic account.");
                    $accountSetupModal.find("a.btnFirstTimeCancel").unbind("click").click(TM.quitSetup);
                    $accountSetupModal.find("a.btnFirstTimeOK").unbind("click").click(function () { window.location = "/Settings?a=openaddti"; });
                    $accountSetupModal.modal();
                } else if (TM.setupState == "noauthorizedtwitteridentities" && TM.queryString("a") == "")
                {
                    $accountSetupModal.find("p.firstTimeMessage").text("Click OK to authorize your twitter identity so that Tweetmatic is allowed to post on your behalf.");
                    $accountSetupModal.find("a.btnFirstTimeCancel").unbind("click").click(TM.quitSetup);
                    $accountSetupModal.find("a.btnFirstTimeOK").unbind("click").click(function () { window.location = "/Settings?a=openoauth"; });
                    $accountSetupModal.modal();
                } 
            }
        },
        quitSetup: function ()
        {
            $.modal.close();
            TM.setupState = "complete";
            $.ajax({
                url: "/Account/QuitSetup",
                data: { },
                dataType: "json",
                type: 'POST',
                success: function (data) {  },
                complete: function () { },
                error: function (XMLHttpRequest, textStatus, errorThrown) { }
            });
        },
        queryString: function (key)
        {
            key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\?&]" + key + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(window.location.href);
            if (results == null)
                return "";
            else
                return decodeURIComponent(results[1].replace(/\+/g, " "));
        },
        showMessage: function (el, message, type)
        {
            type = type.toLowerCase();
            if (message == null || message == "") message = "&nbsp;";
            var className = (type == "error" ? "statusError" : (type == "success" ? "statusSuccess" : (type == "loading" ? "statusLoading" : (type == "info" ? "statusInfo" : ""))));
            $(el).removeClass("statusError statusLoading statusSuccess statusInfo").empty().html(message);
            if (className != "") $(el).addClass(className);
        },
        twitterOAuthPopup: function (returnUrl)
        {
            window.open("/Twitter/GetRequestToken?ReturnUrl=" + escape(returnUrl) + "","tm_oauth_popup", 
                "width=750,height=700,toolbar=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,modal=yes");
        },
        twitterOAuthPopupCallback: function ()
        {
            var url = TM.queryString("ReturnUrl");
            if (url != null && url != "")
            {
                if (url == "/Account" && !window.opener.closed)
                {
                    window.opener.reloadTwitterIdentities();
                } else
                {
                    window.opener.location.href = url;
                }
            } else
            {
                window.opener.location.reload();
            }
            window.close();
        },
        setSetting: function (formSelector, elementType, settingName, settingValue)
        {
            $(formSelector).attr("data-setting", settingValue);
            if (elementType == "checkbox")
            {
                if (settingValue.toString().toLowerCase() == "yes")
                    $(formSelector).attr("checked", "checked");
                else
                    $(formSelector).removeAttr("checked");
            } else if (elementType == "select" || elementType == "textbox" || elementType == "textarea")
                $(formSelector).val(settingValue);
            // alert("setting " + formSelector + " to " + settingValue + " (" + settingName + ")");
        },
        getSetting: function (formSelector, elementType, settingName)
        {
            $.ajax({
                url: "/Account/GetAccountUserSetting",
                data: { SettingName: settingName },
                dataType: "json",
                type: 'POST',
                success: function (data) { if (formSelector != "") TM.setSetting(formSelector, elementType, settingName, data.SettingValue); },
                complete: function () { },
                error: function (XMLHttpRequest, textStatus, errorThrown) { }
            });
        },
        saveSetting: function (formSelector, elementType, settingName, settingValue)
        {
            if (settingName == null || settingValue == null || settingName == "")
                return;
            $.ajax({
                url: "/Account/SaveAccountUserSetting",
                data: { SettingName: settingName, SettingValue: settingValue },
                dataType: "json",
                type: 'POST',
                success: function (data)
                {
                    if (formSelector != null && formSelector != "")
                    {
                        $(formSelector).attr("data-setting", settingValue);
                        if (formSelector == "#chkShowTipsInHeader" && $(formSelector).length > 0)
                            TM.setSetting(formSelector, elementType, settingName, settingValue);
                    }
                },
                complete: function () { },
                error: function (XMLHttpRequest, textStatus, errorThrown) { }
            });
        },
        updateTweetCounter: function (tweetId, counterId)
        {
            var txt = $(tweetId).val();
            TM.tweetCharsRemaining = TM.tweetMaxLength - txt.length;
            $(counterId).text(TM.tweetCharsRemaining);
        },
        ScheduledDate: function (strDate)
        {
            var date = TM.GetDateFromJsonDate(strDate);
            return TM.ShortDateTime(date);
        },
        shortenLinksHistory: [],
        resetShortenLinksHistory: function ()
        {
            TM.shortenLinksHistory = [];
        },
        shortenLinksHistoryList: function ()
        {
            var list = [];
            for (var i = 0; i <= TM.shortenLinksHistory.length - 1; i++)
            {
                list.push(TM.shortenLinksHistory[i].LongUrl + " => " + TM.shortenLinksHistory[i].ShortUrl + "\n");
            }
            return list.join(", ");
        },
        shortenLinksLocalCache: function (arr, selectorForTextArea, selectorForTweetCounter, requireEndingSpace)
        {
            var found = false;
            var txt = String($(selectorForTextArea).val());
            var oldTxt = txt;
            var i = 0;
            var initialCount = arr.length;
            var medialCount = 0;
            var finalCount = 0;
            while (i <= arr.length - 1)
            {
                if (arr[i].indexOf("bit.ly") > -1 || arr[i].length <= 20)
                {
                    arr.splice(i, 1);
                    i--;
                }
                i++;
            }
            medialCount = arr.length;
            for (var i = 0; i <= TM.shortenLinksHistory.length - 1; i++)
            {
                while (txt.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")) > -1)
                    txt = txt.replace(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : ""), TM.shortenLinksHistory[i].ShortUrl + (requireEndingSpace ? " " : ""));
                while (arr.length > 0 && arr.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")) > -1)
                    arr.splice(arr.indexOf(TM.shortenLinksHistory[i].LongUrl + (requireEndingSpace ? " " : "")), 1);
                while (txt.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")) > -1)
                    txt = txt.replace(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : ""), TM.shortenLinksHistory[i].ShortUrl + (requireEndingSpace ? " " : ""));
                while (arr.length > 0 && arr.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")) > -1)
                    arr.splice(arr.indexOf(TM.shortenLinksHistory[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : "")), 1);
            }
            finalCount = arr.length;
            if (txt != oldTxt)
            {
                $(selectorForTextArea).val(txt);
                TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
            }
            return arr;
        },
        shortenLinksDetector: function (selectorForTextArea, selectorForTweetCounter, checkForLinks, requireEndingSpace)
        {
            if (!checkForLinks)
                return;
            var txt = String($(selectorForTextArea).val());
            var m = txt.match(requireEndingSpace ? TM.urlShortenerRegex : TM.urlShortenerRegexNoEndingSpace);
            if (m != null && m.length > 0)
            {
                m = TM.shortenLinksLocalCache(m, selectorForTextArea, selectorForTweetCounter);
                if (m.length > 0)
                    TM.shortenLinks(m, selectorForTextArea, selectorForTweetCounter, requireEndingSpace);
            }
        },
        shortenLinks: function (arr, selectorForTextArea, selectorForTweetCounter, requireEndingSpace)
        {
            var urls = $.trim(arr.join(" "));
            if (urls == "") return;
            $.ajax({
                url: "/Tweet/ShortenLinksBitLy",
                data: { url: urls },
                dataType: "json",
                type: 'POST',
                success: function (data)
                {
                    if (data != null && data.length > 0)
                    {
                        var ta = $(selectorForTextArea);
                        var txt = String(ta.val());
                        for (var i = 0; i <= data.length - 1; i++)
                        {
                            if (data[i].ShortUrl.indexOf("Error: Status code") == -1)
                            {
                                txt = txt
								    .replace(data[i].LongUrl + (requireEndingSpace ? " " : ""), data[i].ShortUrl + (requireEndingSpace ? " " : ""))
								    .replace(data[i].LongUrl.replace("http://", "") + (requireEndingSpace ? " " : ""), data[i].ShortUrl + (requireEndingSpace ? " " : ""));
                                TM.shortenLinksHistory.push(data[i]);
                            }
                        }
                        $(selectorForTextArea).val(txt);
                        TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
                    }
                },
                complete: function () { },
                error: function (XMLHttpRequest, textStatus, errorThrown)
                {
                    TM.updateTweetCounter(selectorForTextArea, selectorForTweetCounter);
                }
            });
        },
        stripeTweetList: function (selector)
        {
            if ($(selector + " li:not(.norecords)").length > 0)
                $(selector + " li.norecords").hide();
            else
                $(selector + " li.norecords").show();

            $(selector + " li:visible").removeClass("odd").removeClass("even");
            $(selector + " li:visible:odd").addClass("odd");
            $(selector + " li:visible:even").addClass("even");
            $(selector + " li span.tweet_application a").attr("target", "_blank");
        },
        stripeTable: function (selector)
        {
            if ($(selector + " tbody tr:not(.norecords)").length > 0)
                $(selector + " tbody tr.norecords").hide();
            else
                $(selector + " tbody tr.norecords").show();

            $(selector + " tbody tr:visible").removeClass("odd").removeClass("even");
            $(selector + " tbody tr:visible:odd").addClass("odd");
            $(selector + " tbody tr:visible:even").addClass("even");
        },
        fixupTweetText: function (dataItem)
        {
            var txt = String(dataItem.text);
            txt = txt.replace(TM.tweetLinkRegex, TM.tweetLinkReplace);
            txt = txt.replace(TM.tweetUserRegex, TM.tweetUserReplace);
            txt = txt.replace(TM.tweetHashtagRegex, TM.tweetHashtagReplace);
            if (dataItem.entities != null && dataItem.entities.urls != null && dataItem.entities.urls.length > 0)
            {
                for (var i = 0; i <= dataItem.entities.urls.length - 1; i++)
                {
                    var item = dataItem.entities.urls[i];
                    if (item != null && item.display_url != null)
                    {
                        var mediaType = "none";
                        var mediaUrl = "none";
                        var mediaID = "";
                        var suffix = "";
                        if (item.display_url.indexOf("yfrog") > -1)
                        {
                            suffix = item.display_url.substring(item.display_url.length - 1, item.display_url.length);
                            // j; JPEG p; PNG b; BMP t; TIFF g; GIF s; SWF d; PDF f; FLV z; MP4 x; Gallery
                            if (suffix == "j" || suffix == "p" || suffix == "b" || suffix == "t" || suffix == "g")
                            {
                                mediaType = "photo";
                                mediaUrl = item.expanded_url + ":iphone";
                            } else if (suffix == "x" || suffix == "z")
                            {
                                mediaType = "video";
                                mediaUrl = item.expanded_url;
                            }
                        } else if (item.display_url.indexOf("twitpic.com") > -1)
                        {
                            mediaType = "photo";
                            mediaID = item.expanded_url.substring(item.expanded_url.lastIndexOf("/") + 1, item.expanded_url.length);
                            mediaUrl = "http://twitpic.com/show/thumb/" + mediaID;
                        } else if (item.display_url.indexOf("twitvid") > -1 || item.display_url.indexOf("youtube.com") > -1)
                        {
                            mediaType = "video";
                            mediaUrl = item.expanded_url;
                            try
                            {
                                mediaID = item.expanded_url.substring(item.expanded_url.lastIndexOf("/") + 1, item.expanded_url.length);
                            } catch (e) { };
                        }
                        txt = txt.replace(
					    "<a href=\"" + item.url + "\" data-mediatype=\"\" data-mediaurl=\"\" data-mediaid=\"\" title=\"Jump to " + item.url + "\" target=\"_blank\" class=\"bluecolor\">" + item.url + "</a>",
					    "<a href=\"" + item.expanded_url + "\" data-mediatype=\"" + mediaType + "\" data-mediaurl=\"" + mediaUrl + "\" data-mediaid=\"" + mediaID + "\" title=\"Jump to " + item.display_url + "\" target=\"_blank\" class=\"bluecolor\">" + item.display_url + "</a>");
                    }
                }
            }
            return txt;
        },
        timeSpanString: function (dateString)
        {
            // twitter timestamp format: Fri Apr 09 12:53:54 +0000 2010

            var second = 1000,
		    minute = second * 60,
		    hour = minute * 60,
		    day = hour * 24,
		    week = day * 7;
            var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

            var now = new Date();
            var then = new Date();
            var offset = new Date().getTimezoneOffset();

            var errored = false;

            if ($.browser.msie)
            {
                // then = Date.parse(dateString.replace(/( \+)/, ' UTC$1'));
                try
                {
                    var v = dateString.split(/\s+/);
                    then = new Date(Date.parse(v[1] + " " + v[2] + ", " + v[5] + " " + v[3] + " UTC"));
                } catch (e)
                {
                    then = new Date(dateString);
                }
            } else
            {
                then = new Date(dateString);
            }

            var UTCnow = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(),  now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
            var UTCthen = new Date(then.getUTCFullYear(), then.getUTCMonth(), then.getUTCDate(),  then.getUTCHours(), then.getUTCMinutes(), then.getUTCSeconds());

            // document.write("now=" + now.toString() + "; then=" + then.toString() + "...<br />");

            var diff = UTCnow.getTime() - UTCthen.getTime();


            if (isNaN(diff) || diff < 0)
            {
                return ""; // return blank string if unknown
            } else if (diff < second * 2)
            {
                // within 2 seconds
                return "right now";
            } else if (diff < minute)
            {
                return Math.floor(diff / second) + " seconds ago";
            } else if (diff < minute * 2)
            {
                return "about 1 minute ago";
            } else if (diff < hour)
            {
                return Math.floor(diff / minute) + " minutes ago";
            } else if (diff < hour * 2)
            {
                return "about 1 hour ago";
            } else if (diff < day)
            {
                return Math.floor(diff / hour) + " hours ago";
            } else if (diff > day && diff < day * 2)
            {
                return "yesterday";
            } else if (diff < day * 10)
            {
                return Math.floor(diff / day) + " days ago";
            } else if (now.getFullYear() == then.getFullYear())
            {
                return months[then.getMonth()] + " " + then.getDate();
            } else
            {
                return months[then.getMonth()] + " " + then.getDate() + " " + then.getFullYear();
            }
        },
        loadLoginCookie: function () 
        {
	        var remember = $.cookie('remember');
	        if (remember == 'true') {
		        var username = $.cookie('username');
		        var password = $.cookie('password');
		        if (username != null) $('#LoginName').val(username);
		        if (password != null) $('#LoginPassword').val(password);
	        }
        },
        saveLoginCookie: function (username, password, remember) 
        {
	        if (remember) {
		        $.cookie('username', username, { expires: 30 });
		        $.cookie('password', password, { expires: 30 });
		        $.cookie('remember', true, { expires: 30 });
	        } else {
		        // reset cookies
		        $.cookie('username', null);
		        $.cookie('password', null);
		        $.cookie('remember', null);
	        }
        },
        endsWith: function (inputString, target)
        {
            inputString = String(inputString);
	        var lastIndex = inputString.lastIndexOf(target);
	        return (lastIndex != -1) && (lastIndex + target.length == inputString.length);
        },
        /*  Date common functions */
        CreateDisplayDateFromJsonDate: function (jsonDate)
        {
	        var today = new Date();
	        var date2 = TM.GetDateFromJsonDate(jsonDate);
	        if (TM.IsSameDay(today, date2))
	        {
		        return TM.ShortTime(date2);
	        } else
	        {
		        return TM.ShortDate(date2);        
	        }
        },
        ShortJsonDateTime: function (strDate)
        {
	        var date = TM.GetDateFromJsonDate(strDate);
	        return TM.ShortDate(date) + " " + TM.ShortTime(date);
        },
        ShortJsonDate: function (strDate)
        {
	        var date = TM.GetDateFromJsonDate(strDate);
	        return TM.ShortDate(date);
        },
        ShortDateTime: function (date)
        {
	        return TM.ShortDate(date) + " " + TM.ShortTime(date);
        },
        ShortDate: function (date)
        {
	        if (isNaN(date.getMonth()))
		        return "";
	        else
		        return (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear();
        },
        ShortTime: function (date)
        {
	        var h = date.getHours();
	        if (isNaN(h)) return "";
	        var m = date.getMinutes();
	        var ampm = h < 12 ? "AM" : "PM";
	        if (h == 0) h = 12;
	        if (h > 12) h -= 12;
	        return h + ":" + (m<10?"0":"") + m + " " + ampm;
        },
        IsSameDay: function (date1, date2) // ignores time
        {
	        console.log(TM.RemoveTimeFromDate(date1), TM.RemoveTimeFromDate(date2), (TM.RemoveTimeFromDate(date1).getTime() == TM.RemoveTimeFromDate(date2).getTime()));
	        return (TM.RemoveTimeFromDate(date1).getTime() == TM.RemoveTimeFromDate(date2).getTime());
        },
        RemoveTimeFromDate: function (dateToConvert)
        {
	        var selectedMonth = dateToConvert.getMonth();
	        var selectedYear = dateToConvert.getFullYear();
	        var selectedDay = dateToConvert.getDate();
	        return new Date(selectedYear, selectedMonth, selectedDay);
        },
        dateWithin: function (beginDate,endDate,checkDate) 
        {
	        var b,e,c;
	        b = Date.parse(beginDate);
	        e = Date.parse(endDate);
	        c = Date.parse(checkDate);
	        if((c <= e && c >= b)) {
		        return true;
	        }
	        return false;
        }, 
        GetDateFromJsonDate: function (jsonDate)
        {
	        var date = new Date(parseInt(jsonDate.slice(6)));
	        return date;
        },
        IsDateEqual: function (date1, date2)  // no time compare, only day, month and year
        {
	        a = new Date(date1.getYear(),date1.getMonth(), date1.getDate());
	        b = new Date(date2.getYear(),date2.getMonth(), date2.getDate());
	        return a.getTime() === b.getTime() // prints true
        }, 
        IsDateAPastDate: function (dateToCompare)
        {
	        return (dateToCompare.getTime() < new Date().getTime());
        },
        DaysCalc: function (inputDate, DaysToAdd)
        {
	        var TheDate = new Date(inputDate.getTime());  // must do this to clone date object, otherwise a ref is used
	        TheDate = TM.addDays(TheDate, -DaysToAdd);
	        return TheDate;
        },
        GetLastFridayOfWeek: function (CurrentDate)
        {
	        var daysToAddToGetToFriday = (5 - CurrentDate.getDay());
	        var lastFridayOfCurrentWeek = new Date(CurrentDate.getTime());  // must do this to clone date object, otherwise a ref is used
	        lastFridayOfCurrentWeek = TM.addDays(lastFridayOfCurrentWeek, daysToAddToGetToFriday);
	        return lastFridayOfCurrentWeek;
        },
        daysInMonth: function (month,year) 
        {
	        var dd = new Date(year, month, 0);
	        return dd.getDate();
        },
        addDays: function (dateObj, days) 
        {
	        return dateObj.setDate(dateObj.getDate() + days);
        }
    };

    if ($("#LoginName").length > 0 && $("#LoginName").is(":visible"))
    {
	    $("#LoginName").watermark("login");
	    $("#LoginPassword").watermark("password");

	    $("#loginpanel form").submit(function (e)
	    {
		    if ($("#LoginName").val() != "" && $("#Password").val() != "")
		    {
			    TM.saveLoginCookie($("#LoginName").val(), $("#LoginPassword").val(), $("#RememberMe").is(":checked"));
			    return true;
		    } else
		    {
			    return false;
		    }
	    });

	    $("#signinlink").click(function () { $("#loginpanel form").submit(); });

	    $("#signinlink").keypress(function (event) {
		    if (event.which == 13) {
			    event.preventDefault();
			    $("#loginpanel form").submit();
		    }
	    });

	    TM.loadLoginCookie();
    }

    $.fn.setCursorPosition = function (pos)
    {
	    this.each(function (index, elem)
	    {
		    if (elem.setSelectionRange)
		    {
			    elem.setSelectionRange(pos, pos);
		    } else if (elem.createTextRange)
		    {
			    var range = elem.createTextRange();
			    range.collapse(true);
			    range.moveEnd('character', pos);
			    range.moveStart('character', pos);
			    range.select();
		    }
	    });
	    return this;
    };

    $(document).ready(TM.init);

})();