mercredi 1 juillet 2015

Single page applications and elements

Are there still any benefits of using a <form> element instead of let's say a <div> element in the context of a single page application? The purpose of the <form> element makes sense to me if the "form" submission isn't made with an ajax call (I'm talking about the more traditional way of submitting a form, with a input/button of type "submit" and the action attribute of the form element that describes the url to call), but otherwise I do not see it's utility (maybe for search engines?).

Copy multiple input fields to other matching input fields with jQuery/Javascript

I have a dummy form and the actual form in which at some point I want to copy all the input values from the dummy form across to the real form. The dummy fields will have the same names as the real form (so I can match them up).

So in dummy form:

<input name="item1" value="field1" />
<input name="item2" value="field1" />
<input name="item3" value="field1" />

and in real form:

<input name="item1" value="" />
<input name="item2" value="" />
<input name="item3" value="" />

I assume I'll need to iterate over each input in dummy form (using jQuery .each() ?) while collecting the name and value in an JS object. Then iterate over each input in the real form, matching the name as the selector and setting the value (perhaps this can be done in the one .each() function ???)

I've started with the following code which only grabs the values (and index) into an array, but because I need two values (name and value, and index is irrelevant) I assume I'll need an object not an array, but really not sure where to begin with that.

var inputValues = [];
    $("#dummyForm input").each(function() {
        inputValues.push($(this).val());
    });

Any help or advice much appreciated.

Creating closures in loops

I am learning about closures and have the basics on what they are and how they work.

I got the following code from MDN and know what the solution is since it's in the same article. I just don't get how this is possible:

<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>


function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}


function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

I know the section of code that needs change for this to work is:

document.getElementById(item.id).onfocus = function() {

      showHelp(item.help);

    }

How is it that at the end of the loop the text being pointed to is: Your age (you must be over 16) for all elements?

I can follow the code and see that the loop successfully loops through the elements correctly but I can't get my head around how is it that the last item pointed to for all elements at the end is Your age ... since it saves each one individually with the onfocus = funtion()... and what ever item.help is at the time is passed in and saved.

Any step by step explanation would greatly help in me understanding what is going on.

Can't use this to point a selected element with jQuery

Why this JS does not apply my class to the element please ?

<input type="password" name="customer-new-password" class="form-control">

<script>
if($("input[name='customer-new-password']").val()=='') {
    $(this).addClass('required');
}
else {
    $(this).removeClass('required');
}
</script>

Thanks.

Javascript conflicting with html anchor

I'm currently creating a website which has a persistent header and footer. To cut down on code duplication, I use jquery to load the header.html and footer.html when each different page is loaded.

Each html page which uses this header and footer, loads it with the code below.

<!-- Header and footer loading -->
<script> 
  $(function() {
    $("#header").load("header.html"); 
    $("#footer").load("footer.html");
  });
</script>

<div id="header">
  (header.html content rendered here)
</div>

The best way to explain this next part is by going to the site I have linked. What I would like to do is have the drop down button take a user to the specific section of the equipment page from any other page on the website. As you can currently see, this function only works if the user is already on the equipment page.

From everything I've read, cross page anchors should be setup the same way as in-page anchors. Use <a href="equipment.html#anchorname></a> and then link it to the page with <a id="anchorname></a>. However, this approach is only working when the user is on the same page as the anchor. I'm pretty sure this is due to the timing of anchor mechanism and when the jQuery code runs.

My two questions are...

  1. Could someone explain the sequence of events that are taking place which are causing my anchor not to work.
  2. What do I need to do in order to get my cross-site anchors to work properly?

Thanks and let me know if you need specific code snippets or have any questions.

Making carousel, can't scroll after click function animates (JSFiddle link updated)

Problem

I'm trying to make a carousel, so when a person clicks the back arrow the page .animate and scrolls back up to the previous chapter in the story. However, after this happens the page appear to get stuck and I can't scroll anymore. I'm wondering why this is happening?

Update #2 - JSFiddle updated: http://ift.tt/1H1tZwF

