Mississippi holds a Presidential preference primary on Tuesday, March 11. Primary elections will also be held for federal offices and for Commissioners of the Yazoo-Mississippi Delta Levee District.
Mississippi has just under 1.8 million registered voters. Mississippi voters do not register by political party, and voters may choose a Republican Party ballot or a Democratic Party ballot at the polls. Absentee voters must have an excuse for being unable to come to the polls. Most votes in the primary will be cast on DREs with a voter-verifiable paper trail printer. The state does not require post-election hand audits of the electronic vote tallies, so there will be no manual verification of software-tabulated election results.
The Election Assistance Commission is considering a Policy Clarification issued last month by Commission Chair Rosemary Rodriguez (pictured at right) that would reverse an earlier staff recommendation regarding the use of remaining Help America Vote Act (HAVA) funds by states to replace voting systems purchased with previous HAVA funds. Verified Voting and VoteTrustUSA strongly supports this Policy Clarification: such expenditures are a reasonable use of HAVA funds to improve the administration of Federal elections.
The Help America Vote Act of 2002 (HAVA) required States to employ voting systems that would meet new requirements. The new requirements were specified in Title III of the bill, which required, among other provisions, that each and every polling place used in federal elections provide at least one voting system allowing voters with disabilities to vote privately and independently.
HAVA established the Election Assistance Commission (EAC) and directed the Commission to disburse appropriated funds in the form of payments to States to assist them in meeting the requirements of Title III. HAVA granted broad discretion to the States regarding the use of such that remained after the State had met the requirements of Title III. Such funds were to be used by States as they found necessary to "improve the administration of Federal elections".
Ohio, Rhode Island, Texas, and Vermont hold Presidential primaries on March 4. Ohio and Texas will also hold state primaries. In all four states, turnout is expected to increase substantially from 2004. The March 4 states use a mix of voting system types. Ohio has a mix of counties useing direct-recording electronic (DRE) machines with a voter-verifiable paper audit trail, and counties using only optically scanned paper ballots. Texas has a very wide diversity of voting systems, including many paperless DREs. Rhode Island and Vermont use paper ballots exclusively. None of these states require manual post election audits of their inital, software-generated, results. In all four states, the primaries are under the jurisdiction of the state election officials, rather than of the political parties.
The Texas primary on March 4 could be the closest and the most consequential election so far this year in which ballots cast on paperless electronic voting machines are a large portion of the overall vote. The Texas primary may determine the Democratic Party's nominee for President (the Republican nomination campaign is considered essentially over) , but its outcome will not be verifiable due to the extensive use of insecure and unrecountable voting systems. As noted in Verified Voting's snapshot of voting sytems in the four March 4 states, Texas's 254 counties use a large diversity of systems. Around 100 counties use only paper ballots, with most paper ballots being optically scanned and a small number hand-counted. Random manual audits are not done in Texas. Most of the state's larger counties make some use of touch screen direct-recording electronic voting machines, or DREs, and in these counties, touch screen DREs have often been the system used for early voting.
Early voting turnout in Texas has been very high, as the campaign press has reported. In the 15 most populous counties in Texas, as many as 20% of registered voters in both parties combined had already cast their votes by February 29. The early voting turnout in the 15 most largest counties is available at the Secretary of State's website. Of these counties, at least 8 are using only paperless machines for early voting: Dallas, Bexar, Hidalgo, El Paso, Tarrant, Nueces, Galveston, and Montgomery. By the end of early voting, 10.76% of the registered voters in Dallas County, and 17.85% of the voters in Hidalgo County, voted on the paperless ES&S iVotronic in the Democratic primary alone. 11.65% of the voters in Nueces County, and almost 10.4% in Galveston County voted on paperless Hart eSlate machines in the Democratic primary.
This article was posted at Ed Felten's Blog and is reposted here with permission of the author.
In Texas, you are not required to register with a party in order to vote in their primary. Instead, you just show up and ask for their primary ballot. In the big city of Houston, any registered voter can go to any of 35 early voting locations over the two weeks of early voting. Alternately, they may vote in their home, local precinct (there are almost a thousand of these) on the day of the election. There have been stories of long lines over the past two weeks. My wife wanted to vote, but procrastinating, we went on the final night to a gigantic supermarket near campus. Arriving at 5:50pm or so, she didn�t reach the head of the queue until 8pm. Meanwhile, I took care of our daughter and tried to figure out the causes of the queue.
Case study examines five states' efforts to limit paperless voting.
A new report by electionline.org details how five states that implemented electronic voting have chosen or are considering statewide paper-based optical scan systems.
"Back to Paper" explores the process by which California, Colorado, Florida, New Mexico and Ohio -- having adopted electronic voting systems -- subsequently decided to de-certify, re-examine or re-think their use.
Although it focuses on five states, the report describes a growing trend. Six years and millions of dollars into a major overhaul of the U.S. election system, a number of states are contemplating returning to paper-based voting systems after failed or troubled experiments with newer voting technology. Even as bills in Congress have stalled, nearly half of all states have adopted requirements for voter-verified paper with electronic voting and/or the use of paper-based voting systems, including optical-scan machines.
In the five states that are the subject of the electionline.org case study, problems at the polls, pressure from voter integrity groups and rising concern among lawmakers prompted leaders to scrap -- or in one case, strongly consider scrapping -- recent purchases of direct-recording electronic systems in favor of paper-based optical scanners.
Everyone�s a critic, and in political argument, this is reason for celebration. It is better still if the criticism is reasoned, exhibiting a coherent point of view and not simply a reflex action. Two prominent historians have criticism to offer of the Presidential nominating process, and this, the criticism, comes through, with no trace of the coherent point of view. Sean Wilentz and Julian E. Zelizer, "A Rotten Way to Pick a President," Washington Post (Feb. 17, 2008) at B3. Granted that no system is perfect�granted, too, that this system in place will have weaknesses that alternatives could correct. Sean Wilentz and Julian Zelizer steer an erratic course through their diagnosis of the problem, with no prospect of arriving at convincing answers.
They are referring here in part to caucuses. Now caucuses did not as a group come under fire until people began turning out at them and casting votes with a significant effect on the nominating process. Only the Iowa Caucuses have been consistently rapped over the years with any meaningful objection, but this was less as a caucus (the virtues of which were highly touted for years, as a vindication of retail politics) and more because its first-in-the-nation place on the calendar was believed to give it undue influence.
U.S. Senator Dianne Feinstein (D-Calif.), Chairman of the Senate Rules and Administration Committee, and Senator Arlen Specter (R-Pa.) today introduced legislation to regulate robocalls.
The measure introduced by Feinstein and Specter would not ban robocalls, but instead places sensible restrictions on how and when the calls can be made � including limiting the hours within which calls can be made, limiting the number of calls that can be made to each household, and requiring callers to identify themselves at the beginning of the call.
�During this primary season, we have heard stories about people being called over and over again, at all hours of the day and night. I believe we need sensible guidelines in place,� Chairman Feinstein said. �Something must be done about the worst of these calls.
Maryland, Virginia, and the District of Columbia hold Presidential primaries on February 12. A majority of the votes cast on "Chesapeake Tuesday" will be cast on paperless electronic voting systems which are vulnerable to error and tampering, and which do not not allow meaningful audits or recounts.
Commendably, Maryland and Virginia are taking steps to adopt verifiable voting systems in future elections.
238 Democratic delegates and 119 Republican delegates are at stake.
Maryland has 3,134,077 million registered voters, and 1618 election-day polling places. All of Maryland's election-day polling places will use only paperless touch screen voting machines. Maryland plans to abandon its paperless voting system and convert to a system of optically scanned paper ballots by 2010.
Virginia has 4,585,828 million registered voters, and over 2,300 election-day polling places. Almost 80% of the state's polling places will use paperless electronic voting systems. Virginia is also taking steps toward reform. In 2007, the Virginia legislature banned the future purchase of direct-recording electronic voting systems.
The District of Columbia has 377, 007 registered voters, and 142 election-day polling places. Each polling place will offer voters either a paper ballot option, or a paperless touch screen option. Verified Voting strongly encourages D.C. voters to vote on a paper ballot.
To make Chesapeake Tuesday's among the nation's last unverifiable elections, Verified Voting urges you to support HR 5036, the Emergency Assistance for Secure Elections Act. HR 5036 will provide badly needing funding to Maryland, Virginia and all states that wish to adopt paper ballot voting systems by November 2008. Click here to read Verified Voting's statement of support, and click here to send Congress a message to pass HR 5036.


text:
Charity partner for north's air ambulance service confirmed
The Air Ambulance NI charity has been confirmed as the partner for the north's first air ambulance service. Picture from Facebook
John Monaghan
Dr John Hinds, who died last year, had been a major supporter of efforts to get an air ambulance service for the north. Picture by Stephen Davison/Pacemaker
THE charity partner for the north's first air ambulance service has been confirmed.
As had been widely expected, Air Ambulance NI has been announced as the partner for the first ever HEMS operation.
Health Minister Michelle O'Neill said that the exact terms of the partnership will be finalised in a memorandum of understanding to be signed between the Ambulance Service and Air Ambulance NI in coming weeks.
She said: "The charity will work in partnership with the Ambulance Service to provide the aviation side of the service and fund the non-medical costs of HEMS.
"The medical staff and equipment will be provided and funded by Health and Social Care services."
"Ultimately there will be a doctor and paramedic on board the aircraft to administer emergency medical services, in line with the outcome of our recent consultation," added Ms O'Neill.
The minister said she had not yet decided on the time frame and operating model for the new service.
She said: "The staffing model requires careful planning and for this reason I have listened to representatives from the clinical community, and will be advised by my Chief Medical Officer on the most clinically appropriate means for delivering this.
"I will therefore make a further decision about the initial operating model, and timeframe for implementing it, in the weeks ahead."
Funding to establish an air ambulance service for the north was secured following the death of Dr John Hinds, a major campaigner on the issue, and the plans were confirmed by former health minister Simon Hamilton earlier this year.
In his budget in March, former Chancellor George Osborne announced that £4.5 million, arising from banking fines, would be used to help establish the service - which is expected to cost millions in annual running costs - and later said that the Air Ambulance NI charity would be the "ultimate recipient of the funding".
Earlier this year there was criticism from a former colleague of Dr Hinds after the charity fundraised and reportedly operated flights at the North West 200 despite confirmation about the charity partner not having been made.
The charity said at the time: "We are very pleased that the NW 200 organisers appointed AANI as their nominated charity for the next three years. As part of this arrangement we provided a helicopter and crew to the NW 200 Medical Team for the duration of the event."
23 August, 2016 13:00 Healthcare news

