4
\$\begingroup\$

I was doing writing some various things in JavaScript and ending up writing 2 scripts that proved useful in quite a lot of my other programs and I was wondering if there was anything that I could do better because I'm fairly new to JavaScript and jQuery after a fairly long history of Java/C++.

Both programs have __ passed to them as I have used this as my global variable to prevent cluttering of the actual global namespace (if that is what you call it) and from what I can tell objects that get passed get passed as pointers but values do not, which I still find hard to fully understand in a weakly typed language like JS. The reason they are actually in the functions in the first place is to prevent it from cluttering the global namespace if one of you wants to use it and has underscore.js or simply use __ somewhere else.

The first one basically manages inline consoles that look better in my pages while debugging and creates an assert function. log assigns classes based on the second parameter, and these classes are listed in every style sheet I make which is fairly annoying, but I have yet to find a better way to do this. I could maybe assign them CSS styles directly, but that would assign it to every object separately and waste memory.

console.js

var log,assert;
!function(__){
__.hasConsole = true;
const ilconsole = $("#console-log");
log = function(text,level){
    if (!ilconsole[0]) return false;
    level = "log-" + (level || "log"); //log-log for best log 2012
    ilconsole.append('<span class = "'+level+'">'+text+'</span></br>');
    return true;
};
assert = function(a){
    if(!a){
        var n = new Error("Assertion failed");
        log(n.stack,"fatal"); //I love stacks, but I hate the way this looks ;c
        throw (n);
        //mabye could replace all this with 'throw new Error("Assertion failed");' or even 'throw "assertion failed";'
    }
};
$(document).ready(function(){
    if (!log("Inline console found","important")){
        log = function(f){console.log(f);}; //Prevents the second paramater interfering with default consoles that take a second paramater
        log("No inline console found, defaulting to browser console. Add an object with id 'console-log' into the document to enable inline console.");
        __.hasConsole = false;
    }
});
}(__ || !function(){throw new Error("Global namespace (__) must be set to an object!");}()); //I don't know if this is bad practice but it stops it from running

The second one is a way to add inputs that have the text disappear when you focus them and have a button linked if you press enter while focused. The difference between this and $(this) are obvious in the object properties but I don't know how to speeds compare, so I went with the basic JavaScript for what I could as I assumed it was faster. This may cause cache-misses but I don't think those are important in JavaScript in general because this isn't being called 120 times a second like things in C++.

jbase.js

!function(__){$(document).ready(function(){
__.hasjbase = true;
$(".jtext")
    .text(function(){this.value = $(this).attr("jvalue");})
    .focus(function(){
            const $this = $(this);
            if(this.value == $this.attr("jvalue"))
                $this.val("");
        })
    .blur(function(){
            const $this = $(this);
            if(this.value === "") // I dont know if this is right (what if they type 'false' or '0' or 'undefined')
                $this.val($this.attr("jvalue"));
        });
$(".jlink")
    .keyup(function(e){
            if (e.which != 13) return;//return key
            const $this = $(this);
            const $that = $("#" + $this.attr("jlink"));
            assert($that[0]);
            $this.blur(); //unneeded?
            $that.focus();
            $that.click();
        });
});}(__ || /*!function(){throw new Error("Global namespace (__) must be set to an object!");}()*/ {});//throw is commented because the __ isnt used importantly this script
//Example usage
/*
Input that changes to blank when focused, and activates foo when enter is hit
<input type = "text" class = "wow so fresh jtext jlink" jvalue = "cool input!" jlink = "foo"></input>
<input type = "button" id = "foo"></input>

Input that changes to blank when focused
<input type = "text" class = "wow so fresh jtext" jvalue = "cool input!"></input>

*/
\$\endgroup\$
  • 2
    \$\begingroup\$ x === "" will not false-positively on 0, null, false, undefined, whitespace, etc it will work as you want, edit: unless you want to be false when they type 0, etc \$\endgroup\$ – ajax333221 May 3 '14 at 3:26
3
\$\begingroup\$

console.js

;(function (__) {

  // As far as I know, there are no "const" in JS.
  var ilconsole = $("#console-log");

  // Like C, 0 is false, non-0 is true. jQuery objects have length, a count of the elements in the set
  __.hasConsole = ilconsole.length;


  function log(text, level) {
    if (__.hasConsole) {
      level = "log-" + (level || "log");

      // Using div for a natural "new-line", no <br>
      // Also using a chained approach, more readable
      $('<div>', {
        class: level
      }).text(text).appendTo(ilconsole);
    } else {

      // default to console.log()
      console.log(text);
    }
  };

  function assert(a) {
    // early return pattern avoids further indentation
    if (a) return;
    // The only standard properties of Error is name and message.
    // You could subclass Error to create custom errors
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
    throw (new Error("Assertion failed"));
  };

  $(function () {
    if (__.hasConsole) log("Inline console found", "important");
    else log("No inline console found, defaulting to browser console. Add an object with id 'console-log' into the document to enable inline console.");
  });

  // If they needed to be global, expose them as global
  window.log = log;
  window.assert = assert;

// Use the existing __ or create one on the fly. No need for declaring __ beforehand
}(this.__ = this.__ || {}));

jbase.js

;(function (__) {
  $(function () {

    __.hasjbase = true;

    // What I think you need here is the placeholder attribute
    // <input type="text" placeholder="some value" />


    // If you go for the JS route, then there's no issue with using native
    // but I highly suggest using data-* attributes so that the HTML will be valid
    $(".jtext")
      .val(function () {
        return this.jvalue;
      })
      .focus(function () {
        if (this.value == this.jvalue) this.value = '';
      })
      .blur(function () {
        if (this.value === "") this.value = this.jvalue;
      });

    $(".jlink").keyup(function (e) {
      if (e.which !== 13) return; //return key
      var $this = $(this);
      var $that = $("#" + this.jlink);
      assert($that[0]);
      // Gain focus on one element will lose focus on the other.
      $that.focus();
      $that.click();
    });
  });
}(this.__ = this.__ || {}));
\$\endgroup\$
  • \$\begingroup\$ in jbase, I didnt realize what I did with the .val under $(".jtext"), (probably some result of me copypasting .focus and .blur), but you kept it as a function that returns the value this.jvalue. Couldnt you just make it into .val(this.jvalue)? \$\endgroup\$ – John2143658709 May 4 '14 at 21:49
  • \$\begingroup\$ @user1114214 The this when doing .val(this.jvalue) is not .jtext. The reason I placed it in a function is because inside that function, the this is .jtext. \$\endgroup\$ – Joseph May 4 '14 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.