$(function(){

    /* -------------------------------------
    GLOBAL VARIABLES
    --------------------------------------*/

    var nav = 72.5;
    var splash = 750 + nav;
    var one = $(".one").offset().top - nav;
    var two = $(".two").offset().top - nav;
    var three = $(".three").offset().top - nav;
    var four = $(".four").offset().top - nav;
    var five = $(".five").offset().top - nav;

    /* -------------------------------------
    PROGRESS BAR
    --------------------------------------*/
    $(window).scroll(function(){
        var scroll = $(window).scrollTop();
        var documentHeight = $(document).height();
        var windowHeight = $(window).height();
        var scrollPercent = (scroll / (documentHeight - windowHeight)) * 100;
        var position = scrollPercent;
        $("progress").attr("value", position);

        /* -------------------------------------
        CHAPTER TEXT SWITCHING
        --------------------------------------*/
        if (scroll >= one && scroll <= two) {
            $(".title").html("Chapter 1");
        } else if (scroll >= two && scroll <= three) {
            $(".title").html("Chapter 2");
        } else if (scroll >= three && scroll <= four) {
            $(".title").html("Chapter 3");
        } else if (scroll >= four && scroll <= five) {
            $(".title").html("Chapter 4");
        } else if (scroll >= five) {
            $(".title").html("Chapter 5");
        } else {
            $(".title").html('It could have been me');
        };

        /* -------------------------------------
        ARROW CAROUSEL
        --------------------------------------*/

        $(".backward").click(function(){
            if (scroll >= two && scroll <= three) {
                $("body").animate({
                    scrollTop: $(".one").offset().top - splash
                }, 1000);
            } else {
                console.log("Backward");
                // $("html, body").animate({
                //  scrollTop: $(".two").offset().top
                // }, 1000);
            }

        });

        $(".forward").click(function(){
            console.log("Forward");
        });
    })
});

index.html

<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
    <meta charset="UTF-8">
    <title>Name of Website</title>
    <meta name="description" content="">
    <meta name="author" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="assets/css/style.css">
    <link rel="stylesheet" href="http://ift.tt/18QXBAt">
    <link href='http://ift.tt/YW5hLg' rel='stylesheet' type='text/css'>
    <!-- <link rel="icon" type="image/png" href="assets/img/favicon.ico"> -->