redpajama_set_name: RedPajamaCommonCrawl


text:
/**
 * Sponsored by: Senter for IKT i utdanningen
 * Code: paalj
 *
 * @file
 * Drag and drop with lines quiz question type implemented using the Raphaël
 * javascript library (http://raphaeljs.com/)
 *
 */

/**
 * Implementation of the connection between a hotspot and the label
 */
Raphael.fn.connection = function (obj1, obj2, line, bg) {
    if (obj1.line && obj1.from && obj1.to && obj1.bg) {
        line = obj1;
        obj1 = line.from;
        obj2 = line.to;
    }

    var bb1 = obj1.getBBox(),
        bb2 = obj2.getBBox(),
        p = [{x: bb1.x + bb1.width / 2, y: bb1.y - 1},
        {x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1},
        {x: bb1.x - 1, y: bb1.y + bb1.height / 2},
        {x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2},
        {x: bb2.x + bb2.width / 2, y: bb2.y - 1},
        {x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1},
        {x: bb2.x - 1, y: bb2.y + bb2.height / 2},
        {x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2}],
        d = {}, dis = [];
    for (var i = 0; i < 4; i++) {
        for (var j = 4; j < 8; j++) {
            var dx = Math.abs(p[i].x - p[j].x),
                dy = Math.abs(p[i].y - p[j].y);
            if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x
 p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) {
                dis.push(dx + dy);
                d[dis[dis.length - 1]] = [i, j];
            }
        }
    }
    if (dis.length == 0) {
        var res = [0, 4];
    } else {
        res = d[Math.min.apply(Math, dis)];
    }
    var x1 = p[res[0]].x,
        y1 = p[res[0]].y,
        x4 = p[res[1]].x,
        y4 = p[res[1]].y;
    dx = Math.max(Math.abs(x1 - x4) / 2, 10);
    dy = Math.max(Math.abs(y1 - y4) / 2, 10);
    var x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
        y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
        x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
        y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3);
    var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");
    if (line && line.line) {
        line.bg && line.bg.attr({path: path});
        line.line.attr({path: path});
    } else {
        var color = typeof line == "string" ? line : "#000";
        return {
            bg: bg && bg.split && this.path(path).attr({stroke: bg.split("|")[0], fill: "none", "stroke-width": bg.split("|")[1] || 3})/*.toBack()*/,
            line: this.path(path).attr({stroke: color, fill: "none", "stroke-width":3}),
            from: obj1,
            to: obj2
        };
    }
};