</head>
<body>

    <nav>
        <progress value="0" max="100"></progress><!-- /.progress -->
        <div class="logo">
            <img src="assets/img/logo.png" alt="" class="bdnsun">
        </div><!-- .logo -->

        <div class="details">
            <p class="title">'It could have been me'</p>
            <span class="dot first">&#9679;</span>
            <span class="by">By</span>
            <span class="byline">Nancy MacDonald</span>
            <span class="dot second">&#9679;</span>
            <span class="time">Time to Read:</span>
            <span class="full">19 min</span>
        </div><!-- .details -->

        <div class="social">
            <a href=""></a>
            <a href=""></a>
            <a href=""></a>
        </div><!-- .social -->

        <div class="chapters">
            <div class="backward" id="target" title="Previous chapter"><i class="fa fa-angle-left fa-4x"></i></div><!-- /.backward -->
            <div class="forward" title="Next chapter"><i class="fa fa-angle-right fa-4x"></i></div><!-- /.forward -->
        </div><!-- .chapters -->
    </nav>

    <main>
        <div class="splash" id="top">
            <div class="teaser">
                <h1>'It could have been me'</h1>
                <p class="subhead">Thirteen women share their remarkable stories</p>
                <p class="byline-alt">Nancy MacDonald</p>
            </div><!-- .splash -->
        </div>

        <div class="wrapper">
            <div class="chapter one">
                <p>Wolf kale chips stumptown fanny pack, vegan kogi asymmetrical. Locavore polaroid sustainable Blue Bottle, farm-to-table kogi plaid keytar Tumblr occupy gluten-free. Pitchfork shabby chic lo-fi flannel, bitters hella readymade. Ethical meggings master cleanse Schlitz mustache Blue Bottle, <span class="highlight">American Apparel</span> dreamcatcher vinyl Tumblr. Scenester try-hard Portland master cleanse. Skateboard tofu mumblecore, swag retro aesthetic kale chips American Apparel lo-fi normcore bespoke Helvetica synth. Tousled Brooklyn DIY, quinoa Etsy chambray umami.</p>

                <p>Meh literally freegan, church-key Tumblr sustainable mlkshk sriracha Pitchfork. Migas stumptown deep v lumbersexual. Cray roof party skateboard scenester hashtag, plaid distillery wayfarers banjo ethical artisan. Skateboard irony Portland deep v, cliche DIY Pinterest brunch Echo Park tilde Helvetica. Etsy stumptown chambray craft beer four loko brunch, twee mustache. Crucifix yr synth, irony mlkshk polaroid master cleanse iPhone mixtape twee direct trade keytar. Brooklyn Pinterest migas Portland gluten-free.</p>

                <blockquote>
                    <span class="quote">“</span>
                    Meh literally freegan, church-key Tumblr sustainable mlkshk sriracha Pitchfork. Migas stumptown deep v lumbersexual.
                </blockquote>

                <p>Blog cold-pressed vinyl Shoreditch organic put a bird on it. Salvia put a bird on it swag chillwave Bushwick, fanny pack stumptown art party selvage narwhal. Readymade distillery asymmetrical bespoke. Blue Bottle bitters tofu, Austin retro meh gentrify tattooed American Apparel Banksy. Try-hard whatever pug tousled DIY lomo. Marfa pop-up shabby chic messenger bag Intelligentsia. Kale chips gastropub viral, Helvetica forage disrupt mumblecore mlkshk Brooklyn vegan.</p>
            </div><!-- .chapter -->

            <div class="chapter two">
                <p>Chapter 2</p>
            </div><!-- .chapter -->

            <div class="chapter three">
                <p>Chapter 3</p>
            </div><!-- .chapter -->

            <div class="chapter four">
                <p>Chapter 4</p>
            </div><!-- .chapter -->

            <div class="chapter five">
                <p>Chapter 5</p>
            </div><!-- .chapter -->
        </div><!-- /.wrapper -->
    </main>

    <p class="more">Read More</p>

    <footer>
    </footer>

    <script src="http://ift.tt/1JsU1tb"></script>
    <script src="http://ift.tt/1CWMYDx"></script>
    <script src="assets/js/scripts.js"></script>

</body>
</html>

WebRTC renegotiate the Peer Connection to switch streams

I have this script where. two users can chat using webrtc. when two users enter to the chat room . the text chat is started automatically. I want to add a botton to allow video chat. for example there is two users. user_1 and user_2 when they enter to the chat room, the text chat is initiated, they can send text messages to each others, and when user_1 click on the video icon the user_2 can see user_1. and the same thing with the user_2 when he click on video icon. This is the code i'm using now. but this code doesn't work properly, when i stat chatting with someone and i click on video icon i can see my self but the other user can't see me.I didn't post all the code because it's more than 300 lines, but i think you cant help me to modify just this to make it work, and thanks in advance everyone.