(function ($) {
var QuizUtil = {
    // The minimum width of the label
    LABEL_MIN_WIDTH: 40,

    CANVAS_PADDING: 10,

    // The glow implementation should be moved into a class,
    // but will do for now
    current_glow: null,

    current_editor: null,

    drag_mode: false,

    imageChanged: false,

    defined: function (a) {
      return (typeof a !== 'undefined');
    },

    bboxUnion: function(bbox1, bbox2) {
      bbox1.x = bbox1.x < bbox2.x ? bbox1.x : bbox2.x;
      bbox1.y = bbox1.y < bbox2.y ? bbox1.y : bbox2.y;
      bbox1.x2 = bbox1.x2 > bbox2.x2 ? bbox1.x2 : bbox2.x2;
      bbox1.y2 = bbox1.y2 > bbox2.y2 ? bbox1.y2 : bbox2.y2;

      return bbox1;
    }
};
/**
 * A list of quiz ddlines elements.
 *
 * Responsible for:
 * - Holding the elements in-memory
 * - Creating/Parsing the jsondata
 * - Making the form input field being in-sync
 */
var QuizElementList = {
  elements: [],
  engine: null,
  add: function(element) {
    this.elements.push(element);
    this.updateForm();
  },
  remove: function(element) {
    // Remove from list:
    for(var i=0; i<this.elements.length; i++) {
      if(element == this.elements[i]) {
        this.elements.splice(i,1);
      }
    }
    // Update form cache:
    this.updateForm();
  },
  clear: function() {
    this.elements = [];

    // Update form cache:
    this.updateForm();
  },
  updateForm: function() {
    if(this.engine.isEditMode()) {
      // Set the value of the hidden form field (ddlines_elements)
      $('input[name=ddlines_elements]').val(this.toJson());
    }
  },
  load: function(engine, display_answers, id) {

    QuizElementList.engine = engine;

    var obj=null;
    if(engine.isResultMode()) {
      obj = display_answers ? engine.conf["answers-"+id] : engine.conf["correct-"+id];
    }
    else {
      json = $('input[name=ddlines_elements]').val();

      if(!json || json.length == 0) {
        return;
      }

      obj = $.parseJSON(json);
    }

    // Set canvas size:
    engine.resizePaper(obj.canvas.width, obj.canvas.height);

    // Set image position:
    if(!QuizUtil.imageChanged) {
      engine.image.setBounds(obj.image.left, obj.image.top, obj.image.width, obj.image.height);
    }

    // Add elements:
    if(QuizUtil.defined(obj.elements)) {
      for (var i = 0; i < obj.elements.length; i++) {
        this.add(QuizElement.fromJson(obj.elements[i], engine));
      }
    }

    // Update connecting lines between each pair if hotspot
    // and label:
    engine.redrawConnections();
  },
  toJson: function() {
    // Get image location:
    var elements='';
    var json = '{' + this.engine.image.toJson() + ',' + this.engine.toJson();
    for (var i = 0; i < this.elements.length; i++) {
      elements += this.elements[i].toJson() + (i<this.elements.length-1 ? ',' : '');
    }

    if(this.elements.length>0) {
      json += ',"elements":['+elements+']';
    }

    return json+'}';
  },
  size: function() {
    return this.elements.length;
  },
  updateHotspotRadius: function(radius) {
    radius = parseInt(radius);

    this.engine.conf.hotspot.radius = radius;

    // Update radius for all elements:
    for(var i=0; i<this.elements.length; i++) {
      this.elements[i].uiHotspot.updateHotspotRadius(radius);
      this.elements[i].redrawConnection();
    }
  },
  adjustCanvasSize: function() {

    var moveLeft = moveUp = 0;
    var bbox = this.engine.image.getBBox();
    var maxElementWidth = 0;

    /* Auto adjust canvas size */
    for (var i = 0; i < this.elements.length; i++) {
      bbox2 = this.elements[i].getBBox();
      maxElementWidth = maxElementWidth < bbox2.width ? bbox2.width : maxElementWidth;

      bbox = QuizUtil.bboxUnion(bbox, bbox2);
    }

    var horizontalPadding = this.engine.executionModeLines() ? QuizUtil.CANVAS_PADDING : maxElementWidth * 0.6;
    horizontalPadding = horizontalPadding > QuizUtil.CANVAS_PADDING ? horizontalPadding : QuizUtil.CANVAS_PADDING;

    moveLeft = -bbox.x + horizontalPadding;
    moveUp = -bbox.y + QuizUtil.CANVAS_PADDING;

    /* Update all elements */
    for (var i = 0; i < this.elements.length; i++) {
      this.elements[i].move(moveLeft, moveUp);
    }

    // Update image:
    this.engine.image.move(moveLeft, moveUp);

    // Update canvas-size
    this.engine.setSize(bbox.x2-bbox.x+(horizontalPadding*2),bbox.y2-bbox.y+(QuizUtil.CANVAS_PADDING*2));

    this.updateForm();
  }
};

/*
 * A user's answers
 */
var Answers = {
  elements: [],
  setAnswer: function(label_id, hotspot_id) {
    this.elements[label_id] = hotspot_id ;
    this.updateForm();
  },
  removeAnswer: function(label_id) {
    delete this.elements[label_id];
    this.updateForm();
  },
  toJson: function() {
    var json = '';
    var count=0;
    for (var key in this.elements) {
      json += (count>0 ? ',' : '') + '{"label_id":'+key+',"hotspot_id":'+this.elements[key]+'}';
      count++;
    }

    if(count===0) {
      return '';
    }
    else {
      return '['+json+']';
    }
  },
  updateForm: function() {
    $('input[name=tries]').val(this.toJson());
  }
};

Drupal.behaviors.quiz_ddlines = {
  initialized: false,
  attach: function(context) {
    /* Auto adjust canvas size */
    $('.node-quiz_ddlines-form #edit-submit:not(.canvas-adjusted)').click(function() {
      QuizElementList.adjustCanvasSize();
      $(this).addClass('canvas-adjusted');
    });

    // Make hotspot radius only accept numbers:
    $('input#edit-hotspot-radius').keypress(function(e) {
      var key_codes = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 8];

      if (!($.inArray(e.which, key_codes) >= 0)) {
        e.preventDefault();
      }
    });

    // Initializing the result page; the correct answer part
    $('.quiz-ddlines-correct-answers', context).each(function() {
      // Id is the node id of the question node
      // Will be overwritten in engine.init
      var id = $(this).attr('id');

      var engine = new Engine();
      engine.init(this, id);

      // Load elements if they exists:
      QuizElementList.load(engine, false, id);
    });

    // Initializing the result page; the user answer part
    $('.quiz-ddlines-user-answers', context).each(function() {
      // Id is the node id of the question node
      // Will be overwritten in engine.init
      var id = $(this).attr('id');

      var engine = new Engine();
      engine.init(this, id);

      // Load elements if they exists:
      QuizElementList.load(engine, true, id);
    });

    $('.image-preview', context).each(function() {
      if(this.initialized) {
        return;
      }
      var self = this;
      this.initialized = true;

      // Initialize
      var engine = new Engine();

      // Need to wait for IE to make image beeing displayed
      // This is not a great solution, but it does work.
      setTimeout( function() {
        engine.init(self);

        // Load elements if they exists:
        QuizElementList.load(engine);

        // Show helptext if no alternatives have been added:
        if(engine.isNew()) {
          engine.addHelpText();
        }
      }, ($.browser.msie ? 1000 : 0));
    });
  }
};

// generic functions for dragging of sets:
function set_drag_start(x, y, event, set) {
  set = QuizUtil.defined(set) ? set : this.set;

  QuizUtil.drag_mode = false;

  set.ox = x;
  set.oy = y;
}
function set_drag_move(dx, dy, x, y, event, set) {
  QuizUtil.drag_mode = true;

  set = QuizUtil.defined(set) ? set : this.set;

  if(QuizElementList.engine.isEditMode()) {
    var inside = true;
    // Do not allow dragging outside canvas:
    set.forEach(function(elm){
      var elm_x,elm_y,elm_width,elm_height;
      if(elm.type === "circle") {
        var radius = elm.attr("r");
        elm_x = elm.attr("cx")+(x - elm.set.ox)-radius;
        elm_y = elm.attr("cy")+(y - elm.set.oy)-radius;
        elm_width = elm_height = radius*2;
      }
      else {
        elm_x = elm.attr("x")+(x - elm.set.ox);
        elm_y = elm.attr("y")+(y - elm.set.oy);
        var elm_bbox = elm.getBBox();
        elm_width = elm_bbox.width;
        elm_height = elm_bbox.height;
      }

      var going_left = (x - elm.set.ox) < 0;
      var going_up = (y - elm.set.oy) < 0;

      if((elm_x<-10 && going_left)
          || (elm_y<-10 && going_up)
          || ((elm_x + elm_width)>QuizElementList.engine.getCanvasWidth()+30 && !going_left)
          || (elm_y + elm_height)>QuizElementList.engine.getCanvasHeight()+10 && !going_up) {
        inside = false;
        return false;
      }
    });

    if(!inside) {
      return false;
    }
  }

  set.forEach(function(elm){
    if(elm.type === "circle") {
      elm.attr({cx: elm.attr("cx")+(x - elm.set.ox),cy: elm.attr("cy")+(y - elm.set.oy)});
    }
    else {
      elm.attr({x: elm.attr("x")+(x - elm.set.ox),y: elm.attr("y")+(y - elm.set.oy)});
    }
  });

  set.ox = x;
  set.oy = y;

  if(QuizUtil.defined(set.parent)) {
    set.parent.redrawConnection();
  }

  return true;
};
function set_drag_finished(event) {
  // Update form:
  QuizElementList.updateForm();
};

/*
 * The main class. Representing the canvas.
 * */
function Engine() {
  var self = this;
  this.id = null;
  this.r = null;
  this.conf = null;
  this.node_id = null;
  this.helptext = null;

  this.getSelector = function() {
    return "#"+this.id;
  };

  this.init = function (container_class, node_id) {

    if(!QuizUtil.defined(Engine.counter)) {
      Engine.counter = 0;
    }
    Engine.counter++;
    this.id = "ddlines-container-"+Engine.counter;
    this.node_id = QuizUtil.defined(node_id) ? node_id : null;

    // Add a specific ID and class to div, so CSS may be set only
    // for our case:
    $(container_class).attr("id",this.id);
    $(container_class).addClass("ddlines-container");

    this.conf = Drupal.settings.quiz_ddlines;

    if(this.isEditMode()) {
      this.conf.feedback.enabled = $('#edit-feedback-enabled').is(':checked') ? "1" : "0";
      $('#edit-feedback-enabled').change(function(){
        // Set the conf variable:
        self.conf.feedback.enabled = $('#edit-feedback-enabled').is(':checked') ? "1" : "0";
        $('#feedback-disabled').css({'display': (self.feedbackEnabled() ? 'none' : 'block')});
      });

      // Listen to change events on hotspot radius input:
      $('input#edit-hotspot-radius').change(function(e) {
        QuizElementList.updateHotspotRadius($(this).val());
      });

      // Add click-handler to add elements when clicking in canvas:
      $(this.getSelector()).click(function(event) {

        var targetIsSVG = (event.target.nodeName === 'svg' || event.target.nodeName === 'DIV');
        var targetIsImage = (event.target.nodeName === 'image' || event.target.nodeName === 'shape');

        if(!targetIsSVG && QuizUtil.drag_mode){
          return;
        }

        // Don't create new element when focus is on inputbox
        if(QuizUtil.current_editor != null && (targetIsSVG || targetIsImage)) {
          QuizUtil.current_editor.editingDone();
          return;
        }

        if(targetIsSVG || targetIsImage ||
          (self.helptext != null && event.target.nodeName === 'tspan')) {

          // Remove help text:
          if(self.helptext != null) {
            self.helptext.remove();
            self.helptext = null;
          }

          // Add element:
          self.createNewElement(event);
        }
      });

      $(this.getSelector()).resizable({
         stop: function(event, ui) {
           // Update size!
           var height=$(self.getSelector()).height();
           var width=$(self.getSelector()).width();
           self.setSize(width,height);
         }
         /*minHeight: 300,
         minWidth: 450*/
      });

      // Add delete handler:
      $(document).keydown(function(event) {
        // Check if the deletion did not take place within an input field
        // 46 is the delete button
        if(event.target.nodeName != 'INPUT' && event.which === 46) {
          // The glow represents the current selected object
          if(QuizUtil.current_glow != null) {
            QuizUtil.current_glow.set.parent.remove();
            QuizUtil.current_glow = null;
            $("#quiz-ddlines-toolpane").fadeOut();
          }
        }
      });

      // Add clearing of data when image is removed
      $('form.node-quiz_ddlines-form #edit-field-image-und-0-remove-button').mousedown(function() {
        QuizElementList.clear();

        QuizUtil.imageChanged = true;
      });
    }

    // Set size of canvas
    $(this.getSelector()).height(this.getCanvasHeight()).width(this.getCanvasWidth());

    // Create paper
    this.r = Raphael(this.id, this.getCanvasWidth(), this.getCanvasHeight());

    // Get image attributes:
    var img_width = $(this.getSelector() + ' > img').attr("width");
    var img_height = $(this.getSelector() + ' > img').attr("height");
    var img_uri=$(this.getSelector() + ' > img').attr("src");
    this.image = new QuizImage(this, img_uri, img_width, img_height);
  };

  this.addHelpText = function() {
    if(this.isEditMode()) {
      // Add help text:
      // Only if this
      self.helptext = this.r.text(this.getCanvasWidth()/2,this.getCanvasHeight()/2,Drupal.t("Click anywhere in\nthe canvas to\nadd an alternative"));
      self.helptext.attr({'font-size': 50, 'fill': '#FFF', stroke:'#000', 'font-weight': 'bold'});

      self.helptext.mousedown(function(){
        QuizUtil.drag_mode = false;
      });
    }
  };

  this.getCanvasHeight = function() {
    if(this.isResultMode()) {
      return this.conf["correct-"+this.node_id].canvas.height;
    }
    else {
      return parseInt(this.conf.canvas.height);
    }
  };

  this.getCanvasWidth = function() {
    if(this.isResultMode()) {
      return this.conf["correct-"+this.node_id].canvas.width;
    }
    else {
      return parseInt(this.conf.canvas.width);
    }
  };

  this.resizePaper = function(width, height) {
    this.setSize(width,height);
    $(this.getSelector()).height(height).width(width);
  };

  this.setSize = function(width,height) {
    if(this.isEditMode()) {
      this.conf.canvas.width=width;
      this.conf.canvas.height=height;
    }
    this.r.setSize(width,height);
  };

  this.redrawConnections = function() {
    for (var i = QuizElementList.elements.length; i--;) {
      QuizElementList.elements[i].redrawConnection();
    }
    this.r.safari();
  };

  this.createNewElement = function (event) {
    // Create a new element
    var x = this.getRelativeX(event.pageX);
    var y = this.getRelativeY(event.pageY);
    var element = new QuizElement(self, Raphael.getColor(0.9), "", undefined, x > 20 ? x-20 : x, y > 80 ? y-80 : y, undefined, x, y);
    // Add to list
    QuizElementList.add(element);

    element.gotoEditMode();
  };

  this.toJson = function() {
    return '"canvas":{"width":'+this.conf.canvas.width+',"height":'+this.conf.canvas.height+'}';
  };

  this.getPosition = function() {
    return $(this.getSelector()).offset();
  };

  this.getRelativeX = function(x) {
    return (x-this.getPosition().left);
  };

  this.getRelativeY = function(y) {
    return (y-this.getPosition().top);
  };

  this.isNew = function() {
    return (this.conf.editmode === 'add');
  };

  this.isEditMode = function() {
    return (this.conf.mode === 'edit');
  };

  this.executionModeLines = function() {
    return (this.conf.execution_mode === '0');
  };

  this.isResultMode = function() {
    return (this.conf.mode === 'result');
  };

  this.isTakeMode = function() {
    return (this.conf.mode === 'take');
  };

  this.feedbackEnabled = function() {
    return (this.conf.feedback.enabled === '1');
  };

  this.pointInsideCanvas = function(x,y) {
    x = this.getRelativeX(x);
    y = this.getRelativeY(y);
    return (x>5 && y>5 && x<this.conf.canvas.width-5 && y<this.conf.canvas.height-5);
  };

  this.showInfoPopup = function(text, border_color) {
    if(text) {
      // Show feedback:
      // Create a div, since shapes in raphael need a value for height, width,
      // and we don't know how much space we need at this point.

      // Calculate the displaytime for the message based on the length of the text:
      var displaytime = 1800 + (text.length*30);

      var $feedback = $('
'+text+'
');
      $feedback.css({'border-color': border_color, 'display': 'none'});
      $(this.getSelector()).append($feedback);
      $feedback.fadeIn();
      setTimeout(function() { $feedback.fadeOut(); }, displaytime);
    }
  };
};

/**
 * The image class
 */
function QuizImage(engine, uri, width, height) {

  /*var self = this;*/

  this.engine = engine;
  this.image = this.engine.r.image(uri, 0, 0, width, height);
  this.image.toFront();

  if(this.engine.isEditMode()) {

    // Center image when added:
    if(this.engine.isNew()) {
      this.image.attr({"x": (engine.getCanvasWidth()/2)-(width/2) ,"y": (engine.getCanvasHeight()/2)-(height/2)});
    }

    /*
    var bbox = this.image.getBBox();
    this.image.resizer = this.engine.r.rect(bbox.x2-20,bbox.y2-20,20,20);
    this.image.resizer.attr({color: "#00bb27", "fill": "#00bb27", "fill-opacity": 0.9, opacity:0.9, cursor: "se-resize"});
    */

    this.image.attr({cursor:'move'});
    /*
    rstart = function () {
      this.ox = this.attr("x");
      this.oy = this.attr("y");

      self.image.ow = self.image.attr("width");
      self.image.oh = self.image.attr("height");
    },
    rmove = function (dx, dy) {
        this.attr({x: this.ox + dx, y: this.oy + dy});
        self.image.attr({width: self.image.ow + dx, height: self.image.oh + dy});
    };
    this.image.resizer.drag(rmove, rstart);*/

    // Setup image dragging handling
    function image_drag_move(dx, dy, x, y, event) {
      if(set_drag_move(dx, dy, x, y, event, this.set)) {
        // Move all hotspots accordingly:
        for (var i = QuizElementList.elements.length; i--;) {
          set_drag_move(dx, dy, x, y, event, QuizElementList.elements[i].uiHotspot.set);
        }
      }
    }

    function image_drag_start(x, y, event) {
      set_drag_start(x, y, event, this.set);

      // Make all hotspots readu to be moved:
      for (var i = QuizElementList.elements.length; i--;) {
        set_drag_start(x, y, event, QuizElementList.elements[i].uiHotspot.set);
      }
    }

    var set = this.engine.r.set();
    set.push(this.image);
    //set.push(this.image.resizer);
    this.image.set = set;
    //this.image.resizer.set = set;
    set.drag(image_drag_move, image_drag_start, set_drag_finished);
  }

  this.toJson = function() {
    return '"image":{"left":'+this.image.attr("x")+',"top":'+this.image.attr("y")+',"width":'+this.image.attr("width")+',"height":'+this.image.attr("height")+'}';
  };

  this.setBounds = function(x,y,width,height) {
    this.image.attr({"x":x, "y":y, "width":width, "height":height});
  };

  this.getBBox = function() {
    return this.image.getBBox();
  };

  this.move = function(deltax, deltay) {
    this.image.attr({"x":this.image.attr("x")+deltax, "y":this.image.attr("y")+deltay});
  };
}

/**
 * The label UI element class
 */
function QuizLabel(parent, color, id, text, x, y) {

  var self = this;

  this.parent = parent;
  this.color = color;
  this.text = text;

  this.setText = function(text) {

    self.label.text.hide();

    // Set the new text
    self.label.text.attr({text: text});

    // Recalculate rectangle size.
    var bbox = self.label.text.getBBox();
    self.label.text.attr({
      x: self.label.attr("x")+bbox.width/2+10,
      y: self.label.attr("y")+10});

    // Set new width of parent rectangle:
    var rect_width = bbox.width+20;
    self.label.attr({width: rect_width < QuizUtil.LABEL_MIN_WIDTH ? QuizUtil.LABEL_MIN_WIDTH : rect_width});
    self.label.fg.attr({width: rect_width < QuizUtil.LABEL_MIN_WIDTH ? QuizUtil.LABEL_MIN_WIDTH : rect_width});

    // Set size of glow if it exists
    if(QuizUtil.defined(self.glow)) {
      self.glow.attr({width: rect_width+8 < QuizUtil.LABEL_MIN_WIDTH+8 ? QuizUtil.LABEL_MIN_WIDTH+8 : rect_width+8});
    }

    self.label.text.show();
  };

  this.updateTextPosition = function() {
    this.setText(this.text);

    // Update position of foreground object:
    var bbox = self.label.getBBox();
    self.label.fg.attr({x:bbox.x, y:bbox.y, width:bbox.width, height: bbox.height});
    self.label.fg.show();
  };

  // Create Raphael objects:
  this.label = this.parent.engine.r.rect(x, y, 100, 20);
  this.label.parent = this;

  // Use same id as previous if this is set
  if(QuizUtil.defined(id)) {
    this.label.id = id;
  }

  this.label.text = this.parent.engine.r.text(-200,y+10,""); // initially hide the text;
  this.label.fg = this.parent.engine.r.rect(x-5, y-5, 110, 30); // Foreground object

  // Set attributes:
  this.label.attr({fill: "#fff", stroke: this.color, "fill-opacity": 1, "stroke-width": 3, cursor: (!this.parent.engine.isResultMode() ? "move" : "default")});
  this.label.text.attr({"font-size": 12, cursor: (!this.parent.engine.isResultMode() ? "move" : "default")});
  this.label.fg.attr({fill: "#fff", "fill-opacity": 0, "stroke-width": 0, "stroke-opacity":0, cursor: (!this.parent.engine.isResultMode() ? "move" : "default")});
  this.label.fg.toFront();

  // Create a set so they can be treated as one:
  this.set = this.parent.engine.r.set();
  this.set.parent = parent;
  this.set.push(this.label, this.label.text, this.label.fg);

  // Create backreference from elements to the set:
  this.label.set = this.label.text.set = this.label.fg.set = this.set;

  // Set text if value set:
  this.setText(text);

  // Move it to center of hotspot if resultpage
  // and execution modes without lines:
  if(!this.parent.engine.executionModeLines() && this.parent.engine.isResultMode() && QuizUtil.defined(this.parent.uiHotspot)) {
    // Get hotspot:
    var center = this.parent.uiHotspot.getCenter();
    if (center != null) {
      this.set.forEach(function(element) {
        element.attr({x: center.x-(element.attr('width')/2), y:center.y-(element.attr('height')/2)});
      });
    }
  }

  this.toJson = function(){
    return '"label":{"id":'+this.label.id+',"x":'+this.label.attr("x")+',"y":'+this.label.attr("y")+',"text":"'+this.label.text.attr("text")+'"}';
  };

  this.setColor = function(color) {
    this.color = color;
    this.label.attr({stroke: this.color});
  };

  if(this.parent.engine.isEditMode()) {
    this.set.drag(set_drag_move,set_drag_start,set_drag_finished);
  }

  var edit_mode = function (event) {
    // Add an inputbox as overlay:
    // Get dimensions of rect

    if(QuizUtil.drag_mode) {
      return false;
    }

    if(event !== null) {
      event.stopPropagation();
    }

    if(QuizUtil.current_editor != null) {
      QuizUtil.current_editor.editingDone();
    }

    var me = QuizUtil.current_editor = this;

    var topleft=self.label.attr("x")-2;
    var topright=self.label.attr("y")-2;
    var bbox=self.label.getBBox();

    var $editButton = $('<input type="text" id="quiz-ddlines-edit" value="'+self.label.text.attr("text")+'"></input>');
    $editButton.css({
      'position': 'absolute',
      'left': topleft+'px',
      'top': topright+'px',
      'z-index': 99999,
      'border': '2px dashed '+self.color,
      'height': (bbox.height+4)+'px',
      'width': (bbox.width+4)+'px'
    });

    this.editingDone = function() {
      // Save the text
      self.parent.setText($editButton.val());
      // Remove the input field
      $editButton.remove();
      self.parent.redrawConnection();

      QuizUtil.current_editor = null;
    };

    // Listen on editing finished:
    $editButton.keypress(function(event) {
      // 13 is enter
      if(event.which === 13) {
        me.editingDone();
      }
    });
    $editButton.keyup(function(event) {
      // Update toolpane:
      $('#quiz-ddlines-toolpane label > em').html($editButton.val());
    });

    $(self.parent.engine.getSelector()).append($editButton);
    setTimeout( function() {
      $editButton.focus();
    }, 100);

    return false;
  };

  var focus_mode = function () {
    if($('#quiz-ddlines-toolpane').length != 0) {
      $('#quiz-ddlines-toolpane').remove();
    }

    if(QuizUtil.current_glow != null) {
      if(QuizUtil.current_glow.set) {
        QuizUtil.current_glow.set.exclude(QuizUtil.current_glow);
      }
      QuizUtil.current_glow.remove();
      QuizUtil.current_glow = null;
    }

    QuizUtil.current_glow = self.parent.engine.r.rect(self.label.attr('x')-4, self.label.attr('y')-4, self.label.attr('width')+8, self.label.attr('height')+8, 5);
    QuizUtil.current_glow.attr({"fill-opacity": 0, "stroke": self.color, "stroke-width": 4, "stroke-opacity": 0.3});
    QuizUtil.current_glow.parent_id = self.label.id;

    self.glow = QuizUtil.current_glow;
    self.set.push(QuizUtil.current_glow);
    QuizUtil.current_glow.set = self.set;

    /*var topleft=self.label.attr("x")-2;
    var topright=self.label.attr("y")-2;
    var bbox=self.label.getBBox();*/
    var selected_text=self.label.text.attr("text");

    var $toolPane = $('

');
    var $buttonPane = $('

');
    var $feedbackPane = $('

');
    var $feedbackCorrect = $('<input type="text" class="form-text feedback correct" value="'+self.parent.feedback_correct+'"></input>');
    var $feedbackWrong = $('<input type="text" class="form-text feedback wrong" value="'+self.parent.feedback_wrong+'"></input>');
    var $feedbackLabel = $('
'+Drupal.t('Settings for')+' '+selected_text+'
');
    var $deleteButton = $('<input id="ddlines-delete-element" type="button" class="form-submit" tabindex="-1" value="'+Drupal.t('delete')+'">');
    var $colorButton = $('<input id="ddlines-change-color" class="form-submit" type="button" value="'+Drupal.t('color')+'">');
    var $closeButton = $('<input id="ddlines-close-panel" class="form-submit" type="button" value="'+Drupal.t('save')+'">');

    $toolPane.css({
      'z-index': 10001,
      'border-color': self.color
    });

    $(self.parent.engine.getSelector()).append($toolPane);
    $toolPane.append($feedbackPane);
    $toolPane.append($buttonPane);

    $feedbackPane.append($feedbackLabel);
    $feedbackPane.append($(''+Drupal.t('Feedback when correct')+''));
    $feedbackPane.append($(''+Drupal.t('Feedback when wrong')+''));
    $feedbackPane.append($feedbackCorrect);
    $feedbackPane.append($feedbackWrong);

    var updateFeedback = function(){
      self.parent.setFeedback($feedbackCorrect.val(), $feedbackWrong.val());
    };
    $feedbackCorrect.keyup(updateFeedback);
    $feedbackWrong.keyup(updateFeedback);

    // Add feedback disabled:
    var $feedbackDisabled = $('

'+Drupal.t('Feedback disabled')+'

');
    $feedbackDisabled.css({'display': self.parent.engine.feedbackEnabled() ? 'none' : 'block'});
    $feedbackPane.append($feedbackDisabled);

    $buttonPane.append($colorButton);
    $buttonPane.append($closeButton);
    $buttonPane.append($deleteButton);

    // Create container:
    var $colorContainer = $('

').css({'width':'150px','height':'150px'});
    $toolPane.append($colorContainer);
    var cw = Raphael.colorwheel($('#colorwheel-container'), 150);
    cw.color(self.color);
    cw.onchange(function(color) {
      $toolPane.css({'border-color': color.hex});
      $colorContainer.css({'border-color': color.hex});
      self.parent.setColor(color.hex);
    });

    // Colorbutton clicked
    $colorButton.click(function() {

      // If color container is visible, close it
      if ( $colorContainer.is(":visible") ) {
        $colorContainer.hide();
      }
      else {

        /*var position = $toolPane.position();
        var pos_left = (position.left + 300) + "px";
        var pos_top = (position.top - 150) + "px";*/

        // Set position of container:
        $colorContainer.css({'border-color': self.color}).show();
      }
    });

    $deleteButton.click(function() {
      $("#quiz-ddlines-toolpane").fadeOut();
      if(QuizUtil.current_editor != null) {
        QuizUtil.current_editor.editingDone();
      }
      self.parent.remove();
    });

    $('#ddlines-close-panel').click(function() {
      // Hide colorwheel:
      $colorContainer.hide();

      // Update form for saving
      QuizElementList.updateForm();

      $("#quiz-ddlines-toolpane").fadeOut();
    });
  };

  if(this.parent.engine.isEditMode()) {
    this.set.click(edit_mode);
    this.set.mousedown(focus_mode);
  }

  this.gotoEditMode = function() {
    focus_mode();
    edit_mode(null);
  };

  this.remove = function() {
    this.set.remove();
  };

  this.getBBox = function() {
    return this.label.getBBox();
  };

  this.move = function(deltax,deltay) {
    this.label.attr({"x": this.label.attr("x") + deltax});
    this.label.attr({"y": this.label.attr("y") + deltay});
  };
}

function QuizLabelDrag(parent, label, color) {
  var self = this;

  this.initial_x = label.attr('x');
  this.initial_y = label.attr('y');

  this.label = label;
  this.parent = parent;
  this.color = color;
  this.ox = this.oy = null;

  var drag_start = function(x,y) {
    self.ox = x;
    self.oy = y;
    self.label.set.toFront();
  };

  var drag_move = function(dx,dy,x,y) {

    /*if(!self.parent.engine.pointInsideCanvas(x,y)) {
      return;
    }*/

    self.label.set.forEach(function(elm){
      elm.attr({x: elm.attr("x")+(x - self.ox), y: elm.attr("y")+(y - self.oy)});
    });

    self.ox = x;
    self.oy = y;

    // Hover on hits:
    x = self.label.attr('x')+(self.label.attr('width')/2);
    y = self.label.attr('y')+(self.label.attr('height')/2);
    var hit_hotspot = false;
    for (var i = QuizElementList.elements.length; i--;) {
      // Check if x,y is within BBox:
      var id = QuizElementList.elements[i].uiHotspot.hotspot.id;
      if(QuizElementList.elements[i].uiHotspot.hotspot.margin.isPointInside(x,y)) {

        hit_hotspot = true;

        if(QuizUtil.current_glow === null || QuizUtil.current_glow.parent_id != id) {
          if(QuizUtil.current_glow != null) {
            QuizUtil.current_glow.remove();
            QuizUtil.current_glow = null;
          }
          QuizUtil.current_glow = QuizElementList.elements[i].uiHotspot.hotspot.glow({"color": self.color, width: self.label.attr('width'), fill: true, opacity: 1.0});
          QuizUtil.current_glow.parent_id = id;
        }

        break;
      }
    }

    if(!hit_hotspot && QuizUtil.current_glow != null) {
      QuizUtil.current_glow.remove();
      QuizUtil.current_glow = null;
    }
  };

  var drag_finish = function(event) {

    if(QuizUtil.current_glow != null) {
      QuizUtil.current_glow.remove();
    }

    var x = self.label.attr("x") + (self.label.attr("width")/2);
    var y = self.label.attr("y") + (self.label.attr("height")/2);

    // Inside any hotspot at all?
    var targets = self.parent.engine.r.getElementsByPoint(x, y);
    var selected_hotspot=null;

    targets.forEach(function(e){
      if(e.isHotspotMargin) {
        selected_hotspot = e.hotspot;
        // Makes callback stop (like break if this was a for loop)
        return false;
      }
    });

    var correct_answer = selected_hotspot === null ? false : (self.parent.uiHotspot.hotspot === selected_hotspot);
    var feedback_enabled = self.parent.engine.feedbackEnabled();

    if((!feedback_enabled && selected_hotspot !== null) || (feedback_enabled && correct_answer)) {
      // Glue it to the center of the selected hotspot,
      // and make it smaller:
      self.label.text.hide();
      self.label.fg.hide();
      self.label.animate({
        x: selected_hotspot.attr("cx")-(self.label.attr('width')/2),
        y: selected_hotspot.attr("cy")-(self.label.attr('height')/2),
        "stroke-opacity": 0.3,
        "fill-opacity": 0.95},
        500,
        "bounce", function() {
          self.label.parent.updateTextPosition();
        });
    }

    if(selected_hotspot === null || (feedback_enabled && !correct_answer)) {
      // Animate back to source!
      // Do the animation of the label:
      self.label.text.hide();
      self.label.fg.hide();
      self.label.animate({
        "stroke-opacity": 1,
        "fill-opacity": 1,
        x: self.initial_x,
        y: self.initial_y}, 500, "bounce", function() {
          self.label.parent.updateTextPosition();
        });

      if(selected_hotspot != null && feedback_enabled && !correct_answer){
        self.parent.engine.showInfoPopup(self.parent.feedback_wrong, self.color);
      }

      Answers.removeAnswer(self.label.id);
    }
    else if(feedback_enabled && correct_answer) {
      self.parent.engine.showInfoPopup(self.parent.feedback_correct, self.color);
      // Save answer:
      Answers.setAnswer(self.label.id, selected_hotspot.id);
    }
    else if(!feedback_enabled && selected_hotspot !== null) {
      // Save answer:
      Answers.setAnswer(self.label.id, selected_hotspot.id);
    }
  };

  label.set.drag(drag_move, drag_start, drag_finish);
}

/**
 * The pointer class, the UI element dragged while taking
 * a test.
 *
 */
function QuizPointer(parent, label, color) {
  var self = this;

  this.color = color;
  this.parent = parent;
  this.label = label;
  this.radius = parseInt(parent.engine.conf.pointer.radius);

  this.connect = function() {
    return this.ie_fix;
  };

  this.createVisual = function(x,y) {
    this.pointer = this.parent.engine.r.circle(x,y,this.radius);
    this.pointer.attr({fill: this.color, stroke: this.color, "fill-opacity": 0.9, "stroke-opacity": 1, "stroke-width": 2, cursor: "move"});
    this.border = this.parent.engine.r.circle(x,y,this.radius+2);
    this.border.attr({stroke: "#fff", "stroke-width": 2, "stroke-opacity": 1});
    this.ie_fix = this.parent.engine.r.rect(x-this.radius, y-this.radius, this.radius*2, this.radius*2);
    this.ie_fix.attr({opacity:0});

    this.set = this.parent.engine.r.set();
    this.set.push(this.pointer, this.border);
  };

  this.updateVisual = function(cx, cy, updatePointer) {
    updatePointer = QuizUtil.defined(updatePointer) ? updatePointer : false;

    if(updatePointer) {
      self.pointer.attr({cx: cx, cy: cy, r:self.radius});
    }
    else {
      self.radius = parseInt(self.pointer.attr("r"));
    }

    self.ie_fix.attr({x: cx-self.radius, y:cy-self.radius, width: self.radius*2, height: self.radius*2});
    self.border.attr({cx: cx, cy: cy, r:(self.radius+2)});

    self.parent.redrawConnection();
  };

  // Start dragging pointer
  this.pointer_drag_start = function(x,y) {
    if(!self.pointer) {
      self.createVisual(self.parent.engine.getRelativeX(x), self.parent.engine.getRelativeY(y));

      if(!self.parent.connection) {
        self.parent.createConnection();
      }

      self.pointer.drag(self.pointer_move, self.pointer_drag_start, self.pointer_up);
    }
  };

  // Dragging of pointer
  this.pointer_move = function(dx,dy,x,y) {
    /*if(!self.parent.engine.pointInsideCanvas(x,y)) {
      return;
    }*/
    x = self.parent.engine.getRelativeX(x);
    y = self.parent.engine.getRelativeY(y);

    self.updateVisual(x,y,true);

    // Check if hotspot is hit, for hovering:
    // Tried using onDragOver, but that did not work. See comment here:
    // http://dashasalo.com/2011/08/15/raphaeljs-2-0-ondragover-limitation/
    var hit_hotspot = false;
    for (var i = QuizElementList.elements.length; i--;) {
      // Check if x,y is within BBox:
      var id = QuizElementList.elements[i].uiHotspot.hotspot.id;
      if(QuizElementList.elements[i].uiHotspot.hotspot.isPointInside(x,y)) {

        hit_hotspot = true;

        if(QuizUtil.current_glow === null || QuizUtil.current_glow.parent_id !== id) {
          if(QuizUtil.current_glow !== null) {
            QuizUtil.current_glow.remove();
            QuizUtil.current_glow = null;
          }
          QuizUtil.current_glow = QuizElementList.elements[i].uiHotspot.hotspot.glow({"color": self.color, width: 20, fill: true, opacity: 1.0});
          QuizUtil.current_glow.parent_id = id;
        }

        break;
      }
    }

    if(!hit_hotspot && QuizUtil.current_glow !== null) {
      QuizUtil.current_glow.remove();
      QuizUtil.current_glow = null;
    }
  };

  this.pointer_up = function(event) {

    if(QuizUtil.current_glow !== null) {
      QuizUtil.current_glow.remove();
    }

    var x = self.pointer.attr("cx");
    var y = self.pointer.attr("cy");

    // Inside any hotspot at all?
    var targets = self.parent.engine.r.getElementsByPoint(x, y);
    var selected_hotspot=null;

    targets.forEach(function(e){
      if(e !== self.pointer && e.isHotspot) {
        // Hit one
        // Check if correct hotspot hit.
        //correct_answer = (self.parent.uiHotspot.hotspot == e);
        selected_hotspot = e;

        // Makes callback stop (like break if this was a for loop)
        return false;
      }
    });

    var correct_answer = selected_hotspot===null ? false : (self.parent.uiHotspot.hotspot == selected_hotspot);
    var feedback_enabled = self.parent.engine.feedbackEnabled();

    if((!feedback_enabled && selected_hotspot !== null) || (feedback_enabled && correct_answer)) {
      // Remove connecting line:
      self.parent.hideConnection();

      // Glue it to the center of the selected hotspot:
      self.set.animate({cx: selected_hotspot.attr("cx"), cy: selected_hotspot.attr("cy"), r: selected_hotspot.attr("r")}, 500, "bounce", function() {
        self.updateVisual(self.pointer.attr("cx"), self.pointer.attr("cy"), false);
      });
    }

    if(selected_hotspot === null || (feedback_enabled && !correct_answer)) {
      // Animate back to source!
      // Remove connecting line:
      self.parent.hideConnection();

      // Do the animation of the pointer
      var bbox = self.label.getBBox();
      self.set.animate({cx: self.label.attr("x")+(bbox.width/2), cy: self.label.attr("y")+50, r: self.parent.engine.conf.pointer.radius}, 500, "bounce", function() {
        self.updateVisual(self.pointer.attr("cx"), self.pointer.attr("cy"), false);
      });

      if(selected_hotspot !== null && feedback_enabled && !correct_answer){
        self.parent.engine.showInfoPopup(self.parent.feedback_wrong, self.color);
      }

      Answers.removeAnswer(self.label.id);
    }
    else if(feedback_enabled && correct_answer) {
      self.parent.engine.showInfoPopup(self.parent.feedback_correct, self.color);
      // Save answer:
      Answers.setAnswer(self.label.id, selected_hotspot.id);
    }
    else if(!feedback_enabled && selected_hotspot !== null) {
      // Save answer:
      Answers.setAnswer(self.label.id, selected_hotspot.id);
    }
  };

}

/**
 * The hotspot UI element class
 */
function QuizHotspot(parent, color, id, x, y, radius) {
  var self = this;
  this.parent = parent;
  this.color = color;

  this.radius = parseInt(self.parent.engine.conf.hotspot.radius);

  this.hotspot = self.parent.engine.r.circle(x, y, this.radius);
  this.hotspot.attr({fill: "#fff", stroke: "#000", "fill-opacity": 0.4, "stroke-opacity": 1, "stroke-width": 2});
  this.hotspot.isHotspot=true;

  this.hotspot.margin = self.parent.engine.r.circle(x, y, this.radius+20);
  this.hotspot.margin.isHotspotMargin = true;
  this.hotspot.margin.hotspot = this.hotspot;
  this.hotspot.margin.hide();

  this.border = self.parent.engine.r.circle(x, y, this.radius+2);
  this.border.attr({stroke: "#fff", "stroke-width": 2, "stroke-opacity": 1});

  this.ie_fix = self.parent.engine.r.rect(x-this.radius, y-this.radius, this.radius*2, this.radius*2);
  this.ie_fix.attr({opacity:0});
  this.ie_fix.toFront();

  if(self.parent.engine.isEditMode()) {
    this.hotspot.attr({cursor: "move", stroke: this.color});
  }

  if(QuizUtil.defined(id)) {
    this.hotspot.id = id;
  }

  if(self.parent.engine.isEditMode()) {
    this.set = self.parent.engine.r.set();
    this.set.parent = parent;
    this.set.push(this.hotspot, this.border, this.ie_fix);
    this.hotspot.set = this.set;
    this.border.set = this.set;
    this.ie_fix.set = this.set;

    this.hotspot.set.drag(set_drag_move,set_drag_start,set_drag_finished);
  }

  this.connect = function() {
    return this.ie_fix;
  };

  this.toJson = function() {
    return '"hotspot":{"id":'+this.hotspot.id+',"x":'+this.hotspot.attr("cx")+',"y":'+this.hotspot.attr("cy")+'}';
  };

  this.remove = function() {
    this.hotspot.remove();
    this.border.remove();
  };

  this.setColor = function(color) {
    this.color = color;
    this.hotspot.attr({stroke: this.color});
  };

  this.updateHotspotRadius = function(radius) {
    var previous_radius = this.radius;
    var diff = radius-previous_radius;
    this.radius = radius;

    this.hotspot.attr({r: radius});
    this.border.attr({r: radius+2});
    this.ie_fix.attr({x: this.ie_fix.attr('x')-diff, y: this.ie_fix.attr('y')-diff, width: radius*2, height: radius*2});
  };

  this.getCenter = function() {
    if(this.hotspot) {
      return {x: this.hotspot.attr('cx'), y:this.hotspot.attr('cy')};
    }
    else {
      return null;
    }
  };

  this.getBBox = function() {
    return this.hotspot.getBBox();
  };

  this.move = function(deltax,deltay) {
    this.hotspot.attr({"cx": this.hotspot.attr("cx") + deltax});
    this.hotspot.attr({"cy": this.hotspot.attr("cy") + deltay});
  };
}

/**
 * The quiz ddlines element.
 *
 * It contains the metadata needed to draw the label, hotspot, pointer
 * and connecting lines
 *
 */
function QuizElement (engine, color, text, label_id, label_x, label_y, hotspot_id, hotspot_x, hotspot_y, feedback_correct, feedback_wrong, correct_answer) {

  var self = this;
  this.engine = engine;

  text = QuizUtil.defined(text) ? text : "";
  label_x = QuizUtil.defined(label_x) ? label_x : 5;
  label_y = QuizUtil.defined(label_y) ? label_y : 5;
  hotspot_x = QuizUtil.defined(hotspot_x) ? hotspot_x : 55;
  hotspot_y = QuizUtil.defined(hotspot_y) ? hotspot_y : 100;
  this.feedback_wrong = QuizUtil.defined(feedback_wrong)  ? feedback_wrong : engine.conf.feedback.wrong;
  this.feedback_correct = QuizUtil.defined(feedback_correct) ? feedback_correct : engine.conf.feedback.correct;
  correct_answer = QuizUtil.defined(correct_answer) ? correct_answer : null;

  // Create default hotspot and label
  this.color = color;

  if((correct_answer !== null || hotspot_id !== null) && hotspot_x !== null) {
    this.uiHotspot = new QuizHotspot(this, color, hotspot_id, hotspot_x, hotspot_y);
  }

  if(correct_answer !== null || label_id !== null) {
    this.uiLabel = new QuizLabel(this, color, label_id, text, label_x, label_y);
  }

  if(this.engine.isTakeMode()) {
    if(this.engine.executionModeLines()) {
      this.pointer = new QuizPointer(this, this.uiLabel.label, color);
      this.uiLabel.set.drag(this.pointer.pointer_move, this.pointer.pointer_drag_start, this.pointer.pointer_up);
    }
    else {
      // Make label beeing draggable
      new QuizLabelDrag(this, this.uiLabel.label, color);
    }
  }

  this.createConnection = function() {
    if(self.engine.isEditMode() || self.engine.executionModeLines()) {
      this.connection = this.engine.r.connection(this.uiLabel.label, (this.engine.isTakeMode() ? this.pointer.connect() : this.uiHotspot.connect()), this.color, "#FFF|5");
    }
  };

  this.hideConnection = function() {
    if(self.engine.isEditMode() || self.engine.executionModeLines()) {
      this.connection.bg.hide();
      this.connection.line.hide();
    }
  };

  if(this.engine.isEditMode() || (this.engine.isResultMode() && hotspot_id !== null && label_id !== null)) {
    this.createConnection();
  }

  if(this.engine.isResultMode() && (correct_answer != null || (label_id === null || hotspot_id === null))) {

    //var settings = {color: (correct_answer ? '#00bb27' : '#fe2020'), width: 20, fill: true, opacity: 1};

    var imagepath = this.engine.conf.quiz_imagepath + (correct_answer ? "icon_ok" : "icon_wrong") + ".gif";

    // Set glow color:
    if(QuizUtil.defined(this.uiLabel)) {
      // Create Image:
      var bbox = this.uiLabel.getBBox();
      this.engine.r.image(imagepath, bbox.x-8, bbox.y-8, 20, 20);
      //this.engine.r.image.attr({'width': 16, 'height': 16});

      //this.uiLabel.label.glow(settings);
    }
    /*if(QuizUtil.defined(this.uiHotspot) && this.engine.executionModeLines()) {
      //this.uiHotspot.hotspot.glow(settings);
      var bbox = this.uiHotspot.getBBox();
      this.engine.r.image(imagepath, bbox.x, bbox.y, 16, 16);
    }*/
  }

  this.redrawConnection = function() {
    if(this.connection) {
      this.connection.bg.show();
      this.connection.line.show();
      this.engine.r.connection(this.connection);
    }
    this.engine.r.safari();
  };

  this.gotoEditMode = function() {
    this.uiLabel.gotoEditMode();
  };

  this.toJson = function() {
    // Generates JSON
    return '{"feedback_wrong":"'+this.feedback_wrong+'",'+'"feedback_correct":"'+this.feedback_correct+'","color":"'+this.color+'",'+this.uiLabel.toJson()+','+this.uiHotspot.toJson()+'}';
  };

  this.setFeedback = function(correct, wrong) {
    this.feedback_correct = correct;
    this.feedback_wrong = wrong;

    // Update list:
    QuizElementList.updateForm();
  };

  this.setText = function(text) {
    // Set the new text
    this.uiLabel.setText(text);

    // Update form element, so it is ready to be saved
    QuizElementList.updateForm();
  };

  this.setColor = function(color) {
    this.color = color;

    this.uiLabel.setColor(this.color);
    this.uiHotspot.setColor(this.color);

    // Set glow if it exists:
    if(QuizUtil.current_glow != null) {
      QuizUtil.current_glow.attr({stroke: this.color});
    }

    // Set connection color:
    this.connection.line.attr({stroke: this.color});
  };

  this.remove = function() {
    // Remove from list:
    QuizElementList.remove(this);

    // Remove from canvas:
    this.uiHotspot.remove();
    this.uiLabel.remove();
    this.connection.bg.remove();
    this.connection.line.remove();
  };

  this.getBBox = function() {
    var bbox = this.uiLabel.getBBox();

    if(QuizUtil.defined(this.uiHotspot)) {
      var bboxHotSpot = this.uiHotspot.getBBox();
      bbox = QuizUtil.bboxUnion(bbox, bboxHotSpot);
    }

    return bbox;
  };

  this.move = function(deltax,deltay) {
    this.uiLabel.move(deltax,deltay);
    this.uiHotspot.move(deltax,deltay);
  };
}

QuizElement.fromJson = function(json, engine) {
  return new QuizElement(
       engine,
       json.color,
       QuizUtil.defined(json.label) ? json.label.text : null,
       QuizUtil.defined(json.label) ? json.label.id : null,
       QuizUtil.defined(json.label) ? json.label.x : null,
       QuizUtil.defined(json.label) ? json.label.y : null,
       QuizUtil.defined(json.hotspot) ? json.hotspot.id : null,
       QuizUtil.defined(json.hotspot) ? json.hotspot.x : null,
       QuizUtil.defined(json.hotspot) ? json.hotspot.y : null,
       json.feedback_correct,
       json.feedback_wrong,
       QuizUtil.defined(json.correct) ? json.correct : null);
};
/*
var Glow = {
    instance: null,
    glow: function(elem, color) {
      this.remove();

      var settings = {};

      if(elem.type='circle') {
        settings = {}
      }
      else {

      }

      this.instance = elem.glow({"color": color, width: 20, fill: true, opacity: 1.0});

      Engine.r.rect(self.label.attr('x')-4, self.label.attr('y')-4, self.label.attr('width')+8, self.label.attr('height')+8, 5);

    },
    remove: function() {
      this.instance.remove();
      this.instance = null;
    },
    isGlowing(): function() {
      return (set != null);
    }
};*/

}(jQuery));

redpajama_set_name: RedPajamaGithub


Give me a like or share. Thanks a lot.
I quit my job and now I am currently a full time blogger. I like Postcrossing Project but the postage and the postcards cost will be high. I decide to print postcards myself to decrease the postcard cost. If you like them, you can send me a message. I will show you how to trade.
My name is Stephen Liu and I've been traveling Taiwan since 1982. Growing up in Kaohsiung, It seems to me I am an old traveler. I didn't take my first trip overseas until I was 29. Outside a flight and fellow trip to Hong Kong, I had no travel experience. After some years, I got married and the standard Taiwanese two weeks a year vacation. We wanted to use that time to travel. After all, it was vacation time, right? So for our first trip overseas, we went on a tour to Japan.
That trip changed our life.
From that point on, I got hooked on overseas travel.
But like most Taiwanese I only had ten days of vacation per year and I didn't know any of the smart ways to save money and travel longer. Two events changed that. One was 2moro that is a Taiwanese boy band, whose members are twins Anthony Guo and Angus Guo interviewed me when I lunched in Tung Men Dumpling Restaurant after completing an endowment in Taipei Taiwan Temple. Both brothers co-hosted a variety show Super Taste on TVBS Entertainment Channel and TVBS-Asia. This was very interesting and let me know Super Taste show. From that moment on, I began to take interest in food tourism programs like Super Taste, Globe Trekker and Fun Taiwan. This was why I started Fun Taiwan(http://funtaiwan.achi.idv.tw); FT for short, in July 2010 after the company which I worked for was merged into InnoLux and before an important event in my life that I got marriage.
The other event was that I joined Couchsurfing in 2010 and started to host members since 2013. Couchsurfing changes our lives. We open our home to travelers and learn about a new culture first-hand or practice a language. We also need to rediscover our city or country because we want to help people to know Taiwan. If possible they also help us to travel in their countries and stayed in their homes. I can't imagine what a wonderful travel we will have! I don't need to quit and don't need to be rich to travel.
And now I know Postcrossing Project. I am very exited because I can send postcards to you and receive postcards. I will enjoy this.


I closed the forceps, crushing the skull of the fetus, and withdrew the forceps. The fetus, now dead, slid out more or less intact.
— Warren Hern, 'A Doctor Ponders a New Era of Prosecution: Did I Violate the Partial-Birth Abortion Ban', Slate, Oct 22, 2003.


Comics maven John DiBello — who brought you an awesome primer on MIRACLEMAN — is back with the tale of a Marvel comic you probably never heard of.
Any serious fan of Marvel Comics is justifiably proud of a huge amount of trivia, factoids, and minutiae. The fan — heck, let's put that in capitals! — The Fan knows that cosmic menace Thanos premiered, of all places, in Iron Man #55, that the commie-smasher Captain America portrayed in 1950s Atlas-era comics was William Burnside, not Steve Rogers, and that the address of Avengers Mansion is 890 Fifth Avenue in Manhattan, a block occupied by the Frick Collection museum in our universe.
There are Marvel Comics published since Fantastic Four #1, however, that most Marvel readers never heard of after they faded into the realm of little-seen, seldom-demanded back issues. Let's pull back into the limelight one of these Marvels That Time Forgot, a phantasm who wasn't a part of Power Pack, a wraith who wasn't in World War Hulk, an apparition who never assembled with the Avengers: HOMER, THE HAPPY GHOST!
Like much of the contemporary Marvel Universe, Homer flew onto the newsstands thanks to the 1968-'69 Marvel Explosion, which dramatically increased the number of titles Stan Lee's House of Ideas published in the early 1970s.
A quick history lesson: Before 1957, Marvel's predecessors (Timely and then Atlas Comics) were distributed to newsstands by the American News Company, the largest distributor of books, magazines, and comics in the 1940s and '50s. The U.S. Justice Department brought and won a suit of "restraint of trade" (attempt to create a monopoly) against American News.
In 1957 American swiftly went out of business, forcing Atlas publisher Martin Goodwin to switch to rival distributor Independent News, owned by National Periodical Publications — the parent company of DC Comics. Independent restricted Goodman to release no more than eight comics each month. You'll find the "Ind." logo on the covers of 1960s Marvels distributed by Independent.
In 1968, Goodman sold Marvel Comics and his other publishing holdings to Perfect Film & Chemical Corporation. An unusual name for a publisher, yes, but Perfect Film is listed as the publisher of Marvel in indicia of late '68/early '69 comics.
A year later in 1969, Perfect bought magazine distributor Curtis Circulation, and in September of that year, the Curtis Circulation "CC" logo began to appear on Marvel's covers. Freed of its DC-owned distributor, Marvel Comics now had the freedom to dramatically increase its line.
This Marvel Explosion brought the world brand-new titles like Conan the Barbarian, but initially the bulk of added comics were reprint titles utilizing the vast inventory of stories from the 1950s Atlas era: books like Fear, Where Monsters Dwell, and The Mighty Marvel Western. Little remembered today, however, is the small line of early '70s kid-targeted humor reprint comics: titles in the not-so-Marvel tradition like Homer, the Happy Ghost, whose first Marvel Age comic book was released in late 1969.
Panel from Homer, The Happy Ghost #1 (November 1969), script by Stan Lee, art by Dan DeCarlo.
Homer didn't originate in the groovy Sixties or swinging Seventies. He was a ghost child of the 1950s, originally appearing in his own Atlas comic that ran 22 issues from 1955 through 1958. Although sales figures are unknown, it must have been one of Atlas' better sellers: In 1957, it was one of the 16 Atlas comics out of more than 80 that Goodman decided would survive under Independent's distribution restrictions.
Along with Millie the Model, Homer was actually one of the few Atlas characters who had more than one comics series, if for a short time only: Adventures of Homer Ghost ran for two issues in 1957 before getting the ax under the new distribution arrangement. Starring in a pair of series practically makes Homer a Wolverine of his time. His reprint revival in 1969 didn't last nearly as long: four issues through 1970.
Atlas-era Homer. Left: Homer, the Happy Ghost #19 (May 1958), art by Dan DeCarlo. Right: Adventures of Homer Ghost #2 (August 1957), art by Tony DiPreta.
If Homer looks familiar, that's no coincidence: He was created and designed to capitalize on the tremendous success of storybook, movie cartoon, and Harvey Comics' Casper the Friendly Ghost. Take away Homer's trademark freckles and halo and even the Ghostly Trio would be hard put to pick Homer out of a ghost-police lineup of Casper impersonators.
Homer wasn't Casper's only copycat: Charlton Comics debuted "Timmy, the Timid Ghost" in 1956. Casper is the one we remember, however, not the copies: Through his decades-long career of cartoons, movies, and sheer overwhelming number of different Harvey comic book titles, Casper's become an icon of the ages while Homer and Timmy have, typically enough for ghosts, just faded away.
Left: The Friendly Ghost, Casper #11 (July 1959), art by Warren Kremer. Right: Timmy the Timid Ghost #13 (January 1959), art by Pat Masulli and Jon D'Agostino.
Homer has a definite charm, however, due to the partnership of Stan Lee on clever, funny scripts and long-time Archie Comics artist Dan DeCarlo. Homer was less innocent and more mischievous than Casper; his adventures and friends often resembled the little-tough-guy escapades of Dennis the Menace (another character eagerly copied by rival comic companies, including Atlas).
Lee and DeCarlo populated Homer's world with a cast of copyright-testing characters like Gobby the Greedy Goblin, Zelda the Scatter-Brained Witch, and Snappy the Ghost Dog. Homer's roughneck best pal is a virtual carbon copy, complete with hat, of Harvey's "Spooky, the Tuff Little Ghost." He's called "Dugan," a name Lee would use again when he created another derby-hatted tough guy in the pages of the Sgt. Fury comic: "Dum-Dum" Dugan. Although the humor sometimes substitutes clichés for punch lines ("dumb" character Morton the Mixed-Up Ghost can never do anything the right way), there's a good deal of wit and jokes that can still elicit giggles in the 21st century.
The ghost of "Dum-Dum" Dugan? Panels from Homer, The Happy Ghost #1 (November 1969), script by Stan Lee, art by Dan DeCarlo.
Although he's best known for his work at Archie Comics, the importance of DeCarlo to what later became Marvel Comics is substantial.
He got his start at Timely in 1947 penciling the comedy comics Jeanie and My Friend Irma, which became a stylistic groundwork for one of Marvel's oldest original characters, Millie the Model, whose adventures DeCarlo drew for a decade. He's also the co-creator, with Stan Lee, of a comic strip following the adventures of a hapless postman: Willie Lumpkin, whose name Lee eventually re-used as the mailman for the Fantastic Four.
On Homer, DeCarlo's energetic cartoon art brings to life a world where burglars, movie directors, and shop clerks interact with cute ghosts and ghoulies. Even in the simplified shorthand of the physical body language on a witch or ghost, DeCarlo shines: An arched eyebrow, shrugged shoulders, or drooping eyelids tells a story about the characters.
Panels from Homer, The Happy Ghost #1 (November 1969), script by Stan Lee, art by Dan DeCarlo.
Man, dig that striped vest, mohair trousers, and jaunty hat, Stan! He and DeCarlo appear as themselves in one of the highlights of Issue #1 in the four 1970s Homer reprint issues. It's a funny, self-deprecating short gag story — meta before we even used the term — in which the Homer and pals, unhappy with their portrayals in comic books, head to Manhattan to complain to the comic's creators.
Unfortunately, DeCarlo was ill served by the 1970s reprints. Issue #1-4 of the reprint series republishes covers and stories from the 1955 series, but DeCarlo's credits are erased from the reprinted stories — an especially egregious, intentional change in the story that stars him, for example. It's an odd decision, especially at a time when Marvel had made a point of crediting its artists almost from the first while DC was still frequently leaving the creators' identities up to guesswork in the letter columns.
Panels printed in original Homer, The Happy Ghost #18 (March 1958) were reprinted in Homer, The Happy Ghost #1 (November 1959), removing reference to Dan DeCarlo's name.
The reprints even removed DeCarlo's signature from and altered the art of the new covers. Sadly, this isn't even the worst time comics have done wrong to DeCarlo: A lawsuit over the creation of Josie and the Pussycats resulted in DeCarlo's loss of any credit on the characters and Archie then severed their relationship with him. Ah, comics, we love you, but there's so much deceit and trickery in your history.
Left: Original 1950s Homer covers. Right: 1970 reprints altering art and removing Dan DeCarlo's signature.
The revival of Homer, The Happy Ghost ended with its fourth issue, cover-dated May 1970. Marvel's other '70s reprint titles featuring kid-oriented humor from the 1950s were gone by 1974, replaced with titles like Marvel Two-in-One, Ghost Rider, and The Defenders, characters and stories more friendly to the Marvel superhero fan.
Today, not many fans, or even Fans, remember the short return of Homer the Happy Ghost. If there's anything we've seen from Marvel history, however, it's that no character remains in limbo forever. When even the kid-friendly characters of Marvel's 1980s line Star Comics pop up again in an X-Men book, there's hope for everybody. One of these days, I bet we'll see Homer fighting alongside S.H.I.E.L.D. or the Guardians of the Galaxy in one of Marvel's mega-crossover events. And if we don't…well, our comics world is the poorer for it.
Leave a comment below! Even if you're a ghost!
This is great! I remember some of those.


text:
Q: How to find the network interface used by a connected socket How to find the interface used by a connected socket.So that i can set status codes for different interfaces.I used the below code.But I didnt get it.
I've tried two different approaches in the test code below, but both fail. The first one connects to a remote server, and uses ioctl with SIOCGIFNAME, but this fails with 'no such device'. The second one instead uses getsockopt with SO_BINDTODEVICE, but this again fails (it sets the name length to 0).
Any ideas on why these are failing, or how to get the I/F name? after compiling, run the test code as test "a.b.c.d", where a.b.c.d is any IPV4 address which is listening on port 80. Note that I've compiled this on Centos 7, which doesn't appear to have IFNAMSZ in <net/if.h>, so you may have to comment out the #define IFNAMSZ line to get this to compile on other systems.
Thanks.
          #include <stdio.h>
        #include <string.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <sys/ioctl.h>
        #include <net/if.h>
        int main(int argc, char **argv) {
        int sock;
        struct sockaddr_in dst_sin;
        struct in_addr     haddr;
        if(argc != 2)
          return 1;
        if(inet_aton(argv[1], &haddr) == 0) {
          printf("'%s' is not a valid IP address\n", argv[1]);
          return 1;
        }
        dst_sin.sin_family = AF_INET;
        dst_sin.sin_port   = htons(80);
        dst_sin.sin_addr   = haddr;
        if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
           perror("socket");
           return 1;
        }

        if(connect(sock, (struct sockaddr*)&dst_sin, sizeof(dst_sin)) < 0) {
           perror("connect");
           return 1;
        }
        printf("connected to %s:%d\n",
          inet_ntoa(dst_sin.sin_addr), ntohs(dst_sin.sin_port));

        #if 0 // ioctl fails with 'no such device'
        struct ifreq ifr;
        memset(&ifr, 0, sizeof(ifr));

        // get the socket's interface index into ifreq.ifr_ifindex
        if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
           perror("SIOCGIFINDEX");
           return 1;
        }

       // get the I/F name for ifreq.ifr_ifindex
       if(ioctl(sock, SIOCGIFNAME, &ifr) < 0) {
          perror("SIOCGIFNAME");
          return 1;
       }
        printf("I/F is on '%s'\n", ifr.ifr_name);

        #else // only works on Linux 3.8+
        #define IFNAMSZ IFNAMSIZ               // Centos7 bug in if.h??
        char      optval[IFNAMSZ] = {0};
         socklen_t optlen = IFNAMSZ;
         if(getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &optval, &optlen) < 0) {
        perror("getsockopt");
        return 1;
          }
        if(!optlen) {
           printf("invalid optlen\n");
           return 1;
        }
        printf("I/F is on '%s'\n", optval);
        #endif
        close(sock);
        return 0;

A: Idea based on another post

*

*Create socket

*Connect

*Get interface address

*Get interface id and name from interface address

$ gcc -std=gnu11 -Wall so_q_63899229.c
$ ./a.out 93.184.216.34 # example.org
interface index   : 2
interface name    : wlp2s0
interface address : 192.168.1.223
remote    address : 93.184.216.34

so_q_63899229.c
#include <arpa/inet.h>
#include <assert.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>

int sockfd=-1;

void connect2(const char *const dst){

  sockfd=socket(AF_INET,SOCK_STREAM,0);
  assert(sockfd>=3);

  struct sockaddr_in sin={
    .sin_family=AF_INET,
    .sin_port=htons(80),
    .sin_addr={}
  };
  assert(1==inet_pton(AF_INET,dst,&(sin.sin_addr)));

  assert(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in)));

}

void getsockname2(struct sockaddr_in *const sin){
  socklen_t addrlen=sizeof(struct sockaddr_in);
  assert(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
  assert(addrlen==sizeof(struct sockaddr_in));
}

void disconnect(){
  close(sockfd);
  sockfd=-1;
}

void addr2iface_ifconf(const struct in_addr *const sin_addr,int *const index,char *const name){

  struct ifconf ifc={
    .ifc_len=0,
    .ifc_req=NULL
  };

  int ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  assert(ioctlfd>=3);
  assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));

  const int sz=ifc.ifc_len;
  assert(sz%sizeof(struct ifreq)==0);
  const int n=sz/sizeof(struct ifreq);

  char buf[sz];
  bzero(buf,sz);
  ifc.ifc_buf=buf;
  assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
  assert(
    ifc.ifc_len==sz &&
    (char*)ifc.ifc_req==buf
  );

  for(int i=0;i<n;++i)if(0==memcmp(
    &(((struct sockaddr_in*)(&(ifc.ifc_req[i].ifr_addr)))->sin_addr),
    sin_addr,
    sizeof(struct in_addr)
  )){
    *index=ifc.ifc_req[i].ifr_ifindex;
    assert(name==strncpy(name,ifc.ifc_req[i].ifr_name,IFNAMSIZ));
    return;
  }

  assert(0);

}

int main(int argc,const char *argv[]){

  assert(argc==2);
  assert(argv[1]&&strlen(argv[1]));
  const char *const remoteaddr_s=argv[1];
  // const char *const remoteaddr_s="93.184.216.34";

  connect2(remoteaddr_s);

  struct sockaddr_in ifaddr={};
  getsockname2(&ifaddr);

  disconnect();

  int index=0;
  char ifname[IFNAMSIZ]={};
  addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);

  char ifaddr_s[INET_ADDRSTRLEN]={};
  assert(ifaddr_s==inet_ntop(AF_INET,&(ifaddr.sin_addr),ifaddr_s,INET_ADDRSTRLEN));

  printf("interface index   : %d\n",index);
  printf("interface name    : %s\n",ifname);
  printf("interface address : %s\n",ifaddr_s);
  printf("remote    address : %s\n",remoteaddr_s);
  // printf("#%d %s %s -> %s\n",
  //   index,
  //   ifname,
  //   ifaddr_s,
  //   remoteaddr_s
  // );

  return 0;

}

Also there doesn't seem to be an identifier named IFNAMSZ. IFNAMSIZ defined in <net/if.h> should be the maxinum legth (including '\0') allowed for the name of any interface IMHO.

redpajama_set_name: RedPajamaStackExchange


text:
#pragma once

#include "generated/CPACSEnginePosition.h"
#include "CTiglRelativelyPositionedComponent.h"

namespace tigl {

class CCPACSEnginePosition : public generated::CPACSEnginePosition, public CTiglRelativelyPositionedComponent
{
public:
    TIGL_EXPORT CCPACSEnginePosition(CCPACSEnginePositions* parent, CTiglUIDManager* uidMgr);

    TIGL_EXPORT std::string GetDefaultedUID() const override;

    TIGL_EXPORT TiglGeometricComponentType GetComponentType() const override { return TIGL_COMPONENT_ENGINE_NACELLE; }
    TIGL_EXPORT TiglGeometricComponentIntent GetComponentIntent() const override { return TIGL_INTENT_PHYSICAL; }

    // Override setters for invalidation
    TIGL_EXPORT void SetSymmetryAxis(const TiglSymmetryAxis& axis) override;
    TIGL_EXPORT void SetTransformation(const CCPACSTransformation& transform) override;
    TIGL_EXPORT void SetSymmetry(const boost::optional<TiglSymmetryAxis>& value) override;
    TIGL_EXPORT void SetEngineUID(const std::string& value) override;

protected:
    virtual PNamedShape BuildLoft() const override;

private:
    void InvalidateImpl(const boost::optional<std::string>& source) const override;

};

} // namespace tigl