var pc_config = webrtcDetectedBrowser === 'firefox' ?
{'iceServers':[{'url':'stun:23.21.150.121'}]} : // IP address
{'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};
var pc_constraints = {
  'optional': [
    {'DtlsSrtpKeyAgreement': true},
    {'RtpDataChannels': true}
  ]};
var sdpConstraints = {'mandatory': {
  'OfferToReceiveAudio':true,
  'OfferToReceiveVideo':true }};
var constraints = {video: true, audio: true};
var v_on_off = false;
v_call.on('click', function(){
  if (!v_on_off) {
        navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
        if (isInitiator) {
            maybeStart();
        };
      v_on_off = true;
  } else {
      // stop stream
  }
});
function handleUserMedia(stream) {
        localStream = stream;
        attachMediaStream(localVideo, stream);
        sendMessage('got user media');
}
var socket = io.connect();
if (room !== '') {
  socket.emit('create or join', room);
}
socket.on('created', function (room){
  isInitiator = true;
});
socket.on('join', function (room){
  isChannelReady = true;
});
socket.on('joined', function (room){
  isChannelReady = true;
});
function sendMessage(message){
  socket.emit('message', message);
}
// this will start a text chat between too peers
sendMessage('got user media');
if (isInitiator) {
    maybeStart();
  }
socket.on('message', function (message){
  console.log('Received message:', message);
  if (message === 'got user media') {
    maybeStart();
  } else if (message.type === 'offer') {
    if (!isInitiator && !isStarted) {
      maybeStart();
    }
    pc.setRemoteDescription(new RTCSessionDescription(message));
    doAnswer();
  } else if (message.type === 'answer' && isStarted) {
    pc.setRemoteDescription(new RTCSessionDescription(message));
  } else if (message.type === 'candidate' && isStarted) {
    var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
      candidate:message.candidate});
    pc.addIceCandidate(candidate);
  } else if (message === 'bye' && isStarted) {
    handleRemoteHangup();
  }
});
function maybeStart() {
  if (!isStarted && isChannelReady) {
    createPeerConnection();
    isStarted = true;
    if (isInitiator) {
      doCall();
    }
  }
}
function createPeerConnection() {
  try {
    pc = new RTCPeerConnection(pc_config, pc_constraints);
    if (typeof localStream != 'undefined') {
        pc.addStream(localStream);
    }
    pc.onicecandidate = handleIceCandidate;
  } catch (e) {
    alert('Cannot create RTCPeerConnection object.');
      return;
  }
  pc.onaddstream = handleRemoteStreamAdded;
  pc.onremovestream = handleRemoteStreamRemoved;
  if (isInitiator) {
    try {
      // Reliable Data Channels not yet supported in Chrome
      sendChannel = pc.createDataChannel("sendDataChannel",
        {reliable: false});
      sendChannel.onmessage = handleMessage;
      trace('Created send data channel');
    } catch (e) {
      alert('Failed to create data channel. ' +
            'You need Chrome M25 or later with RtpDataChannel enabled');
      trace('createDataChannel() failed with exception: ' + e.message);
    }
    sendChannel.onopen = handleSendChannelStateChange;
    sendChannel.onclose = handleSendChannelStateChange;
  } else {
    pc.ondatachannel = gotReceiveChannel;
  }
}
function gotReceiveChannel(event) {
  trace('Receive Channel Callback');
  sendChannel = event.channel;
  sendChannel.onmessage = handleMessage;
  sendChannel.onopen = handleReceiveChannelStateChange;
  sendChannel.onclose = handleReceiveChannelStateChange;
}
function handleSendChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Send channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}
function handleReceiveChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Receive channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}
function handleIceCandidate(event) {
  console.log('handleIceCandidate event: ', event);
  if (event.candidate) {
    sendMessage({
      type: 'candidate',
      label: event.candidate.sdpMLineIndex,
      id: event.candidate.sdpMid,
      candidate: event.candidate.candidate});
  } else {
    console.log('End of candidates.');
  }
}
function doCall() {
  var constraints = {'optional': [], 'mandatory': {'MozDontOfferDataChannel': true}};
  // temporary measure to remove Moz* constraints in Chrome
  if (webrtcDetectedBrowser === 'chrome') {
    for (var prop in constraints.mandatory) {
      if (prop.indexOf('Moz') !== -1) {
        delete constraints.mandatory[prop];
      }
     }
   }
  constraints = mergeConstraints(constraints, sdpConstraints);
  console.log('Sending offer to peer, with constraints: \n' +
    '  \'' + JSON.stringify(constraints) + '\'.');
  pc.createOffer(setLocalAndSendMessage, null, constraints);
}
function doAnswer() {
  console.log('Sending answer to peer.');
  pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints);
}
function handleRemoteStreamAdded(event) {
  console.log('Remote stream added.');
  attachMediaStream(remoteVideo, event.stream);
  remoteStream = event.stream;
}  

and this is a server side code :

socket.on('message', function (message) {
    // channel-only broadcast...
    socket.broadcast.to(message.channel).emit('message', message);
});
// Handle 'create or join' messages
socket.on('create or join', function (room) {
    var numClients = io.sockets.clients(room).length;
    // First client joining...
    if (numClients == 0){
        socket.join(room);
        socket.emit('created', room);
    } else if (numClients == 1) {
        io.sockets.in(room).emit('join', room);
        socket.join(room);
        socket.emit('joined', room);
    } else { 
    socket.emit('full', room);
    }
});